docs(perf): Phase N.6 slice 1 — radius=12 baseline + surface dump path

Capture authoritative CPU+GPU dispatch numbers at Holtburg with the
gpu_us diagnostic now working (commit 25cb147). Three radii (4/8/12)
x two motion modes (standstill/walking) + a surface-format histogram
from ACDREAM_DUMP_SURFACES=1.

Adds env-gated one-shot dump path (TextureCache.TickSurfaceHistogramDumpIfEnabled,
called from GameWindow.OnRender) that fires once after both (a) frame
600 of the session AND (b) the upload-metadata dict reaches 100 entries
-- the cache-size gate prevents the dump from firing during pre-world
GUI ticks where OnRender spins at high rates but no scenery has streamed.
Output writes to %LOCALAPPDATA%\acdream\n6-surfaces.txt with a try/catch
around the I/O so disk-full / permission errors don't crash mid-measurement.

Baseline document at docs/plans/2026-05-11-phase-n6-perf-baseline.md
documents:
- CPU dominates GPU by 30-50x at every radius (strongly CPU-bound)
- GPU wildly under-utilized (max gpu_us p95 ~600us vs 16,600us frame budget)
- CPU scales superlinearly with N1 (Tier 1 cache wins on inner loop but
  not outer LB walk)
- Surface atlas opportunity high (59% of textures in top-3 triples) but
  win is memory-only since GPU isn't bottlenecked

Recommendation: C.1.5 (PES emitter wiring) next, then a reduced-scope
N.6 slice 2 (drop atlas + persistent-mapped buffers -- not justified by
the GPU under-utilization observed).

Roadmap entry amended to split N.6 into slice 1 (shipped) and slice 2
(planned, reduced scope, deferred until after C.1.5).

Spec: docs/superpowers/specs/2026-05-11-phase-n6-slice1-design.md.
Plan: docs/superpowers/plans/2026-05-11-phase-n6-slice1.md (Task 4).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-05-11 12:34:10 +02:00
parent 25cb147d97
commit 13abf96a5e
4 changed files with 318 additions and 16 deletions

View file

@ -687,22 +687,26 @@ for our deletions/additions; merge upstream `master` periodically.
manifest at higher radius. Spec acceptance criterion #5 was wrong;
amended via `docs/plans/2026-05-09-phase-n5b-perf-baseline.md`. Plan
archived at `docs/superpowers/plans/2026-05-09-phase-n5b-terrain-modern.md`.
- **N.6 — Perf polish.** **Planned (post-A.5 polish takes priority).**
Builds on N.5 + N.5b. Legacy renderer retirement was pulled forward
into N.5 ship amendment — `InstancedMeshRenderer`, `StaticMeshRenderer`,
`WbFoundationFlag` are gone — and the terrain legacy renderer
(`TerrainChunkRenderer` + `TerrainRenderer` + `terrain.vert/.frag`)
retired in N.5b. N.6 scope: WB atlas adoption for memory savings
on shared content, persistent-mapped buffers if `glBufferData` shows
up in profiling (the modern terrain path's per-frame DEIC `BufferSubData`
is a candidate), GPU-side culling via compute pre-pass (eliminates
the per-frame slot walk + DEIC build entirely), GL_TIME_ELAPSED query
double-buffering (deferred from N.5 — diagnostic shows `gpu_us=0/0`
under `ACDREAM_WB_DIAG=1`), direct higher-radius perf comparison (A.5
has now landed — modern's architectural wins are measurable), retire the
legacy `Texture2D`/`sampler2D` path in `TextureCache` (currently kept
for Sky + Debug + particle paths now that Terrain has migrated).
Plan + spec written when work begins. **Estimate: 1-2 weeks.**
- **N.6 slice 1 — GPU timing fix + radius=12 perf baseline.** **SHIPPED 2026-05-11.**
Fixed the gpu_us double-buffering bug in `WbDrawDispatcher` (ring-of-3
query slots, read-before-overwrite, vendor-neutral across AMD/NVIDIA/Intel
desktop GL). Added env-gated surface-format histogram dump in `TextureCache`
for atlas-opportunity audit. Captured authoritative baseline at Holtburg
radii 4 / 8 / 12 (standstill + walking) with the now-working `gpu_us`
diagnostic. Plan + spec at `docs/superpowers/{specs,plans}/2026-05-11-phase-n6-slice1-*.md`.
Baseline numbers + next-phase recommendation at
[docs/plans/2026-05-11-phase-n6-perf-baseline.md](2026-05-11-phase-n6-perf-baseline.md).
- **N.6 slice 2 — Perf polish cleanup.** **Planned — deferred until after C.1.5
(PES emitter wiring) per the baseline doc's recommendation.** Builds on
slice 1's measurement. Scope: retire the legacy `Texture2D`/`sampler2D` path
in `TextureCache` (currently kept for Sky + Debug + particle paths now that
Terrain has migrated); delete orphan `mesh.frag` (verify zero callers post-N.5
amendment); decide bindless-everywhere vs legacy-island for the remaining
`sampler2D` consumers. **Dropped from slice 2 scope per baseline data**:
WB atlas adoption and persistent-mapped buffers — both target GPU/sampler
throughput but the baseline shows GPU is wildly under-utilized (max gpu_us
p95 ~600 µs vs 16,600 µs frame budget). Slice 2 reduces to a ~1-day cleanup.
Plan + spec written when work begins. **Estimate: ~1 day once C.1.5 lands.**
- **N.7 — EnvCells / dungeons.** Replace EnvCell rendering with WB's
`EnvCellRenderManager` + `PortalRenderManager` on top of N.4's
foundation. **Estimate: 1-2 weeks** (was 2-3 — naturally smaller now