feat(render) Campaign FW3.2a: the walk-to-draw population layer
The piece that turns walk-visited static content into draws, with no production frame wiring (FW3.2b roots the frame): - TryClassifyBatch: ONE shared per-batch classify core (the #426 untextured gate, #188 opacity promotion, texture resolve, foliage classification, in the exact original order) extracted from ClassifyBatches; the classic and packed classifiers now call it - behavior-identical, proven by the full hermetic + InstalledDat + Core Wb suites. - ClassifyEntityForWalk / WalkClassifiedBatch: the per-entity seam yielding per-batch keys + instance data WITHOUT InstanceGroup bucketing, plus the per-part selection data (picking stays alive on the walk path - the survey's unlisted-consumer fix). - WalkStaticStreamPopulator: per-entity walk-ordered opaque appends (under depth Less, opaque order is pixel-relevant only for coplanar surfaces, which retail resolves first-drawn-wins in ITS order - never material-grouped), translucent instances to the SAME RetailAlphaQueue via SubmitWalkAlphaInstance (identical viewer distances; walk-order submission improves retail's tie fidelity), selection parts published per entity. - SubmitOrderedStream now owns _orderedDrawCullModes, retiring the FW2-recorded alpha-scope interleaving constraint; DrawIndirectRangeRhi takes an optional cull array (all existing call sites unchanged). The referee test was verified to FAIL against the old shared-scratch behavior. - WalkDrawStage.OutdoorStatic added for the landscape turn. Suites: full Release build 0 warnings; Walk lane 195/1 skip; hermetic 6,747/0 (the two failures the implementation round reported were transient - both pass in isolation and in the full run). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
b10ad662b0
commit
81c6531727
9 changed files with 1264 additions and 116 deletions
|
|
@ -253,14 +253,14 @@ public sealed unsafe partial class WbDrawDispatcher
|
|||
|
||||
// Per-instance-first emission — the PrepareDeferredAlphaDraws shape,
|
||||
// into the SAME per-frame scratch arrays PrepareDeferredAlphaDraws/
|
||||
// SubmitRhi write. Most are consumed immediately by the ring uploads
|
||||
// below, but _drawCullModes is NOT write-then-consume: the deferred-
|
||||
// alpha path reads it at FLUSH time (DrawIndirectRangeRhi's internal
|
||||
// cull split), so an ordered submission may never interleave between
|
||||
// RetailAlphaQueue prepare and flush. FW2 has no production caller;
|
||||
// the FW3 wiring must either sequence around the alpha scope or give
|
||||
// this path its own cull scratch.
|
||||
// SubmitRhi write, EXCEPT cull modes: this stage (FW3.2a) gives the
|
||||
// ordered path its own _orderedDrawCullModes scratch (see
|
||||
// DrawIndirectRangeRhi's doc comment) precisely so this loop and its
|
||||
// draws below can freely interleave with a mid-flight
|
||||
// RetailAlphaQueue scope without corrupting — or being corrupted by
|
||||
// — the alpha path's _drawCullModes.
|
||||
EnsureDeferredAlphaCapacity(count);
|
||||
EnsureOrderedCullModeCapacity(count);
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
GroupKey key = stream.Keys[i];
|
||||
|
|
@ -286,7 +286,7 @@ public sealed unsafe partial class WbDrawDispatcher
|
|||
BaseVertex = key.BaseVertex,
|
||||
BaseInstance = (uint)i,
|
||||
};
|
||||
_drawCullModes[i] = key.CullMode;
|
||||
_orderedDrawCullModes[i] = key.CullMode;
|
||||
}
|
||||
|
||||
// Write every section ONCE — the PrepareRhiAlphaSections shape, but
|
||||
|
|
@ -350,10 +350,10 @@ public sealed unsafe partial class WbDrawDispatcher
|
|||
|
||||
// One in-order pass over the pre-built merge runs: bind the run's
|
||||
// pipeline, set RenderPass, draw. DrawIndirectRangeRhi still splits
|
||||
// internally on _drawCullModes (issue #52's absolute DrawIdOffset per
|
||||
// sub-call) — every run here already shares one cull mode by
|
||||
// construction, so that inner split is a no-op here, never a second
|
||||
// boundary this loop failed to expect.
|
||||
// internally on _orderedDrawCullModes (issue #52's absolute
|
||||
// DrawIdOffset per sub-call) — every run here already shares one
|
||||
// cull mode by construction, so that inner split is a no-op here,
|
||||
// never a second boundary this loop failed to expect.
|
||||
foreach (OrderedMergeRun run in runs)
|
||||
{
|
||||
ValidateMergeRun(stream, run);
|
||||
|
|
@ -365,7 +365,20 @@ public sealed unsafe partial class WbDrawDispatcher
|
|||
BindPipelineWithMesh(encoder, pipeline, global);
|
||||
DrawIndirectRangeRhi(
|
||||
encoder, ref pushConstants, commandBuffer, commandBase,
|
||||
run.FirstCommand, run.CommandCount);
|
||||
run.FirstCommand, run.CommandCount, _orderedDrawCullModes);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Grows <see cref="_orderedDrawCullModes"/> to at least
|
||||
/// <paramref name="count"/> — the same growth shape
|
||||
/// <c>EnsureDeferredAlphaCapacity</c> uses for <see cref="_drawCullModes"/>,
|
||||
/// kept as its own method because this scratch array is not part of that
|
||||
/// method's shared per-instance group (see this file's type doc comment).
|
||||
/// </summary>
|
||||
private void EnsureOrderedCullModeCapacity(int count)
|
||||
{
|
||||
if (_orderedDrawCullModes.Length < count)
|
||||
_orderedDrawCullModes = new CullMode[count + 64];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue