render3d: the height field and photograph on the CPU as tiles read from a file (off until the game asks)

terrain_tiles_to(dir, key) before a map is made: once made, its heights, photograph and baked normals
are written tile by tile (64 m, TT_TEX) to <dir>/<key>.tiles - fresh every time, header last, so no
other generator's or a torn file is ever read - and the whole copies go. Every read goes through the
tile: resident, else read from the file there and then into a 2048-tile clock, so terrain_height,
terrain_height_smooth, terrain_ortho* and terrain_chunk_heights answer exactly what the whole copy
did (R3D_TT_CHECK: worst 0.0 m over 4000 points) whatever is resident - two machines and the boot's
placements agree to the bit. terrain_chunk_heights takes render3d_st mut for it.

terrain_height_near(read-only): the tile if it is in, else a coarse 2048^2 level (worst 0.91 m), never
the file - for line checks that must not take render3d_st mut. terrain_texel() is the texel size,
terrain_tiles_prefetch(x, z, r, budget) reads ahead, and a frame that reads more than 8 tiles says so
once. R3D_TERRAIN_TILES=<dir> turns it on for a run.

At the overlook with MallocLargeCache=0: 1731 MB off, 1658 MB on; 192 MB written in ~200 ms; the
frame unchanged (0 pixels over 8).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Orkun ÇAKILKAYA 2026-09-29 16:53:28 +03:00
parent c5e58d14ea
commit 5b3cfac48e
8 changed files with 385 additions and 15 deletions

View file

@ -829,6 +829,25 @@ export state Render3dState {
ter_ortho_tex: int = 0 # a photograph of the same window, draped with distance
ter_carpet: int = 0 # the distant-grass carpet (carpet_bake), 0 = none
ter_shadow_tex: int = 0 # height-field sun shadow: R32F, the lowest lit height
tt_dir: string = "" # terrain_tiles_to: where a map's tiles are written ("" keeps the whole copies)
tt_key: string = ""
tt_file: pointer = null # the tiles' file, open for reading (terrain_tiles.ludic)
tt_n: int = 0 # tiles a side
tt_oside: int = 0 # photograph texels a tile a side
tt_hoff: int = 0 # where the heights and the photograph start in the file
tt_ooff: int = 0
tt_noff: int = 0
tt_h: floats = null # TT_SLOTS tiles of heights
tt_o: words = null # ... and of photograph, 0xRRGGBB
tt_nm: words = null # ... and of normals, RG16F in a word
tt_coarse: floats = null # the heights at TT_COARSE a side, for terrain_height_near
tt_slot_of: words = null # per tile: its slot, or -1
tt_tile_in: words = null # per slot: its tile, or -1
tt_ref: words = null # per slot: asked for since the clock's hand last passed
tt_hand: int = 0
tt_reads: int = 0 # tiles read from the file, over the run and this frame
tt_frame_reads: int = 0
tt_warned: bool = false
ter_shadow_prog_aux: int = 0 # the bake of the aux target (TS_AUX)
ter_shadow_aux: int = 0 # beside it, RG16F: the occluder distance and the cloud mask
ter_shadow_yaw: float = 1000000000.0 # the sky yaw it was baked for