docs(render): drop the ambient-encoder relaxation from Campaign V

The transitional path for slices V4a-V4g needs no special API after all.
On GL, BeginPass binds the target framebuffer and applies load ops but
deliberately leaves viewport and scissor to the encoder, so a renderer
being ported mid-campaign opens a Load/Store pass against the backbuffer
and gets exactly today's behavior while the frame spine still owns clears.
One less contract concept, and one less thing for V4h to unwind.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-07-27 14:28:06 +02:00
parent 621b16364b
commit 90f7c6f2f4
2 changed files with 11 additions and 6 deletions

View file

@ -398,7 +398,7 @@ commit's build, capture again at slice HEAD, compare with the
| Slice | Scope | Gate |
|---|---|---|
| **V0** ✅ | Pinned RHI contract, `RecordingGpuDevice`, contract tests, this document, roadmap entry. | build + tests + contract tests |
| **V1** | GL backend: `GlGpuDevice` (no Chorizite inheritance), buffers (`BufferSubData`, behaviour-preserving), ring over the existing fence-bounded pattern, textures + the binding-9 handle table, samplers, pipelines, the ambient-encoder relaxation, timers, `IGpuFenceApi` re-home, backbuffer capture. Constructed in composition; no consumers yet. | build + tests + GL unit tests + pixel gate (trivially identical — a tripwire) |
| **V1** | GL backend: `GlGpuDevice` (no Chorizite inheritance), buffers (`BufferSubData`, behaviour-preserving), ring over the existing fence-bounded pattern, textures + the binding-9 handle table, samplers, pipelines, timers, backbuffer capture. Constructed in composition; no consumers yet. | build + tests + GL unit tests + pixel gate (trivially identical — a tripwire) |
| **V2** | Shader dialect + texture-index migration **on GL**: `uvec2 textureHandle``uint textureIndex`, binding-9 table, `common.glsl` preamble, CPU batch-struct change, caches registering into the device table. Sub-commits: V2a mesh, V2b terrain, V2c particles. | pixel gate per sub-commit |
| **V3** | Clip-space and sRGB audit: verify every projection producer is [0,1] convention, confirm clip-plane derivation, record the sRGB swapchain decision and the depth-precision divergence class here. | pixel gate + connected lifecycle |
| **V4a** | `TextRenderer` (three fence-buffered VBO sets → ring allocations), `BitmapFont`, `DebugLineRenderer`, the UI RenderSurface upload path, `UiViewport`'s texture handoff. | pixel gate (UI-heavy checkpoints) |
@ -408,7 +408,7 @@ commit's build, capture again at slice HEAD, compare with the
| **V4e** | `ParticleRenderer` (after V4c — shared alpha-queue contract). | pixel gate (particle-heavy checkpoint) |
| **V4f** | `SkyRenderer` + weather. | pixel gate (dawn/dusk, day group pinned) |
| **V4g** | `PrivateEntityViewportRenderer``IGpuRenderTarget`; `PortalDepthMaskRenderer` + `PortalTunnelPresentation` → stencil/depth-mask pipelines. | pixel gate incl. paperdoll and portal transit |
| **V4h** | Frame-spine formalization: pass executors emit `BeginPass`/`EndPass`, the ambient relaxation is removed, flight/screenshot/resize/profiler move onto the RHI, `OpenGLGraphicsDevice`'s live role retires, Chorizite consumers are audited, and the architecture test lands. **Milestone: seam complete.** | pixel + connected lifecycle + R6 soak + complete Release suite + interim perf (RHI-on-GL CPU p50 ≤ 1.95 ms) |
| **V4h** | Frame-spine formalization: pass executors emit real declared `BeginPass`/`EndPass` (clears and framebuffer management move out of the spine and into pass load/store ops), flight/screenshot/resize/profiler move onto the RHI, `OpenGLGraphicsDevice`'s live role retires, Chorizite consumers are audited, and the architecture test lands. **Milestone: seam complete.** | pixel + connected lifecycle + R6 soak + complete Release suite + interim perf (RHI-on-GL CPU p50 ≤ 1.95 ms) |
| **V5** | Vulkan bring-up, dark: `ACDREAM_RENDER_BACKEND`, surface/instance/device/queues/swapchain, the capability record/probe/guard with the exit-4 contract, a clear-colour loop with screenshot and clean shutdown. | VK boots to clear on the RX 9070 XT; forced-unsupported knob → exit 4 |
| **V6** | Vulkan RHI backend, dark, three sequential commits: **a** allocator/buffers/staging/rings/timeline; **b** textures/BC mips/samplers/descriptor table/render targets/MSAA resolve; **c** `.spv` toolchain, pipelines, pipeline cache, negative viewport, push constants, timestamps, readback, debug names. **Milestone: full game frame on Vulkan.** | per-commit build + tests; VK renders world, UI, paperdoll, portals |
| **V7** | GL-versus-Vulkan differential: `tools/run-backend-differential-gate.ps1`, strict paired-PNG compare, divergences fixed in the Vulkan backend only, then lifecycle + R6 soak natively on Vulkan, one validation-layer-clean run, one RenderDoc capture. **Milestone: parity.** | every differential checkpoint passes; both connected routes green on VK |

View file

@ -42,10 +42,15 @@ internal readonly record struct GpuDepthAttachment(
///
/// GL has no such object — its "pass" is implicit in whatever framebuffer happens
/// to be bound — so making passes explicit is the single largest structural change
/// the RHI imposes on the existing renderers. The GL backend therefore accepts an
/// ambient encoder during Campaign V slices V1..V4g (draws outside any declared
/// pass, preserving today's behaviour) and slice V4h removes that relaxation once
/// every renderer declares its passes.
/// the RHI imposes on the existing renderers.
///
/// The transitional path needs no special API. On GL, <c>BeginPass</c> binds the
/// target framebuffer and applies load ops, and deliberately does NOT touch
/// viewport or scissor — encoders set those explicitly. A renderer being ported
/// during Campaign V slices V4a..V4g therefore opens a pass with
/// <see cref="GpuLoadOp.Load"/> / <see cref="GpuStoreOp.Store"/> against the
/// backbuffer and gets exactly today's behaviour, while the frame spine still
/// owns clears and framebuffer management. Slice V4h converts the spine itself.
/// </summary>
internal sealed record GpuPassDescription
{