fix(render): S3 chunk 3 round 2 follow-up — the StreamMark pin now fires real StreamMarks

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 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-09-03 10:44:55 +02:00
parent 896c63fe9a
commit 74ac7aa227
2 changed files with 17 additions and 5 deletions

View file

@ -302,9 +302,10 @@ internal enum WalkFrameEventKind : byte
/// ONLY opaque batches, depth test AND write on, no blending, so opaque /// ONLY opaque batches, depth test AND write on, no blending, so opaque
/// terrain and opaque statics resolve identically in either submission /// terrain and opaque statics resolve identically in either submission
/// order. A particle turn whose cell has no renderable emitter submits /// order. A particle turn whose cell has no renderable emitter submits
/// nothing and keeps the batch open (fix round 1, F2). The GPU /// nothing and keeps the batch open (fix round 1, F2). The resolved image is therefore identical to replaying each cell
/// submission order is therefore identical to replaying each cell /// alone: every event whose GPU order against opaque terrain is
/// alone.</summary> /// observable still flushes first (§9.7 F10), and opaque-vs-opaque
/// order is depth-resolved.</summary>
LandCell, LandCell,
/// <summary><see cref="IWalkFrameLeafRenderer.DrawCellShell"/> — /// <summary><see cref="IWalkFrameLeafRenderer.DrawCellShell"/> —

View file

@ -1530,12 +1530,18 @@ public sealed class WalkFrameDriverTests
leaf.CellsWithoutEmitters.Add(0xAAAA0001u); leaf.CellsWithoutEmitters.Add(0xAAAA0001u);
leaf.CellsWithoutEmitters.Add(0xAAAA0002u); leaf.CellsWithoutEmitters.Add(0xAAAA0002u);
var ctx = new TestContext(); 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; IWalkEventSink sink = driver;
using DrawScope draw = fx.BeginDraw(); using DrawScope draw = fx.BeginDraw();
driver.BeginFrame(ctx, Matrix4x4.Identity, Vector3.Zero); 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.OnLandCellTurn(0xF4180000u, 8, 0); // landblock A
sink.OnLandscapeCellTurn(0xAAAA0001u); // empty particle turn: no growth, no emitters -> no submit, no flush (F2) 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( Assert.Equal(
new[] 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", "LANDCELL:f4180000:8:0,f3180000:8:0,f2180001:8:0",
"PARTICLES:bbbb0002", "PARTICLES:bbbb0002",
"LANDCELL:f3180000:8:1", "LANDCELL:f3180000:8:1",
@ -1572,6 +1580,9 @@ public sealed class WalkFrameDriverTests
log); log);
Assert.DoesNotContain("PARTICLES:aaaa0001", log); Assert.DoesNotContain("PARTICLES:aaaa0001", log);
Assert.DoesNotContain("PARTICLES:aaaa0002", 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(4, leaf.LandCellBatches.Count);
Assert.Equal( Assert.Equal(
new (uint LandblockId, int SideCellCount, int CellIndex)[] new (uint LandblockId, int SideCellCount, int CellIndex)[]