From 74ac7aa227d9b09e71636a3ff03db32d4ba1d8fd Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 3 Sep 2026 10:44:55 +0200 Subject: [PATCH] =?UTF-8?q?fix(render):=20S3=20chunk=203=20round=202=20fol?= =?UTF-8?q?low-up=20=E2=80=94=20the=20StreamMark=20pin=20now=20fires=20rea?= =?UTF-8?q?l=20StreamMarks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The re-expressed F4(c) pin installed an empty landscape view, so nothing classified visible, the ordered stream never grew, and no StreamMark fired: the one behavior round 2 changes was unpinned (review finding). The test now installs a real full-viewport view and records the trace, asserting two FLUSH lines ahead of the merged three-cell terrain batch. The LandCell doc no longer claims an identical submission order; the resolved image is identical (opaque-vs-opaque order is depth-resolved, every observable order still flushes first). Co-Authored-By: Claude Fable 5.1 --- src/AcDream.App/Rendering/Walk/WalkFrameDriver.cs | 7 ++++--- .../Rendering/Walk/WalkFrameDriverTests.cs | 15 +++++++++++++-- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/AcDream.App/Rendering/Walk/WalkFrameDriver.cs b/src/AcDream.App/Rendering/Walk/WalkFrameDriver.cs index 76192c47..4ba65a75 100644 --- a/src/AcDream.App/Rendering/Walk/WalkFrameDriver.cs +++ b/src/AcDream.App/Rendering/Walk/WalkFrameDriver.cs @@ -302,9 +302,10 @@ internal enum WalkFrameEventKind : byte /// ONLY opaque batches, depth test AND write on, no blending, so opaque /// terrain and opaque statics resolve identically in either submission /// order. A particle turn whose cell has no renderable emitter submits - /// nothing and keeps the batch open (fix round 1, F2). The GPU - /// submission order is therefore identical to replaying each cell - /// alone. + /// nothing and keeps the batch open (fix round 1, F2). The resolved image is therefore identical to replaying each cell + /// alone: every event whose GPU order against opaque terrain is + /// observable still flushes first (§9.7 F10), and opaque-vs-opaque + /// order is depth-resolved. LandCell, /// — diff --git a/tests/AcDream.App.Tests/Rendering/Walk/WalkFrameDriverTests.cs b/tests/AcDream.App.Tests/Rendering/Walk/WalkFrameDriverTests.cs index 0ff7f4dc..f31d4306 100644 --- a/tests/AcDream.App.Tests/Rendering/Walk/WalkFrameDriverTests.cs +++ b/tests/AcDream.App.Tests/Rendering/Walk/WalkFrameDriverTests.cs @@ -1530,12 +1530,18 @@ public sealed class WalkFrameDriverTests leaf.CellsWithoutEmitters.Add(0xAAAA0001u); leaf.CellsWithoutEmitters.Add(0xAAAA0002u); var ctx = new TestContext(); - var driver = new WalkFrameDriver(fx.Dispatcher, leaf, worldData); + var driver = new WalkFrameDriver(fx.Dispatcher, leaf, worldData, new RecordingTrace(log)); IWalkEventSink sink = driver; using DrawScope draw = fx.BeginDraw(); driver.BeginFrame(ctx, Matrix4x4.Identity, Vector3.Zero); - sink.OnLandscapeViews(new WalkPortalView()); + // A REAL full-viewport landscape view: with an empty view the classifier + // admits nothing, the stream never grows, and no StreamMark ever fires + // (the round-2 review caught exactly that vacuity). + var landscapeViews = new WalkPortalView(); + WalkCopyView.AppendFullViewportQuad( + landscapeViews, ctx.Rays, ctx.WorldViewpoint, ctx.ViewportWidth, ctx.ViewportHeight); + sink.OnLandscapeViews(landscapeViews); sink.OnLandCellTurn(0xF4180000u, 8, 0); // landblock A sink.OnLandscapeCellTurn(0xAAAA0001u); // empty particle turn: no growth, no emitters -> no submit, no flush (F2) @@ -1561,6 +1567,8 @@ public sealed class WalkFrameDriverTests Assert.Equal( new[] { + "FLUSH:1:OutdoorStatic", // 0xAAAA0002's statics: the StreamMark draws its range but does NOT flush the terrain batch (F10) + "FLUSH:1:OutdoorStatic", // 0xBBBB0002's statics: same "LANDCELL:f4180000:8:0,f3180000:8:0,f2180001:8:0", "PARTICLES:bbbb0002", "LANDCELL:f3180000:8:1", @@ -1572,6 +1580,9 @@ public sealed class WalkFrameDriverTests log); Assert.DoesNotContain("PARTICLES:aaaa0001", log); Assert.DoesNotContain("PARTICLES:aaaa0002", log); + // Two genuine StreamMarks fired (the ordered stream grew twice) — the + // F10 rule is exercised, not assumed. + Assert.Equal(2, log.Count(entry => entry.StartsWith("FLUSH:", StringComparison.Ordinal))); Assert.Equal(4, leaf.LandCellBatches.Count); Assert.Equal( new (uint LandblockId, int SideCellCount, int CellIndex)[]