diff options
| author | Andre Weissflog <floooh@gmail.com> | 2024-08-26 14:32:25 +0200 |
|---|---|---|
| committer | Andre Weissflog <floooh@gmail.com> | 2024-08-26 14:32:25 +0200 |
| commit | 7b68f8b5758e21cda3301617ffa5f81efc001d9c (patch) | |
| tree | b92f4c503db135e0784aee50882b3a18582a2ac1 /util | |
| parent | 3c9719dfe3bd4f4cf7faeaf6947ddbcd9eb6f5ff (diff) | |
sokol_gl.h: don't skip rendering completely in case of errors, plus:
- more detailed error tracking
- two new functions to query number of recorded vertices and commands
Diffstat (limited to 'util')
| -rw-r--r-- | util/sokol_gl.h | 140 |
1 files changed, 105 insertions, 35 deletions
diff --git a/util/sokol_gl.h b/util/sokol_gl.h index 15b38808..654cb0f6 100644 --- a/util/sokol_gl.h +++ b/util/sokol_gl.h @@ -372,8 +372,8 @@ the last call to sgl_draw() through sokol-gfx, and will 'rewind' the internal vertex-, uniform- and command-buffers. - --- each sokol-gl context tracks an internal error code, to query the - current error code for the currently active context call: + --- each sokol-gl context tracks internal error states which can + be obtains via: sgl_error_t sgl_error() @@ -381,18 +381,28 @@ sgl_error_t sgl_context_error(ctx); - ...which can return the following error codes: + ...this returns a struct with the following booleans: - SGL_NO_ERROR - all OK, no error occurred since last sgl_draw() - SGL_ERROR_VERTICES_FULL - internal vertex buffer is full (checked in sgl_end()) - SGL_ERROR_UNIFORMS_FULL - the internal uniforms buffer is full (checked in sgl_end()) - SGL_ERROR_COMMANDS_FULL - the internal command buffer is full (checked in sgl_end()) - SGL_ERROR_STACK_OVERFLOW - matrix- or pipeline-stack overflow - SGL_ERROR_STACK_UNDERFLOW - matrix- or pipeline-stack underflow - SGL_ERROR_NO_CONTEXT - the active context no longer exists + .any - true if any of the below errors is true + .vertices_full - internal vertex buffer is full (checked in sgl_end()) + .uniforms_full - the internal uniforms buffer is full (checked in sgl_end()) + .commands_full - the internal command buffer is full (checked in sgl_end()) + .stack_overflow - matrix- or pipeline-stack overflow + .stack_underflow - matrix- or pipeline-stack underflow + .no_context - the active context no longer exists - ...if sokol-gl is in an error-state, sgl_draw() will skip any rendering, - and reset the error code to SGL_NO_ERROR. + ...depending on the above error state, sgl_draw() may skip rendering + completely, or only draw partial geometry + + --- you can get the number of recorded vertices and draw commands in the current + frame and active sokol-gl context via: + + int sgl_num_vertices() + int sgl_num_commands() + + ...this allows you to check whether the vertex or command pools are running + full before the overflow actually happens (in this case you could also + check the error booleans in the result of sgl_error()). RENDER LAYERS ============= @@ -762,14 +772,14 @@ typedef struct sgl_context { uint32_t id; } sgl_context; Errors are reset each frame after calling sgl_draw(), get the last error code with sgl_error() */ -typedef enum sgl_error_t { - SGL_NO_ERROR = 0, - SGL_ERROR_VERTICES_FULL, - SGL_ERROR_UNIFORMS_FULL, - SGL_ERROR_COMMANDS_FULL, - SGL_ERROR_STACK_OVERFLOW, - SGL_ERROR_STACK_UNDERFLOW, - SGL_ERROR_NO_CONTEXT, +typedef struct sgl_error_t { + bool any; + bool vertices_full; + bool uniforms_full; + bool commands_full; + bool stack_overflow; + bool stack_underflow; + bool no_context; } sgl_error_t; /* @@ -832,6 +842,10 @@ SOKOL_GL_API_DECL void sgl_set_context(sgl_context ctx); SOKOL_GL_API_DECL sgl_context sgl_get_context(void); SOKOL_GL_API_DECL sgl_context sgl_default_context(void); +/* get information about recorded vertices and commands in current context */ +SOKOL_GL_API_DECL int sgl_num_vertices(void); +SOKOL_GL_API_DECL int sgl_num_commands(void); + /* draw recorded commands (call inside a sokol-gfx render pass) */ SOKOL_GL_API_DECL void sgl_draw(void); SOKOL_GL_API_DECL void sgl_context_draw(sgl_context ctx); @@ -2342,7 +2356,7 @@ typedef struct { /* state tracking */ int base_vertex; - int vtx_count; /* number of times vtx function has been called, used for non-triangle primitives */ + int quad_vtx_count; /* number of times vtx function has been called, used for non-triangle primitives */ sgl_error_t error; bool in_begin; int layer_id; @@ -2903,10 +2917,24 @@ static void _sgl_destroy_context(sgl_context ctx_id) { // ██ ██ ██ ███████ ██████ // // >>misc + +static sgl_error_t _sgl_error_defaults(void) { + sgl_error_t defaults = {0}; + return defaults; +} + +static int _sgl_num_vertices(_sgl_context_t* ctx) { + return ctx->vertices.next; +} + +static int _sgl_num_commands(_sgl_context_t* ctx) { + return ctx->commands.next; +} + static void _sgl_begin(_sgl_context_t* ctx, _sgl_primitive_type_t mode) { ctx->in_begin = true; ctx->base_vertex = ctx->vertices.next; - ctx->vtx_count = 0; + ctx->quad_vtx_count = 0; ctx->cur_prim_type = mode; } @@ -2916,7 +2944,7 @@ static void _sgl_rewind(_sgl_context_t* ctx) { ctx->uniforms.next = 0; ctx->commands.next = 0; ctx->base_vertex = 0; - ctx->error = SGL_NO_ERROR; + ctx->error = _sgl_error_defaults(); ctx->layer_id = 0; ctx->matrix_dirty = true; } @@ -2938,7 +2966,8 @@ static _sgl_vertex_t* _sgl_next_vertex(_sgl_context_t* ctx) { if (ctx->vertices.next < ctx->vertices.cap) { return &ctx->vertices.ptr[ctx->vertices.next++]; } else { - ctx->error = SGL_ERROR_VERTICES_FULL; + ctx->error.vertices_full = true; + ctx->error.any = true; return 0; } } @@ -2947,7 +2976,8 @@ static _sgl_uniform_t* _sgl_next_uniform(_sgl_context_t* ctx) { if (ctx->uniforms.next < ctx->uniforms.cap) { return &ctx->uniforms.ptr[ctx->uniforms.next++]; } else { - ctx->error = SGL_ERROR_UNIFORMS_FULL; + ctx->error.uniforms_full = true; + ctx->error.any = true; return 0; } } @@ -2964,7 +2994,8 @@ static _sgl_command_t* _sgl_next_command(_sgl_context_t* ctx) { if (ctx->commands.next < ctx->commands.cap) { return &ctx->commands.ptr[ctx->commands.next++]; } else { - ctx->error = SGL_ERROR_COMMANDS_FULL; + ctx->error.commands_full = true; + ctx->error.any = true; return 0; } } @@ -2991,7 +3022,7 @@ static void _sgl_vtx(_sgl_context_t* ctx, float x, float y, float z, float u, fl SOKOL_ASSERT(ctx->in_begin); _sgl_vertex_t* vtx; /* handle non-native primitive types */ - if ((ctx->cur_prim_type == SGL_PRIMITIVETYPE_QUADS) && ((ctx->vtx_count & 3) == 3)) { + if ((ctx->cur_prim_type == SGL_PRIMITIVETYPE_QUADS) && ((ctx->quad_vtx_count & 3) == 3)) { /* for quads, before writing the last quad vertex, reuse the first and third vertex to start the second triangle in the quad */ @@ -3007,7 +3038,7 @@ static void _sgl_vtx(_sgl_context_t* ctx, float x, float y, float z, float u, fl vtx->rgba = rgba; vtx->psize = ctx->point_size; } - ctx->vtx_count++; + ctx->quad_vtx_count++; } static void _sgl_identity(_sgl_matrix_t* m) { @@ -3342,7 +3373,7 @@ static bool _sgl_is_default_context(sgl_context ctx_id) { static void _sgl_draw(_sgl_context_t* ctx, int layer_id) { SOKOL_ASSERT(ctx); - if ((ctx->error == SGL_NO_ERROR) && (ctx->vertices.next > 0) && (ctx->commands.next > 0)) { + if ((ctx->vertices.next > 0) && (ctx->commands.next > 0)) { sg_push_debug_group("sokol-gl"); uint32_t cur_pip_id = SG_INVALID_ID; @@ -3356,6 +3387,8 @@ static void _sgl_draw(_sgl_context_t* ctx, int layer_id) { sg_update_buffer(ctx->vbuf, &range); } + // render all successfully recorded commands (this may be less than the + // issued commands if we're in an error state) for (int i = 0; i < ctx->commands.next; i++) { const _sgl_command_t* cmd = &ctx->commands.ptr[i]; if (cmd->layer_id != layer_id) { @@ -3463,7 +3496,10 @@ SOKOL_API_IMPL sgl_error_t sgl_error(void) { if (ctx) { return ctx->error; } else { - return SGL_ERROR_NO_CONTEXT; + sgl_error_t err = _sgl_error_defaults(); + err.no_context = true; + err.any = true; + return err; } } @@ -3472,7 +3508,10 @@ SOKOL_API_IMPL sgl_error_t sgl_context_error(sgl_context ctx_id) { if (ctx) { return ctx->error; } else { - return SGL_ERROR_NO_CONTEXT; + sgl_error_t err = _sgl_error_defaults(); + err.no_context = true; + err.any = true; + return err; } } @@ -3521,6 +3560,26 @@ SOKOL_API_IMPL sgl_context sgl_default_context(void) { return SGL_DEFAULT_CONTEXT; } +SOKOL_API_IMPL int sgl_num_vertices(void) { + SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie); + _sgl_context_t* ctx = _sgl.cur_ctx; + if (ctx) { + return _sgl_num_vertices(ctx); + } else { + return 0; + } +} + +SOKOL_API_IMPL int sgl_num_commands(void) { + SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie); + _sgl_context_t* ctx = _sgl.cur_ctx; + if (ctx) { + return _sgl_num_commands(ctx); + } else { + return 0; + } +} + SOKOL_API_IMPL sgl_pipeline sgl_make_pipeline(const sg_pipeline_desc* desc) { SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie); _sgl_context_t* ctx = _sgl.cur_ctx; @@ -3576,7 +3635,8 @@ SOKOL_API_IMPL void sgl_push_pipeline(void) { ctx->pip_tos++; ctx->pip_stack[ctx->pip_tos] = ctx->pip_stack[ctx->pip_tos-1]; } else { - ctx->error = SGL_ERROR_STACK_OVERFLOW; + ctx->error.stack_overflow = true; + ctx->error.any = true; } } @@ -3589,7 +3649,8 @@ SOKOL_API_IMPL void sgl_pop_pipeline(void) { if (ctx->pip_tos > 0) { ctx->pip_tos--; } else { - ctx->error = SGL_ERROR_STACK_UNDERFLOW; + ctx->error.stack_underflow = true; + ctx->error.any = true; } } @@ -3778,6 +3839,7 @@ SOKOL_API_IMPL void sgl_end(void) { SOKOL_ASSERT(ctx->in_begin); SOKOL_ASSERT(ctx->vertices.next >= ctx->base_vertex); ctx->in_begin = false; + bool matrix_dirty = ctx->matrix_dirty; if (matrix_dirty) { ctx->matrix_dirty = false; @@ -3787,6 +3849,12 @@ SOKOL_API_IMPL void sgl_end(void) { uni->tm = *_sgl_matrix_texture(ctx); } } + + // don't record any new commands when we're in an error state + if (ctx->error.any) { + return; + } + // check if command can be merged with current command sg_pipeline pip = _sgl_get_pipeline(ctx->pip_stack[ctx->pip_tos], ctx->cur_prim_type); sg_image img = ctx->texturing_enabled ? ctx->cur_img : _sgl.def_img; @@ -4205,7 +4273,8 @@ SOKOL_GL_API_DECL void sgl_push_matrix(void) { _sgl_matrix_t* dst = _sgl_matrix(ctx); *dst = *src; } else { - ctx->error = SGL_ERROR_STACK_OVERFLOW; + ctx->error.stack_overflow = true; + ctx->error.any = true; } } @@ -4220,7 +4289,8 @@ SOKOL_GL_API_DECL void sgl_pop_matrix(void) { if (ctx->matrix_tos[ctx->cur_matrix_mode] > 0) { ctx->matrix_tos[ctx->cur_matrix_mode]--; } else { - ctx->error = SGL_ERROR_STACK_UNDERFLOW; + ctx->error.stack_underflow = true; + ctx->error.any = true; } } |