render3d: a fog wall nearer than a layer's cards lets its impostor atlases go, and a fog that opens bakes them again

Inside the wall every instance is a mesh whose LOD2 casts its shadow, so a card is neither drawn nor
cast there: fog_impostors.ludic frees a layer's atlases while wall + margin < its near (trees 420-480
m, rocks 320 m) and paints them again from the model when it opens past it (impostor_paint, split out
of the bake). Impostor atlases get memory of their own, so a release goes back to the driver instead
of leaving a hole in a shared block. R3D_FOG_AT=<frame> with R3D_FOG_TO=<m> changes the wall mid-run.

At the overlook: 2102 MB off, 1824 MB at 30 m (249 -> 67 MB of atlases; the rest is the ground cover's
card atlases, drawn inside the wall); opening re-bakes 16 layers in 42-46 ms, back to 2102 MB.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Orkun ÇAKILKAYA 2026-09-29 16:05:16 +03:00
parent 6289564382
commit 7024f42789
6 changed files with 88 additions and 7 deletions

View file

@ -199,6 +199,11 @@ export state Render3dState {
gvk_al_tag: []int = null # per allocation id: owner * 4 + image * 2 + host (vkmem_report.ludic)
gvk_tag: int = 0 # the owner allocations are made for now (VKM_*)
vkmem_at: int = 0 # R3D_VKMEM=<frame>: the report is printed at that frame
fog_imp_released: int = 0 # impostor atlases let go under a fog wall (fog_impostors.ludic)
fog_imp_rebaked: int = 0
fog_imp_rebake_us: int = 0
fog_at: int = 0 # R3D_FOG_AT=<frame>:<m>, a change of the wall mid-run (a dev switch)
fog_at_m: float = 0.0
@max(4096) gvk_al_spare: []int = null # ids to reuse
gvk_pool: long = 0
gvk_fence: bytes = null