fix(render): draw look-in dynamics only at retail walk turns

This commit is contained in:
Erik 2026-08-31 03:22:01 +02:00
parent 572de1ec30
commit 966836895f
5 changed files with 84 additions and 37 deletions

View file

@ -193,10 +193,14 @@ public sealed class RenderScenePViewFrameProductTests
0x0100_0000_0000_0022,
RenderProjectionClass.LiveDynamicRoot,
parentCell: lookInCell);
RenderProjectionRecord outdoorDynamic = Record(
0x0100_0000_0000_0023,
RenderProjectionClass.LiveDynamicRoot);
scene.Apply(
[
RenderProjectionDelta.Register(Generation, 1, rootDynamic),
RenderProjectionDelta.Register(Generation, 2, lookInDynamic),
RenderProjectionDelta.Register(Generation, 3, outdoorDynamic),
]);
PortalVisibilityFrame portal = Portal(Cell);
@ -235,6 +239,18 @@ public sealed class RenderScenePViewFrameProductTests
.ToArray()
.Select(static record => record.Id));
RenderFrameCandidateRange outside = Assert.Single(
frame.RouteRanges.ToArray(),
range => range.Route
== RenderFrameCandidateRoute.LandscapeOutsideDynamic);
RenderProjectionId[] outsideIds = frame.RouteCandidates
.Slice(outside.Offset, outside.Count)
.ToArray()
.Select(static record => record.Id)
.ToArray();
Assert.Contains(outdoorDynamic.Id, outsideIds);
Assert.DoesNotContain(lookInDynamic.Id, outsideIds);
RenderFrameCandidateRange dynamicLast = Assert.Single(
frame.RouteRanges.ToArray(),
range => range.Route == RenderFrameCandidateRoute.DynamicLast);

View file

@ -25,7 +25,8 @@ namespace AcDream.App.Tests.Rendering.Walk;
/// Campaign FW stage FW3.2b-1: <see cref="WalkFrameDriver"/>'s headless
/// referee suite — proves that driving <see cref="RetailFrameWalk"/> with the
/// driver as its <see cref="IWalkEventSink"/> produces retail's own turn
/// order (shell-then-contents per cell, flush-before-every-leaf-action,
/// order (all shells then all contents in reverse flood order,
/// flush-before-every-leaf-action,
/// content-before-punch) through the REAL <see cref="WbDrawDispatcher.SubmitOrderedStream"/>
/// onto a <see cref="RecordingGpuDevice"/> — never a mock of the submission
/// path itself. No production wiring is exercised (<c>WorldSceneRenderer</c>
@ -172,10 +173,9 @@ public sealed class WalkFrameDriverTests
Plane = new WalkPlane(new Vector3(0, 0, facingViewer ? 1f : -1f), facingViewer ? -z : z),
};
// ── Deliverable: RunFrame drives an interior two-cell flood; shell
// precedes contents per cell, and a flush happens exactly at the point
// the NEXT cell's shell needs the stream clear (never before, never
// batched across cells within this stage's turn-by-turn discipline). ──
// ── Deliverable: RunFrame drives an interior two-cell flood using
// PView::DrawCells' exact two reverse loops: ALL shells far-to-near,
// then ALL object cells far-to-near. ─────────────────────────────────
// ── Deliverable (2026-08-30 decomp correction): PView::DrawCells
// @0x005a4840's actual DRAW order for an interior root's OWN flood is
@ -186,7 +186,7 @@ public sealed class WalkFrameDriverTests
// (pc:432785-432786), and ONLY THEN the flood's own cells far-to-near.
// This case has a surviving exit view (ov=1): DC records the flood list
// (no draw), the landscape turn runs (flush no-op, sky, terrain), THEN
// clear, seals, and the two flood cells shell-then-contents. ──────────
// clear, seals, then all shells and all contents in reverse order. ───
[Fact]
public void RunFrame_InteriorFloodWithExitView_DrawsLandscapeThenClearSealsThenFloodCells()
@ -258,7 +258,8 @@ public sealed class WalkFrameDriverTests
new[]
{
"SKY", "TERRAIN:0", "CLEAR", "SEALS",
"SHELL:00000100", "FLUSH:1:CellStatic", "SHELL:00000101", "FLUSH:1:CellStatic",
"SHELL:00000101", "SHELL:00000100",
"FLUSH:1:CellStatic", "FLUSH:1:CellStatic",
},
log);
@ -329,7 +330,11 @@ public sealed class WalkFrameDriverTests
// No SKY/TERRAIN — ov==0 means DrawInside never calls DrawLandscape
// at all — but CLEAR/SEALS still fire unconditionally.
Assert.Equal(
new[] { "CLEAR", "SEALS", "SHELL:00000100", "FLUSH:1:CellStatic", "SHELL:00000101", "FLUSH:1:CellStatic" },
new[]
{
"CLEAR", "SEALS", "SHELL:00000101", "SHELL:00000100",
"FLUSH:1:CellStatic", "FLUSH:1:CellStatic",
},
log);
List<GpuRecordedMultiDrawIndirect> mdiCalls =