Skip to content

R-15a: retained GPU buffers for v2 terrain (perf Lever 1, look-independent) #436

Description

@mrtlvmbt

R-15a — retained GPU buffers for v2 terrain (perf Lever 1, look-independent)

Part of the "hex diorama" program. Integration branch: render-r12-terragen-preview — branch
off it, and PR back into it with --base render-r12-terragen-preview EXPLICITLY (gh defaults
to main; see GOTCHAS.md, this exact rake was stepped on in PR #435).
Lane: render (v2/crates/render/** ONLY; standalone workspace, OUT of CI).

Why

macroquad's draw_mesh re-copies vertices and rewrites indices CPU->GPU EVERY frame (see the
comment in main.rs around the drawcall-capacity setup). At 512x512 that is ~3.5M verts/frame
re-streamed (R-13 BENCH: cpu_ms 9.56 avg / 13.43 p95 at dim=512). R-14's look pack (AO, chamfer
bevel) will roughly double vertex count — the copy cost is the wall the program hits at 60fps.
Retained buffers upload each chunk ONCE and draw per frame.

Scope

Port the PATTERN (not the code) from v1 crates/animata/src/render/gpu.rs (retained immutable
miniquad buffers, one draw call per visible chunk, own GLSL + MVP uniform + Pipeline with depth
test + backface culling) into the v2 render terrain path:

  1. New module v2/crates/render/src/gpu_terrain.rs: build-once upload of each chunk's mesh
    (positions, normals baked into vertex color shading as today, colors) into immutable miniquad
    buffers; per-frame: frustum-cull chunks (existing AABBs), bind pipeline, set MVP from the
    existing IsoCam, draw visible chunks.
  2. Runtime toggle --retained (default OFF for now; flipping the default is R-15 proper, after
    R-14 lands on top). Interactive key toggle optional.
  3. Both hex and cube mesh kinds must work (they share chunk struct).
  4. The egui/macroquad UI overlay and creature rendering keep using the macroquad path — only
    terrain chunks move to retained buffers. Verify draw-order/depth interop (v1 does exactly this
    mix; its gpu.rs comments document the pitfalls — depth Comparison::Less, clockwise cull).

Acceptance

  • Screenshot PARITY: --screenshot at --cam iso-default and iso-zoom-close, dim=512 seed=1,
    retained OFF vs ON — pixel-identical or diff-explained in the PR (this is the guard against
    silent depth/cull/format drift; R-13 makes it free). Attach both pairs.
  • BENCH lines (dim=64 and dim=512, both modes) in the PR body: expect cpu_ms to DROP
    substantially with --retained; wall_ms stays vsync-locked (documented macOS Metal behavior).
  • No regression in interactive controls; 'T' hex/cube toggle works in retained mode.
  • cd v2/crates/render && bash ../../../scripts/compile-check.sh PASS (quoted) + clippy clean.
  • Code-critic self-review, verdict block posted as PR comment, before ready-for-review.

Process

Branch r15a-retained-buffers off origin/render-r12-terragen-preview (fetch first — R-13 just
merged into it). PR with EXPLICIT --base. App launches via background execution (GOTCHAS).
VERIFY every screenshot by opening it with the Read tool before claiming anything about it —
a black/empty PNG is not evidence (precedent: R-13 F-B5).
Final report: STATUS line contract; status.md last.

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent:BOwned by dev agent B

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions