revolver

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

commit 79e2c5d6ed704a7e372d24ff7f3978b65ce1e203
parent 8adebc64dcbd0735c27fd4f392a3ec0d81b884ee
Author: Samdal <samdal@protonmail.com>
Date:   Thu, 27 Mar 2025 15:14:05 +0100

idraw2d index buffer

Diffstat:
Mexamples/simple_texture.c | 4++--
Msrc/render/impl/opengl.c | 4++--
Msrc/render/render.h | 4++--
Msrc/util/util_bump_cache.c | 40++++++++++++++++++++++------------------
Msrc/util/util_bump_cache.h | 7++++---
Msrc/util/util_idraw2d.c | 80++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------
Msrc/util/util_idraw2d.h | 4++--
7 files changed, 95 insertions(+), 48 deletions(-)

diff --git a/examples/simple_texture.c b/examples/simple_texture.c @@ -20,8 +20,8 @@ f32 v_data[] = { // Index data for quad uint32_t i_data[] = { - 0, 3, 2, // First Triangle - 0, 1, 3 // Second Triangle + 0, 1, 2, // First Triangle + 1, 2, 3 // Second Triangle }; rv_str8 v_src = S("#version 330 core\n" rv_strify( diff --git a/src/render/impl/opengl.c b/src/render/impl/opengl.c @@ -686,9 +686,9 @@ RV_INTERNAL void ogl_handle_command(rv_command_t* c) { case 1: itype = GL_UNSIGNED_BYTE; break; } if (c->draw.instances) { - glDrawElementsInstanced(prim, c->draw.count, itype, (void*)(s64)c->draw.first, c->draw.instances); + glDrawElementsInstanced(prim, c->draw.count, itype, (void*)(c->draw.first * ogl_ctx.bound_ibo->elem_size), c->draw.instances); } else { - glDrawElements(prim, c->draw.count, itype, (void*)(s64)c->draw.first); + glDrawElements(prim, c->draw.count, itype, (void*)(c->draw.first * ogl_ctx.bound_ibo->elem_size)); } } else { if (c->draw.instances) { diff --git a/src/render/render.h b/src/render/render.h @@ -29,8 +29,8 @@ typedef enum { } rv_texture_wrap_t; typedef enum { - RV_TEXTURE_FILTER_LINEAR, RV_TEXTURE_FILTER_NEAREST, + RV_TEXTURE_FILTER_LINEAR, } rv_texture_filter_t; typedef struct { @@ -328,7 +328,7 @@ struct rv_command_t { } obj; struct { rv_primitive_type_t primitive; - s32 first; + s64 first; // first index s64 count; s64 instances; } draw; diff --git a/src/util/util_bump_cache.c b/src/util/util_bump_cache.c @@ -8,39 +8,43 @@ RV_GLOBAL void rv_bump_cache_create(rv_bump_cache_ctx_t* bc, s64 element_size) // TODO(Samdal): // Check if the arena implementation supports virtual paging first... - bc->bump_arena = rv_arena_alloc(.flags = rv_arena_flag_no_chain, .reserve_size = GB(1)); + bc->arena = rv_arena_alloc(.flags = rv_arena_flag_no_chain, .reserve_size = GB(1)); } RV_GLOBAL void rv_bump_cache_destroy(rv_bump_cache_ctx_t* bc) { - if (bc->bump_arena) { - rv_arena_release(bc->bump_arena); + if (bc->arena) { + rv_arena_release(bc->arena); } *bc = (rv_bump_cache_ctx_t){0}; } RV_GLOBAL void* rv_bump_cache_push(rv_bump_cache_ctx_t* bc, const void* new) { + return rv_bump_cache_push_many(bc, new, 1); +} +RV_GLOBAL void* rv_bump_cache_push_many(rv_bump_cache_ctx_t* bc, const void* new, s64 count) +{ rv_assert(bc->element_size > 0); - void* res = rv_arena_push(bc->bump_arena, bc->element_size, 1); - rv_mem_copy(res, new, bc->element_size); + void* res = rv_arena_push(bc->arena, bc->element_size * count, 1); + rv_mem_copy(res, new, bc->element_size * count); - if (!bc->bump_begin) { - bc->bump_begin = res; - rv_assert(bc->bump_total_size == 0); + if (!bc->begin) { + bc->begin = res; + rv_assert(bc->total_count == 0); rv_assert(bc->committed_so_far == 0); } - bc->current_count += 1; - bc->bump_total_size += bc->element_size; + bc->current_count += count; + bc->total_count += count; return res; } RV_GLOBAL void rv_bump_cache_break(rv_bump_cache_ctx_t* bc, s64* offset_out, s64* count_out) { - *offset_out = bc->committed_so_far; - *count_out = bc->current_count; + if (offset_out) *offset_out = bc->committed_so_far; + if (count_out) *count_out = bc->current_count; rv_command_t res = {0}; @@ -52,14 +56,14 @@ RV_GLOBAL void rv_bump_cache_break(rv_bump_cache_ctx_t* bc, s64* offset_out, s64 RV_GLOBAL void rv_bump_cache_upload_and_reset(rv_bump_cache_ctx_t* bc, rv_arena* arena, void** data_out, s64* size_out) { // copy over data into new arena - *data_out = rv_arena_push(arena, bc->bump_total_size, 8); - rv_mem_copy(*data_out, bc->bump_begin, bc->bump_total_size); - *size_out = bc->bump_total_size; + *data_out = rv_arena_push(arena, bc->total_count * bc->element_size, 8); + rv_mem_copy(*data_out, bc->begin, bc->total_count * bc->element_size); + *size_out = bc->total_count * bc->element_size; // reset - rv_arena_clear(bc->bump_arena); - bc->bump_begin = NULL; + rv_arena_clear(bc->arena); + bc->begin = NULL; bc->current_count = 0; bc->committed_so_far = 0; - bc->bump_total_size = 0; + bc->total_count = 0; } diff --git a/src/util/util_bump_cache.h b/src/util/util_bump_cache.h @@ -4,21 +4,22 @@ typedef struct { // initialization s64 element_size; - rv_arena* bump_arena; + rv_arena* arena; // construction s64 current_count; s64 committed_so_far; // upload - void* bump_begin; - s64 bump_total_size; + void* begin; + s64 total_count; } rv_bump_cache_ctx_t; RV_GLOBAL void rv_bump_cache_create(rv_bump_cache_ctx_t* bc, s64 element_size); RV_GLOBAL void rv_bump_cache_destroy(rv_bump_cache_ctx_t* bc); RV_GLOBAL void* rv_bump_cache_push(rv_bump_cache_ctx_t* bc, const void* new); +RV_GLOBAL void* rv_bump_cache_push_many(rv_bump_cache_ctx_t* bc, const void* new, s64 count); RV_GLOBAL void rv_bump_cache_break(rv_bump_cache_ctx_t* bc, s64* offset_out, s64* count_out); // returns draw command with filled data diff --git a/src/util/util_idraw2d.c b/src/util/util_idraw2d.c @@ -57,6 +57,7 @@ RV_GLOBAL void rvi2d_create(rv_idraw2d_ctx* ctx, rv_arena* arena, rv_command_lis // make render objects ctx->vbo = rv_push_compound(ctx->permanent_arena, rv_vbo_t, {.usage = RV_BUFFER_USAGE_DYNAMIC}); + ctx->ibo = rv_push_compound(ctx->permanent_arena, rv_ibo_t, {.usage = RV_BUFFER_USAGE_DYNAMIC, .elem_size = sizeof(u32)}); rv_shader_t* vert = rv_push_compound(ctx->permanent_arena, rv_shader_t, {.source = rv_idraw2d_v_src, .type = RV_SHADER_TYPE_VERTEX}); rv_shader_t* frag = rv_push_compound(ctx->permanent_arena, rv_shader_t, {.source = rv_idraw2d_f_src, .type = RV_SHADER_TYPE_FRAGMENT}); ctx->pip = rv_push(ctx->permanent_arena, rv_pipeline_t); @@ -73,17 +74,23 @@ RV_GLOBAL void rvi2d_create(rv_idraw2d_ctx* ctx, rv_arena* arena, rv_command_lis // add creation commands rv_cmd_push_obj(arena, create_commands, RV_COMMAND_OBJ_VERTEX, RV_RENDER_OBJ_OP_CREATE, ctx->vbo); + rv_cmd_push_obj(arena, create_commands, RV_COMMAND_OBJ_INDEX, RV_RENDER_OBJ_OP_CREATE, ctx->ibo); rv_cmd_push_obj(arena, create_commands, RV_COMMAND_OBJ_SHADER, RV_RENDER_OBJ_OP_CREATE, vert); rv_cmd_push_obj(arena, create_commands, RV_COMMAND_OBJ_SHADER, RV_RENDER_OBJ_OP_CREATE, frag); rv_cmd_push_obj(arena, create_commands, RV_COMMAND_OBJ_PIPELINE, RV_RENDER_OBJ_OP_CREATE, ctx->pip); rv_cmd_push_obj(arena, create_commands, RV_COMMAND_OBJ_SHADER, RV_RENDER_OBJ_OP_DESTROY, frag); // don't need anymore rv_cmd_push_obj(arena, create_commands, RV_COMMAND_OBJ_SHADER, RV_RENDER_OBJ_OP_DESTROY, vert); // don't need anymore - rv_cmd_push_obj(arena, create_commands, RV_COMMAND_OBJ_PIPELINE, RV_RENDER_OBJ_OP_BIND, ctx->pip); - rv_cmd_push_uniform_update(arena, create_commands, ctx->u_omit_tex, {.v_f32 = 1.0f}); - rv_cmd_push_uniform_update(arena, create_commands, ctx->u_resolution, {.v_vec2 = rv_v2(1,1)}); - rv_cmd_push_obj(arena, create_commands, RV_COMMAND_OBJ_PIPELINE, RV_RENDER_OBJ_OP_BIND, NULL); + { // set default uniforms + rv_cmd_push_obj(arena, create_commands, RV_COMMAND_OBJ_PIPELINE, RV_RENDER_OBJ_OP_BIND, ctx->pip); + rv_cmd_push_uniform_update(arena, create_commands, ctx->u_omit_tex, {.v_f32 = 1.0f}); + ctx->u_omit_tex_last = 1.0f; + rv_cmd_push_uniform_update(arena, create_commands, ctx->u_resolution, {.v_vec2 = rv_v2(1,1)}); + ctx->u_resolution_last = rv_v2(1,1); + rv_cmd_push_obj(arena, create_commands, RV_COMMAND_OBJ_PIPELINE, RV_RENDER_OBJ_OP_BIND, NULL); + } rv_bump_cache_create(&ctx->vertex, sizeof(rv_vec2) + sizeof(rv_vec2) + sizeof(rv_vec4)); + rv_bump_cache_create(&ctx->index, sizeof(u32)); ctx->default_binds = rv_push(ctx->permanent_arena, rv_command_list_node_t); rv_cmd_push_obj(ctx->permanent_arena, &ctx->default_binds->commands, RV_COMMAND_OBJ_PIPELINE, RV_RENDER_OBJ_OP_BIND, ctx->pip); @@ -101,11 +108,13 @@ RV_GLOBAL void rvi2d_destroy(rv_idraw2d_ctx* ctx, rv_arena* arena, rv_command_li rv_pipeline_t* pip_copy = rv_push_copy(arena, rv_pipeline_t, ctx->ibo); rv_cmd_push_obj(arena, destroy_commands, RV_COMMAND_OBJ_VERTEX, RV_RENDER_OBJ_OP_DESTROY, vbo_vertex_copy); + rv_cmd_push_obj(arena, destroy_commands, RV_COMMAND_OBJ_INDEX, RV_RENDER_OBJ_OP_DESTROY, ibo_copy); rv_cmd_push_obj(arena, destroy_commands, RV_COMMAND_OBJ_PIPELINE, RV_RENDER_OBJ_OP_DESTROY, pip_copy); rv_arena_release(ctx->arena); rv_arena_release(ctx->permanent_arena); rv_bump_cache_destroy(&ctx->vertex); + rv_bump_cache_destroy(&ctx->index); *ctx = (rv_idraw2d_ctx){0}; } @@ -118,13 +127,22 @@ RV_GLOBAL rv_command_t* rvi2d_draw_and_reset(rv_idraw2d_ctx* ctx, rv_arena* aren { rv_command_t* res = rvi2d_break(ctx); - rv_command_t update_cmd = rv_cmd_obj(RV_COMMAND_OBJ_VERTEX, RV_RENDER_OBJ_OP_UPDATE, ctx->vbo); + { // update vbo + rv_command_t update_vbo_cmd = rv_cmd_obj(RV_COMMAND_OBJ_VERTEX, RV_RENDER_OBJ_OP_UPDATE, ctx->vbo); + rv_bump_cache_upload_and_reset(&ctx->vertex, arena, &update_vbo_cmd.obj.vbo_update.data, &update_vbo_cmd.obj.vbo_update.size); + rv_cmd_push_copy(arena, render_commands, update_vbo_cmd); + } - rv_bump_cache_upload_and_reset(&ctx->vertex, arena, &update_cmd.obj.vbo_update.data, &update_cmd.obj.vbo_update.size); - rv_cmd_push_copy(arena, render_commands, update_cmd); + { // update ibo + rv_command_t update_ibo_cmd = rv_cmd_obj(RV_COMMAND_OBJ_INDEX, RV_RENDER_OBJ_OP_UPDATE, ctx->ibo); + rv_bump_cache_upload_and_reset(&ctx->index, arena, &update_ibo_cmd.obj.ibo_update.data, &update_ibo_cmd.obj.ibo_update.size); + rv_cmd_push_copy(arena, render_commands, update_ibo_cmd); + } + // push draw commands rv_render_copy_commands(arena, render_commands, &ctx->commands); + // check that custom binds steck is where it started if (ctx->custom_binds_stack->next) { rv_unreachable(); ctx->custom_binds_stack = NULL; @@ -148,8 +166,9 @@ RV_GLOBAL rv_command_t* rvi2d_break(rv_idraw2d_ctx* ctx) if (ctx->last_bind != ctx->custom_binds_stack) { rv_render_copy_commands(ctx->arena, &ctx->commands, &ctx->custom_binds_stack->commands); - // force rebind vbo + // force rebind vbo and ibo rv_cmd_push_obj(ctx->arena, &ctx->commands, RV_COMMAND_OBJ_VERTEX, RV_RENDER_OBJ_OP_BIND, ctx->vbo); + rv_cmd_push_obj(ctx->arena, &ctx->commands, RV_COMMAND_OBJ_INDEX, RV_RENDER_OBJ_OP_BIND, ctx->ibo); // force update all uniforms rv_cmd_push_uniform_update(ctx->arena, &ctx->commands, ctx->u_resolution, {.v_vec2 = ctx->u_resolution_last}); rv_cmd_push_uniform_update(ctx->arena, &ctx->commands, ctx->u_tex, {.v_tex = ctx->u_tex_last}); @@ -159,9 +178,10 @@ RV_GLOBAL rv_command_t* rvi2d_break(rv_idraw2d_ctx* ctx) } s64 first, count; - rv_bump_cache_break(&ctx->vertex, &first, &count); + rv_bump_cache_break(&ctx->vertex, NULL, NULL); + rv_bump_cache_break(&ctx->index, &first, &count); - if (count > 0 ) { + if (count > 0) { rv_command_t draw_cmd = { .type = RV_COMMAND_DRAW, .draw = { @@ -209,7 +229,7 @@ RV_GLOBAL rv_command_t* rvi2d_tex_ex(rv_idraw2d_ctx* ctx, rv_texture_t* tex, boo if (tex) { rv_cmd_push_uniform_update(ctx->arena, &ctx->commands, ctx->u_omit_tex, {.v_f32 = is_red_channel ? -1.0f : 0.0f}); - ctx->u_omit_tex_last = 0.0f; + ctx->u_omit_tex_last = is_red_channel ? -1.0f : 0.0f; } else { rv_cmd_push_uniform_update(ctx->arena, &ctx->commands, ctx->u_omit_tex, {.v_f32 = 1.0f}); ctx->u_omit_tex_last = 1.0f; @@ -251,9 +271,11 @@ RV_GLOBAL rv_command_t* rvi2d_custom_binds_pop(rv_idraw2d_ctx* ctx) RV_GLOBAL void rvi2d_triangle(rv_idraw2d_ctx* ctx, rv_vec2 pos_a, rv_vec2 pos_b, rv_vec2 pos_c, - rv_vec2 uv_a, rv_vec2 uv_b, rv_vec2 uv_c, + rv_vec2 uv_a, rv_vec2 uv_b, rv_vec2 uv_c, rv_color_t color) { + u32 last_index = ctx->vertex.total_count; + rv_vec4 c = rv_vec4_from_color(color); struct { rv_vec2 pos, uv; @@ -263,9 +285,10 @@ RV_GLOBAL void rvi2d_triangle(rv_idraw2d_ctx* ctx, {.pos = pos_b, .uv = uv_b, .color = c}, {.pos = pos_c, .uv = uv_c, .color = c}, }; - rv_bump_cache_push(&ctx->vertex, &copy_from[0]); - rv_bump_cache_push(&ctx->vertex, &copy_from[1]); - rv_bump_cache_push(&ctx->vertex, &copy_from[2]); + rv_bump_cache_push_many(&ctx->vertex, &copy_from, 3); + + u32 indices[3] = {last_index + 0, last_index + 1, last_index + 2}; + rv_bump_cache_push_many(&ctx->index, &indices, 3); } RV_GLOBAL void rvi2d_quad(rv_idraw2d_ctx* ctx, @@ -273,10 +296,29 @@ RV_GLOBAL void rvi2d_quad(rv_idraw2d_ctx* ctx, rv_vec2 uv_tl, rv_vec2 uv_tr, rv_vec2 uv_bl, rv_vec2 uv_br, rv_color_t color) { - rvi2d_triangle(ctx, pos_tl, pos_tr, pos_bl, - uv_tl, uv_tr, uv_bl, color); - rvi2d_triangle(ctx, pos_tr, pos_bl, pos_br, - uv_tr, uv_bl, uv_br, color); + u32 index_begin = ctx->vertex.total_count; + + rv_vec4 c = rv_vec4_from_color(color); + struct { + rv_vec2 pos, uv; + rv_vec4 color; + } copy_from[4] = { + {.pos = pos_tl, .uv = uv_tl, .color = c}, + {.pos = pos_tr, .uv = uv_tr, .color = c}, + {.pos = pos_bl, .uv = uv_bl, .color = c}, + {.pos = pos_br, .uv = uv_br, .color = c}, + }; + rv_bump_cache_push_many(&ctx->vertex, &copy_from, 4); + + u32 indices[6] = { + index_begin + 0, // tl +--+ + index_begin + 1, // tr | / + index_begin + 2, // bl +/ + index_begin + 1, // tr /+ + index_begin + 2, // bl / | + index_begin + 3, // br +--+ + }; + rv_bump_cache_push_many(&ctx->index, &indices, 6); } ////////////////////////////////////////////////////////////////// diff --git a/src/util/util_idraw2d.h b/src/util/util_idraw2d.h @@ -2,7 +2,6 @@ // util_idraw2d.h // // TODO(Samdal): -// Use an index buffer (?) // Implement line drawing // Implement circle drawing @@ -29,6 +28,7 @@ typedef struct { // state rv_bump_cache_ctx_t vertex; + rv_bump_cache_ctx_t index; rv_command_list_t commands; rv_command_t* last_commited_command; rv_texture_t* last_tex; @@ -72,7 +72,7 @@ RV_GLOBAL rv_command_t* rvi2d_custom_binds_push(rv_idraw2d_ctx* ctx, rv_command_ RV_GLOBAL rv_command_t* rvi2d_custom_binds_pop(rv_idraw2d_ctx* ctx); RV_GLOBAL void rvi2d_triangle(rv_idraw2d_ctx* ctx, rv_vec2 pos_a, rv_vec2 pos_b, rv_vec2 pos_c, - rv_vec2 uv_a, rv_vec2 uv_b, rv_vec2 uv_c, + rv_vec2 uv_a, rv_vec2 uv_b, rv_vec2 uv_c, rv_color_t color); RV_GLOBAL void rvi2d_quad(rv_idraw2d_ctx* ctx, rv_vec2 pos_tl, rv_vec2 pos_tr, rv_vec2 pos_bl, rv_vec2 pos_br,