From c27fa53236e1be0f76d4a21b88bdbeae01d478d8 Mon Sep 17 00:00:00 2001 From: Katajisto Date: Sun, 3 May 2026 00:35:31 +0300 Subject: [PATCH] 200x perf improvement on world rendering task creation --- src/rendering/backend_sokol.jai | 25 ++++++++++--- src/rendering/helpers.jai | 65 ++++++++++++++++++++------------- src/world.jai | 32 ++++++++++++++-- 3 files changed, 88 insertions(+), 34 deletions(-) diff --git a/src/rendering/backend_sokol.jai b/src/rendering/backend_sokol.jai index 02d0051..f011cb9 100644 --- a/src/rendering/backend_sokol.jai +++ b/src/rendering/backend_sokol.jai @@ -143,9 +143,9 @@ backend_add_trile_positions :: (positions : []Trile_Instance, chunk: Chunk_Key) array_reset_keeping_memory(*trile_position_staging); for position : positions { array_add(*trile_position_staging, Vector4.{ - cast(float)(position.x + chunk.x), - cast(float)(position.y + chunk.y), - cast(float)(position.z + chunk.z), + cast(float)(position.x + chunk.x * 32.0), + cast(float)(position.y + chunk.y * 32.0), + cast(float)(position.z + chunk.z * 32.0), cast(float)(position.orientation) }); } @@ -178,7 +178,11 @@ backend_draw_trile_positions_gbuffer :: (trile : string, amount : s32, worldConf offset := trile_offsets[offset_index]; - trilegfx := get_trile_gfx(trile); + trilegfx, success := get_trile_gfx(trile); + if !success { + log_warn("Failed to get trile: %\n", trile); + return; + } vbuf, nbuf, cbuf : sg_buffer; vcount : s64; @@ -217,7 +221,12 @@ backend_draw_trile_positions_main :: (trile : string, amount : s32, worldConf: * return; } - trilegfx := get_trile_gfx(trile); + trilegfx, success := get_trile_gfx(trile); + if !success { + log_warn("Failed to get trile: %\n", trile); + return; + } + offset := trile_offsets[offset_index]; // Pick mesh source based on LOD level. For shadow + gbuffer we keep the original pipeline @@ -363,7 +372,11 @@ backend_add_trile_rdm_position :: (position: Vector4) { backend_draw_trile_rdm :: (trile: string, worldConf: *World_Config, atlas_rect: Vector4, offset_index: s32) { if offset_index >= trile_rdm_offsets.count then return; - trilegfx := get_trile_gfx(trile); + trilegfx, success := get_trile_gfx(trile); + if !success { + log_warn("Failed to get trile: %\n", trile); + return; + } offset := trile_rdm_offsets[offset_index]; mvp := create_viewproj(*camera); diff --git a/src/rendering/helpers.jai b/src/rendering/helpers.jai index 49c3c89..3e77cec 100644 --- a/src/rendering/helpers.jai +++ b/src/rendering/helpers.jai @@ -83,34 +83,49 @@ create_world_rendering_tasks :: (world: *World, camera: Camera, plane_height: fl reflect_planes := extract_frustum_planes(reflect_mvp); for chunk: world.chunks { - chunk_quadrant_vis : [8]bool; - any_vis : bool; - - for i: 0..1 { - for j: 0..1 { - for k: 0..1 { - bmin := Vector3.{ - chunk.coord.x * 32.0 + i * 16.0, - chunk.coord.y * 32.0 + j * 16.0, - chunk.coord.z * 32.0 + k * 16.0 - }; - bmax := bmin + .{16, 16, 16}; - in_cam := aabb_in_frustum(cam_planes, bmin, bmax); - in_reflect := aabb_in_frustum(reflect_planes, bmin, bmax); - in_shad := aabb_in_frustum(shadow_planes, bmin, bmax); - vis := in_cam || in_reflect || in_shad; - chunk_quadrant_vis[i+j*2+k*2*2] = vis; - if !any_vis then any_vis = vis; - } - } - } + // Skip chunks that are completely out of view. + bmin := Vector3.{ + chunk.coord.x * 32.0, + chunk.coord.y * 32.0, + chunk.coord.z * 32.0 + }; + bmax := bmin + .{32, 32, 32}; + in_cam := aabb_in_frustum(cam_planes, bmin, bmax); + in_reflect := aabb_in_frustum(reflect_planes, bmin, bmax); + in_shad := aabb_in_frustum(shadow_planes, bmin, bmax); + vis := in_cam || in_reflect || in_shad; + if !vis then continue; for group : chunk.groups { + if group.instances.count < 1 then continue; + + + gmin := group.bounding_min; + gmax := group.bounding_max; + + gmin += Vector3.{cast(float)chunk.coord.x * 32, cast(float)chunk.coord.y * 32, cast(float)chunk.coord.z * 32}; + gmax += Vector3.{cast(float)chunk.coord.x * 32, cast(float)chunk.coord.y * 32, cast(float)chunk.coord.z * 32}; + in_cam := aabb_in_frustum(cam_planes, gmin, gmax); + in_reflect := aabb_in_frustum(reflect_planes, gmin, gmax); + in_shad := aabb_in_frustum(shadow_planes, gmin, gmax); + vis := in_cam || in_reflect || in_shad; + + if !vis then continue; + + diff := group.average_pos - camera.position; + dist := length(diff); + lod_index : s32 = 0; + for lod_dist : LOD_DISTANCES { + if dist < lod_dist then break; + lod_index += 1; + } + task := Rendering_Task_Trile.{ - trile = group.trile_name, - chunk_key = chunk.coord, - positions = group.instances, - worldConf = *world.conf + trile = group.trile_name, + chunk_key = chunk.coord, + positions = group.instances, + worldConf = *world.conf, + lod_index = lod_index }; add_rendering_task(task); } diff --git a/src/world.jai b/src/world.jai index 9f5ab11..041a4a9 100644 --- a/src/world.jai +++ b/src/world.jai @@ -44,9 +44,15 @@ Trile_Instance :: struct { } Chunk_Trile_Group :: struct { - trile_name: string; - instances: [..]Trile_Instance; - is_buried: [..]bool; // Runtime-only, parallel to instances. Not serialized. + trile_name : string; + + // Precalculated to save time when we are creating render tasks. + bounding_min : Vector3; + bounding_max : Vector3; + average_pos : Vector3; + + instances : [..]Trile_Instance; + is_buried : [..]bool; // Runtime-only, parallel to instances. Not serialized. } Chunk :: struct { @@ -676,6 +682,25 @@ load_world_from_json :: (json_str: string, chunk_bin: []u8) -> (World, bool) { inst := read_value(chunk_data, *chunk_cursor, Trile_Instance); array_add(*group.instances, inst); } + gmin := Vector3.{31,31,31}; + gmax := Vector3.{0,0,0}; + gavg := Vector3.{0,0,0}; + + for i : group.instances { + gmin.x = min(gmin.x, xx i.x); + gmin.y = min(gmin.y, xx i.y); + gmin.z = min(gmin.z, xx i.z); + gmax.x = max(gmax.x, xx i.x); + gmax.y = max(gmax.y, xx i.y); + gmax.z = max(gmax.z, xx i.z); + + gavg += Vector3.{xx i.x, xx i.y, xx i.z}; + } + gavg /= cast(float) group.instances.count; + + group.bounding_min = gmin; + group.bounding_max = gmax; + group.average_pos = gavg; array_add(*chunk.groups, group); } table_set(*world.chunks, chunk.coord, chunk); @@ -771,6 +796,7 @@ load_world_from_data :: (data: []u8) -> (World, bool) { inst := read_value(data, *chunk_cursor, Trile_Instance); array_add(*group.instances, inst); } + array_add(*chunk.groups, group); } table_set(*world.chunks, chunk.coord, chunk);