feat(render) Campaign FW2: OrderedDrawStream + walk-order submitter
The walk-order submission layer over the existing RHI (plan section FW2): - OrderedDrawStream: append-only walk-ordered draw commands (GroupKey + transform + per-instance data + WalkDrawStage + cell provenance), struct-of-arrays with one lockstep Reset (#193 shape). The PortalPunch stage exists but has no FW2 submission path - the submitter throws on it; punch emission lands with FW3 wiring. - WbDrawDispatcher.OrderedStream partial: per-instance-first emission (the deferred-alpha shape - command i owns instance i, walk order survives into the indirect array), each SSBO section written once, then one DrawIndirectRangeRhi call per maximal merge run. Runs are built by pure-CPU BuildOrderedMergeRuns and may never span a stage, pipeline-bucket, or cull boundary; ValidateMergeRun re-checks every emitted run and throws (the campaign fail-loud rule). Nothing is sorted, reordered, or dropped: N commands in, N indirect commands out, covered exactly once. - WorldDepthContract: retail world depth verified verbatim from the decomp - Render::zfuncVal @0x00820e1c = 0x2, SetDepthBufferMode @0x005a2d10 writes the enum directly as D3DRS_ZFUNC so the value IS D3DCMP_LESS, applied by the surface-state applier @0x0059c80a with Z-write toggled by blend; the LESSEQUAL sites are GameSky::Draw-local. Seven world pipeline sites now cite the named constant (no value changes). - Plan updated: FW1 status block + gate amendment (the ten pose-stamped retail traces supersede re-expressing the old-builder replay fixtures; those retire with the old builder at FW4 and their scenario classes re-verify at the FW3/FW4 connected gates). Known FW2 scope notes recorded in the code: the building-detail overlay replay is production wiring (FW3); the _drawCullModes scratch may not interleave with a mid-flight RetailAlphaQueue scope (FW3 sequencing constraint). The pixel A/B equivalence proof rides FW3's cutover toggle where a walk-driven scene first exists. Suites: full Release build 0 warnings; Walk lane 154/1 skip; hermetic 6,714/0 (+27 new). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
77f5342b62
commit
e65644cb33
12 changed files with 1461 additions and 31 deletions
47
src/AcDream.App/Rendering/WorldDepthContract.cs
Normal file
47
src/AcDream.App/Rendering/WorldDepthContract.cs
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
using AcDream.App.Rendering.Gpu;
|
||||
|
||||
namespace AcDream.App.Rendering;
|
||||
|
||||
/// <summary>
|
||||
/// Campaign FW stage FW2: the one depth-compare operator every world-space
|
||||
/// pipeline uses, named instead of repeated as a literal at each of the
|
||||
/// world's own pipeline-creation sites.
|
||||
///
|
||||
/// <para><b>Why <see cref="GpuCompareOp.Less"/>, not
|
||||
/// <see cref="GpuPipelineDescription"/>'s/<c>GpuDepthState</c>'s own
|
||||
/// <c>LessOrEqual</c> convention default:</b> the GL-era world frame ran under
|
||||
/// <c>GL_LESS</c> and never called <c>glDepthFunc</c> to change it, so every
|
||||
/// world-space renderer inherited <c>GL_LESS</c> by omission rather than by
|
||||
/// design. <c>LessOrEqual</c> would flip which of two exactly-coplanar retail
|
||||
/// surfaces wins the depth test — visible wherever terrain meets a road or a
|
||||
/// building footing, or wherever two retail-authored polygons share a plane.
|
||||
/// FW2's decomp verification (plan §FW2, read 2026-08-30) confirms retail's
|
||||
/// own world raster state is <c>D3DCMP_LESS</c>: the .data default
|
||||
/// <c>Render::zfuncVal</c> @0x00820e1c is <c>0x2</c>, and
|
||||
/// <c>RenderDeviceD3D::SetDepthBufferMode</c> @0x005a2d10 writes that enum
|
||||
/// value DIRECTLY as <c>D3DRS_ZFUNC</c> (render state 0x17) — the enum IS
|
||||
/// <c>D3DCMPFUNC</c>, so <c>0x2 = D3DCMP_LESS</c>. The surface-state applier
|
||||
/// @0x0059c80a–0x0059c866 applies it to all world geometry with Z-write
|
||||
/// toggled by blend state (on for opaque, off for blended), exactly this
|
||||
/// pipeline set's per-variant <c>depthWrite</c>. The <c>DEPTHTEST_LESSEQUAL</c>
|
||||
/// sites in the decomp are SKY-local (<c>GameSky::Draw</c> @0x00506ff0, drawn
|
||||
/// at 4× zfar) — never world state. So <c>Less</c> is not merely "what the
|
||||
/// port happened to inherit" — it is retail's actual world depth-compare
|
||||
/// operator, now named as a citable contract instead of a bare literal
|
||||
/// repeated at each call site.</para>
|
||||
///
|
||||
/// <para>Scope: WORLD-SPACE geometry only (terrain, EnvCell shells, entity
|
||||
/// meshes, particles, portal punches, the directional shadow caster/receiver
|
||||
/// pair). The two <c>RetailDetail</c> pipelines
|
||||
/// (<see cref="RetailDetailTextureContract"/>'s <c>Equal</c>/<c>LessOrEqual</c>
|
||||
/// pair, used by the building-detail overlay replay) are a documented
|
||||
/// exception with their own citation and are untouched by this contract.</para>
|
||||
/// </summary>
|
||||
internal static class WorldDepthContract
|
||||
{
|
||||
/// <summary>Retail's world-space depth-compare operator. See the type
|
||||
/// doc comment for the full citation; every world pipeline site should
|
||||
/// reference this constant rather than spelling <c>GpuCompareOp.Less</c>
|
||||
/// again.</summary>
|
||||
public const GpuCompareOp WorldCompare = GpuCompareOp.Less;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue