a-game

2D platformer written from scratch.
git clone git://git.amin.space/a-game.git
Log | Files | Refs | README | LICENSE

commit c39c262c868d24698f5a6a7c26e41610f947b60a
parent bd88d22d902bd6e582766d4b5681a4e7a9386e82
Author: amin <dev@aminmesbah.com>
Date:   Mon, 10 Jun 2019 03:04:27 +0000

Sort render job queue based on layer

I'm very suspicious at how this seems to be working upon the very first
compile.

FossilOrigin-Name: 3fe01d1b137585327cba2f5cb176b2e2b6fd9c677a3b36cf3255f818b18ab5bb
Diffstat:
Msrc/game.c | 47++++++++++++++++++++++++++---------------------
Msrc/memory.c | 6++++++
Msrc/render.c | 52+++++++++++++++++++++++++++++++++++++++++++++-------
Msrc/render.h | 12+++++++++++-
4 files changed, 88 insertions(+), 29 deletions(-)

diff --git a/src/game.c b/src/game.c @@ -152,21 +152,23 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga } - m4 view = math_m4_init_id(); - // World origin is in the lower left - view = math_translate(view, (v3) {0.0f, framebuffer.height, 0.0f}); - view = math_scale(view, (v3) {1.0f, -1.0f, 1.0f}); - view = math_translate(view, (v3) {viewport.min.x, viewport.min.y, 0.0f}); - view = math_scale(view, (v3) {ppm, ppm, 1.0f}); - game_state->renderer.view = view; + { + m4 view = math_m4_init_id(); + // World origin is in the lower left + view = math_translate(view, (v3) {0.0f, framebuffer.height, 0.0f}); + view = math_scale(view, (v3) {1.0f, -1.0f, 1.0f}); + view = math_translate(view, (v3) {viewport.min.x, viewport.min.y, 0.0f}); + view = math_scale(view, (v3) {ppm, ppm, 1.0f}); + game_state->renderer.view = view; + } // Screen origin is in the upper left game_state->renderer.projection = math_projection_ortho(0.0f, framebuffer.width, framebuffer.height, 0.0f, -1.0f, 0.0f); v2i current_room_i = game_state->player.pos.room; - struct Room *r = world_room_get(game_state->world, current_room_i); + struct Room *current_room = world_room_get(game_state->world, current_room_i); - assert(r); + assert(current_room); // game_print_player_chunk { @@ -177,14 +179,14 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga printf("Current Player Room: "); math_print(current_room_i); printf("Current Actual Room: "); - math_print(r->index); + math_print(current_room->index); printf("Chunk Index: "); math_print(c->index); } - assert(math_v2i_eq(current_room_i, r->index)); + assert(math_v2i_eq(current_room_i, current_room->index)); - u32 *tiles = r->tiles; + u32 *tiles = current_room->tiles; // game_render_tiles { @@ -238,17 +240,18 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga if (player_is_in_tile && solid) { color = (v3) {0.8f, 0.4f, 0.4f}; - // TODO: re-enable this - //assert(false); + assert(false); } } - struct RenderJob j = { - .ebo = game_state->renderer.quad_ebo, - .color = color, - .model = model, - }; - render_job_enqueue(&game_state->renderer, j); + render_job_enqueue( + &game_state->renderer, + (struct RenderJob) { + .ebo = game_state->renderer.quad_ebo, + .color = color, + .model = model, + .layer = RENDER_LAYER_TILES, + }); } } } @@ -534,10 +537,12 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga .ebo = game_state->renderer.quad_ebo, .color = color, .model = model, + .layer = RENDER_LAYER_PLAYER, }); } - render_jobs(&game_state->renderer); + render_jobs_sort(&game_state->renderer, &game_state->world_allocator); + render_jobs_draw(&game_state->renderer); } internal void game_cleanup(struct GameMemory *game_memory) diff --git a/src/memory.c b/src/memory.c @@ -1,5 +1,6 @@ #define mem_st_alloc_struct(allocator, type) mem_st_alloc((allocator), sizeof(type), alignof(type)) #define mem_st_alloc_buffer(allocator, type, count) mem_st_alloc((allocator), sizeof(type) * (count), alignof(type)) +#define mem_move_buffer(d, s, t, c) mem_move((d), (s), sizeof(t) * (c)) // TODO: test that alignment is working properly internal inline uintptr_t mem_align_address(uintptr_t address, size_t alignment) @@ -44,3 +45,8 @@ internal void mem_st_free_all(struct StackAllocator *allocator) { allocator->used = 0; } + +internal void mem_move(void *dest, void *source, size_t num_bytes) +{ + memmove(dest, source, num_bytes); +} diff --git a/src/render.c b/src/render.c @@ -51,7 +51,7 @@ internal void render_init(struct RendererState *renderer, struct StackAllocator renderer->queue_count = 0; } -internal void render_jobs(struct RendererState *renderer) +internal void render_jobs_draw(struct RendererState *renderer) { glClearColor(0.1f, 0.1f, 0.1f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); @@ -90,6 +90,42 @@ internal void render_jobs(struct RendererState *renderer) renderer->queue_count = 0; } +internal void render_jobs_sort(struct RendererState *renderer, struct StackAllocator *allocator) +{ + size_t marker = mem_st_get_marker(allocator); + + struct RenderJob *queue = renderer->queue; + + size_t layer_pop_count[NUM_RENDER_LAYERS] = {0}; + for (size_t i = 0; i < renderer->queue_count; i++) + { + struct RenderJob j = queue[i]; + assert(j.layer < NUM_RENDER_LAYERS); + layer_pop_count[j.layer] += 1; + } + + struct RenderJob *sorted = mem_st_alloc_buffer(allocator, struct RenderJob, renderer->queue_count); + size_t layer_pop_count_sorted[NUM_RENDER_LAYERS] = {0}; + for (size_t i = 0; i < renderer->queue_count; i++) + { + struct RenderJob j = queue[i]; + + size_t insertion_index = 0; + for (enum RenderLayer l = RENDER_LAYER_TILES; l < j.layer; l++) + { + insertion_index += layer_pop_count[l]; + } + insertion_index += layer_pop_count_sorted[j.layer]; + + assert(layer_pop_count_sorted[j.layer] < layer_pop_count[j.layer]); + sorted[insertion_index] = j; + layer_pop_count_sorted[j.layer] += 1; + } + + mem_move_buffer(queue, sorted, struct RenderJob, renderer->queue_count); + mem_st_free_to_marker(allocator, marker); +} + internal void render_job_enqueue(struct RendererState *renderer, struct RenderJob job) { assert(renderer); @@ -108,12 +144,14 @@ internal void render_debug_quad(struct RendererState *renderer, rect r, v3 color model = math_translate(model, (v3) {r.min.x, r.min.y, 0.0f}); model = math_scale(model, (v3) {dim.width, dim.height, 1.0f}); - struct RenderJob j = { - .ebo = renderer->rect_ebo, - .color = color, - .model = model, - }; - render_job_enqueue(renderer, j); + render_job_enqueue( + renderer, + (struct RenderJob) { + .ebo = renderer->rect_ebo, + .color = color, + .model = model, + .layer = RENDER_LAYER_DEBUG, + }); } internal void render_cleanup(struct RendererState *renderer) diff --git a/src/render.h b/src/render.h @@ -1,10 +1,20 @@ #define RENDER_QUEUE_SIZE 512 +enum RenderLayer +{ + RENDER_LAYER_TILES = 0, + RENDER_LAYER_DEBUG, + RENDER_LAYER_PLAYER, + + NUM_RENDER_LAYERS, +}; + struct RenderJob { GLuint ebo; v3 color; m4 model; + enum RenderLayer layer; }; struct RendererState @@ -17,5 +27,5 @@ struct RendererState m4 view; struct Shader shader; struct RenderJob *queue; - u32 queue_count; + size_t queue_count; };