phase(N.5): roadmap — N.5 shipped, N.6 next
Moves N.5 from in-flight to Shipped (2026-05-08). N.6 (retire InstancedMeshRenderer + perf polish) becomes the in-flight phase. CLAUDE.md in-flight pointer updated to match. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
38eb999f2c
commit
77e619d48a
2 changed files with 38 additions and 31 deletions
19
CLAUDE.md
19
CLAUDE.md
|
|
@ -500,14 +500,17 @@ acdream's plan lives in two files committed to the repo:
|
||||||
acceptance criteria. Do not drift from the spec without explicit user
|
acceptance criteria. Do not drift from the spec without explicit user
|
||||||
approval.
|
approval.
|
||||||
|
|
||||||
**Currently in flight: Phase N.5 — Modern Rendering Path.** Roadmap entry
|
**Currently in flight: Phase N.6 — Retire legacy renderers + perf polish.**
|
||||||
at [`docs/plans/2026-04-11-roadmap.md`](docs/plans/2026-04-11-roadmap.md).
|
Roadmap entry at [`docs/plans/2026-04-11-roadmap.md`](docs/plans/2026-04-11-roadmap.md).
|
||||||
Builds on N.4's `WbDrawDispatcher` to adopt WB's modern rendering primitives:
|
Builds on N.5. Retires `InstancedMeshRenderer` + `StaticMeshRenderer` entirely.
|
||||||
bindless textures (eliminate `glBindTexture` calls) and
|
Optional candidates: WB atlas adoption, persistent-mapped buffers, GPU-side
|
||||||
`glMultiDrawElementsIndirect` (one GL call per pass instead of one per
|
culling via compute pre-pass, GL_TIME_ELAPSED query double-buffering, direct
|
||||||
group). Together these target a 2-5× CPU win on draw-heavy scenes by
|
N.4 vs N.5 perf measurement. Plan + spec written when work begins.
|
||||||
eliminating the remaining per-group state changes. Plan + spec to be
|
|
||||||
written when work begins.
|
**Phase N.5 (Modern Rendering Path) shipped 2026-05-08.** `WbDrawDispatcher`
|
||||||
|
on bindless textures + `glMultiDrawElementsIndirect`. CPU dispatcher 1.23ms/frame
|
||||||
|
at Holtburg (~810 fps). Plan archived at
|
||||||
|
[`docs/superpowers/plans/2026-05-08-phase-n5-modern-rendering.md`](docs/superpowers/plans/2026-05-08-phase-n5-modern-rendering.md).
|
||||||
|
|
||||||
**Phase N.4 (Rendering Pipeline Foundation) shipped 2026-05-08.** WB's
|
**Phase N.4 (Rendering Pipeline Foundation) shipped 2026-05-08.** WB's
|
||||||
`ObjectMeshManager` is integrated and is the default rendering path
|
`ObjectMeshManager` is integrated and is the default rendering path
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# acdream — strategic roadmap
|
# acdream — strategic roadmap
|
||||||
|
|
||||||
**Status:** Living document. Updated 2026-05-08 for Phase N.4 shipping (`WbMeshAdapter` + `WbDrawDispatcher` + `ACDREAM_USE_WB_FOUNDATION` default-on) + N.5 rebranded to "Modern rendering path" (bindless + multi-draw indirect on top of N.4's foundation).
|
**Status:** Living document. Updated 2026-05-08 for Phase N.5 shipping (bindless textures + `glMultiDrawElementsIndirect` on top of N.4's foundation; CPU dispatcher 1.23ms/frame at Holtburg, ~810 fps) + N.6 becomes the new in-flight phase (retire legacy renderers + perf polish).
|
||||||
**Purpose:** One source of truth for where the project is and where it's going. Every observed defect or missing feature has a named phase that owns it; when something looks wrong in-game, look here to find the phase that'll address it. Implementation details live in per-phase specs under `docs/superpowers/specs/`, not in this file.
|
**Purpose:** One source of truth for where the project is and where it's going. Every observed defect or missing feature has a named phase that owns it; when something looks wrong in-game, look here to find the phase that'll address it. Implementation details live in per-phase specs under `docs/superpowers/specs/`, not in this file.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
@ -60,6 +60,7 @@
|
||||||
| N.1 | WorldBuilder-backed scenery (Chorizite/WorldBuilder fork as submodule, SceneryHelpers + TerrainUtils replace our inline ports) | Live ✓ |
|
| N.1 | WorldBuilder-backed scenery (Chorizite/WorldBuilder fork as submodule, SceneryHelpers + TerrainUtils replace our inline ports) | Live ✓ |
|
||||||
| N.3 | WorldBuilder-backed texture decode — `SurfaceDecoder` delegates INDEX16 / P8 / A8R8G8B8 / R8G8B8 / A8(+Additive) to `TextureHelpers.Fill*`; `isAdditive` threaded through (terrain alpha → `FillA8Additive`, non-additive entity surfaces → `FillA8`). R5G6B5 + A4R4G4B4 newly handled (previously magenta). X8R8G8B8, DXT1/3/5, SolidColor remain ours (no WB equivalent). 9 conformance tests prove byte-identical equivalence per format. | Live ✓ |
|
| N.3 | WorldBuilder-backed texture decode — `SurfaceDecoder` delegates INDEX16 / P8 / A8R8G8B8 / R8G8B8 / A8(+Additive) to `TextureHelpers.Fill*`; `isAdditive` threaded through (terrain alpha → `FillA8Additive`, non-additive entity surfaces → `FillA8`). R5G6B5 + A4R4G4B4 newly handled (previously magenta). X8R8G8B8, DXT1/3/5, SolidColor remain ours (no WB equivalent). 9 conformance tests prove byte-identical equivalence per format. | Live ✓ |
|
||||||
| N.4 | Rendering pipeline foundation — adopted WB's `ObjectMeshManager` as the production mesh pipeline behind `ACDREAM_USE_WB_FOUNDATION` (default-on). `WbMeshAdapter` is the single seam (owns `ObjectMeshManager`, drains the staged-upload queue per frame, populates `AcSurfaceMetadataTable` with per-batch translucency / luminosity / fog metadata). `WbDrawDispatcher` is the production draw path: groups all visible (entity, batch) pairs, single-uploads the matrix buffer, fires one `glDrawElementsInstancedBaseVertexBaseInstance` per group with `BaseInstance` slicing into the shared instance VBO. `LandblockSpawnAdapter` + `EntitySpawnAdapter` bridge spawn lifecycle to WB ref-counts (atlas tier vs per-instance). Perf wins shipped as part of N.4: per-entity frustum cull, opaque front-to-back sort, palette-hash memoization (compute once per entity, reuse across batches). Visual verification at Holtburg passed: scenery + connected characters with full close-detail geometry (Issue #47 regression resolved). Legacy `InstancedMeshRenderer` retained as `ACDREAM_USE_WB_FOUNDATION=0` escape hatch until N.6. | Live ✓ |
|
| N.4 | Rendering pipeline foundation — adopted WB's `ObjectMeshManager` as the production mesh pipeline behind `ACDREAM_USE_WB_FOUNDATION` (default-on). `WbMeshAdapter` is the single seam (owns `ObjectMeshManager`, drains the staged-upload queue per frame, populates `AcSurfaceMetadataTable` with per-batch translucency / luminosity / fog metadata). `WbDrawDispatcher` is the production draw path: groups all visible (entity, batch) pairs, single-uploads the matrix buffer, fires one `glDrawElementsInstancedBaseVertexBaseInstance` per group with `BaseInstance` slicing into the shared instance VBO. `LandblockSpawnAdapter` + `EntitySpawnAdapter` bridge spawn lifecycle to WB ref-counts (atlas tier vs per-instance). Perf wins shipped as part of N.4: per-entity frustum cull, opaque front-to-back sort, palette-hash memoization (compute once per entity, reuse across batches). Visual verification at Holtburg passed: scenery + connected characters with full close-detail geometry (Issue #47 regression resolved). Legacy `InstancedMeshRenderer` retained as `ACDREAM_USE_WB_FOUNDATION=0` escape hatch until N.6. | Live ✓ |
|
||||||
|
| N.5 | Modern rendering path — lifted `WbDrawDispatcher` onto bindless textures (`GL_ARB_bindless_texture`) + `glMultiDrawElementsIndirect`. Per-frame entity rendering: 3 SSBO uploads (instance matrices @ binding=0, batch data @ binding=1, indirect commands) + 2 indirect draw calls (opaque + transparent). ~12-15 GL calls per frame regardless of group count, down from hundreds-of-per-group in N.4. CPU dispatcher: 1.23 ms/frame median at Holtburg courtyard (1662 groups, ~810 fps sustained). All textures on the WB modern path use 1-layer `Texture2DArray` + `sampler2DArray`. Legacy callers keep `Texture2D` / `sampler2D` via the parallel `TextureCache` path until N.6 retires them. Three gotchas captured in memory: texture target lock-in, bindless Dispose order (two-phase non-resident before delete), GL_TIME_ELAPSED double-buffering. Plan archived at `docs/superpowers/plans/2026-05-08-phase-n5-modern-rendering.md`. | Live ✓ |
|
||||||
|
|
||||||
Plus polish that doesn't get its own phase number:
|
Plus polish that doesn't get its own phase number:
|
||||||
- FlyCamera default speed lowered + Shift-to-boost
|
- FlyCamera default speed lowered + Shift-to-boost
|
||||||
|
|
@ -624,22 +625,21 @@ for our deletions/additions; merge upstream `master` periodically.
|
||||||
memoization. Legacy `InstancedMeshRenderer` retained as flag-off
|
memoization. Legacy `InstancedMeshRenderer` retained as flag-off
|
||||||
fallback until N.6 fully retires it. Plan archived at
|
fallback until N.6 fully retires it. Plan archived at
|
||||||
`docs/superpowers/plans/2026-05-08-phase-n4-rendering-foundation.md`.
|
`docs/superpowers/plans/2026-05-08-phase-n4-rendering-foundation.md`.
|
||||||
- **N.5 — Modern rendering path.** **Rebranded from "Terrain rendering"
|
- **✓ SHIPPED — N.5 — Modern rendering path.** Shipped 2026-05-08.
|
||||||
2026-05-08 after N.4 perf review.** N.4 left two big remaining wins
|
**Rebranded from "Terrain rendering" 2026-05-08 after N.4 perf
|
||||||
on the table that pair naturally: (1) bindless textures via
|
review.** Lifted `WbDrawDispatcher` onto bindless textures
|
||||||
`GL_ARB_bindless_texture` (WB already populates
|
(`GL_ARB_bindless_texture`) + `glMultiDrawElementsIndirect`. Per-frame
|
||||||
`ObjectRenderBatch.BindlessTextureHandle`; switch our shader to
|
entity rendering: 3 SSBO uploads (instance matrices @ binding=0, batch
|
||||||
consume per-instance handles, eliminate 100% of `glBindTexture`
|
data @ binding=1, indirect commands) + 2 indirect calls (opaque +
|
||||||
calls), and (2) `glMultiDrawElementsIndirect` (one GL call per pass
|
transparent). ~12-15 GL calls per frame regardless of group count, down
|
||||||
instead of one per group; build a `DrawElementsIndirectCommand`
|
from hundreds-of-per-group in N.4. CPU dispatcher: 1.23 ms/frame median
|
||||||
buffer, fire one indirect draw, the driver pulls everything). Both
|
at Holtburg (1662 groups, ~810 fps). All textures on the modern path use
|
||||||
require shader changes (same shader, in fact — bindless + indirect
|
1-layer `Texture2DArray` + `sampler2DArray`; legacy callers retain
|
||||||
are the same modern path WB uses internally). Together they target a
|
`Texture2D` via the parallel `TextureCache` path until N.6 retires them.
|
||||||
2-5× CPU win on draw-heavy scenes (Holtburg courtyard, Foundry,
|
Three gotchas in memory (`project_phase_n5_state.md`): texture target
|
||||||
dense dungeons). Also folds in: persistent-mapped instance VBO
|
lock-in, bindless Dispose two-phase order, GL_TIME_ELAPSED double-
|
||||||
(`glBufferStorage` + `MAP_PERSISTENT_BIT | MAP_COHERENT_BIT` + ring
|
buffering. Plan archived at
|
||||||
buffer + sync) and texture pre-warm at landblock load (smooths
|
`docs/superpowers/plans/2026-05-08-phase-n5-modern-rendering.md`.
|
||||||
streaming-boundary hitches). **Estimate: 2-3 weeks.**
|
|
||||||
- **N.5b — Terrain rendering on N.5 path.** Wire WB's
|
- **N.5b — Terrain rendering on N.5 path.** Wire WB's
|
||||||
`TerrainRenderManager` + `LandSurfaceManager` + `TerrainGeometryGenerator`
|
`TerrainRenderManager` + `LandSurfaceManager` + `TerrainGeometryGenerator`
|
||||||
onto the modern rendering path. Closes N.2's deferred terrain math
|
onto the modern rendering path. Closes N.2's deferred terrain math
|
||||||
|
|
@ -647,12 +647,16 @@ for our deletions/additions; merge upstream `master` periodically.
|
||||||
`CalculateSplitDirection` + `GetHeight` + `GetNormal` in lockstep,
|
`CalculateSplitDirection` + `GetHeight` + `GetNormal` in lockstep,
|
||||||
resolving ISSUE #51. **Estimate: 1-2 weeks** (was 2-3 — modern path
|
resolving ISSUE #51. **Estimate: 1-2 weeks** (was 2-3 — modern path
|
||||||
primitives already in place from N.5).
|
primitives already in place from N.5).
|
||||||
- **N.6 — Static objects rendering.** Wire WB's
|
- **N.6 — Retire legacy renderers + perf polish.** **Currently in flight.**
|
||||||
`StaticObjectRenderManager` onto the modern rendering path; **fully
|
Builds on N.5. Retires `InstancedMeshRenderer` + `StaticMeshRenderer`
|
||||||
delete** legacy `StaticMeshRenderer` + `InstancedMeshRenderer` (they
|
entirely — they remain as `ACDREAM_USE_WB_FOUNDATION=0` escape hatches
|
||||||
remain as `ACDREAM_USE_WB_FOUNDATION=0` escape hatches through N.5).
|
through N.5 but are deleted when N.6 ships. Optional N.6 candidates: WB
|
||||||
Mostly draw orchestration at this point — most of the substance
|
atlas adoption for memory savings on shared content, persistent-mapped
|
||||||
landed in N.4 + N.5. **Estimate: 1-2 weeks** (was 2-3).
|
buffers if `glBufferData` shows up in profiling, GPU-side culling via
|
||||||
|
compute pre-pass, GL_TIME_ELAPSED query double-buffering (deferred from
|
||||||
|
N.5 — diagnostic shows `gpu_us=0/0` under `ACDREAM_WB_DIAG=1`), direct
|
||||||
|
N.4 vs N.5 perf measurement. Plan + spec written when work begins.
|
||||||
|
**Estimate: 1-2 weeks** (was 2-3).
|
||||||
- **N.7 — EnvCells / dungeons.** Replace EnvCell rendering with WB's
|
- **N.7 — EnvCells / dungeons.** Replace EnvCell rendering with WB's
|
||||||
`EnvCellRenderManager` + `PortalRenderManager` on top of N.4's
|
`EnvCellRenderManager` + `PortalRenderManager` on top of N.4's
|
||||||
foundation. **Estimate: 1-2 weeks** (was 2-3 — naturally smaller now
|
foundation. **Estimate: 1-2 weeks** (was 2-3 — naturally smaller now
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue