checkpoint(render): preserve pre-overhaul investigation state

This commit is contained in:
Erik 2026-09-01 18:04:24 +02:00
parent e880860291
commit b3b7d922f1
45 changed files with 3168 additions and 619 deletions

View file

@ -45,16 +45,16 @@ public sealed class WalkFrameDriverTests
RetailAlphaQueue? alpha = null) : IWalkFrameLeafRenderer
{
public readonly List<WalkPolygon> Punches = new();
public readonly List<(uint CellId, uint ClipSlot)> Shells = new();
public readonly List<uint> Shells = new();
public readonly List<int> AlphaPendingAtBarrier = new();
public void DrawSky() => log.Add("SKY");
public void DrawTerrainSlice(int sliceIndex) => log.Add($"TERRAIN:{sliceIndex}");
public void DrawCellShell(uint cellId, uint clipSlot)
public void DrawCellShell(uint cellId)
{
Shells.Add((cellId, clipSlot));
Shells.Add(cellId);
log.Add($"SHELL:{cellId:x8}");
}
@ -267,7 +267,9 @@ public sealed class WalkFrameDriverTests
var leaf = new RecordingLeafRenderer(log);
var trace = new RecordingTrace(log);
var driver = new WalkFrameDriver(fx.Dispatcher, leaf, worldData, trace);
using ClipFrame clipFrame = ClipFrame.NoClip();
var driver = new WalkFrameDriver(
fx.Dispatcher, leaf, worldData, trace, clipFrame);
var walk = new RetailFrameWalk();
// A minimal, no-op landscape (1x1 window, the one slot unpublished)
// — matches RetailFrameWalkTests' own exit-view fixture. LScape::draw
@ -296,6 +298,79 @@ public sealed class WalkFrameDriverTests
Assert.All(mdiCalls, c => Assert.Equal(1u, c.DrawCount));
// Nothing dropped: every populated record reached exactly one indirect draw.
Assert.Equal(2, mdiCalls.Sum(c => (int)c.DrawCount));
// Exit seals replay through the exact portal_view slices captured by
// this walk. The legacy PortalVisibilityFrame is not consulted.
Assert.Equal(1, driver.InteriorFloodViewSliceCountAt(0));
Assert.Equal(1, driver.InteriorFloodViewSliceCountAt(1));
Assert.Equal(4, driver.InteriorFloodViewClipPlanesAt(0, 0).Length);
Assert.Equal(4, driver.InteriorFloodViewClipPlanesAt(1, 0).Length);
Assert.True(clipFrame.SlotCount >= 3);
}
[Fact]
public void InteriorFloodAfterLandscape_RearmsRetailPartStampForPostClearCellRepaint()
{
using var fx = new DispatcherFixture();
var log = new List<string>();
const ulong gfxObj = 0x0200_0021UL;
const uint outdoorCellId = 0xF4180009u;
const uint interiorCellId = 0xF4180112u;
InjectRenderData(fx.Manager, gfxObj, MakeFlatMesh(
MakeBatch(0x08100021u, TranslucencyKind.Opaque, 0, 0, 3, 1)));
RenderProjectionRecord sharedPart = MakeRecord(
0x4F41806Cu,
0,
Vector3.Zero,
[new MeshRef((uint)gfxObj, Matrix4x4.Identity)]);
var worldData = new FakeWorldData();
worldData.OutdoorStaticsByCell[outdoorCellId] =
new WalkFrameStaticRecords(new[] { sharedPart }, 0xF418u);
worldData.CellStaticsByCell[interiorCellId] =
new WalkFrameStaticRecords(new[] { sharedPart }, 0xF418u);
var ctx = new TestContext();
var interiorCell = new WalkCell { CellId = interiorCellId };
interiorCell.PushView();
WalkCopyView.AppendFullViewportQuad(
interiorCell.TopView,
ctx.Rays,
ctx.WorldViewpoint,
ctx.ViewportWidth,
ctx.ViewportHeight);
ctx.Cells[interiorCellId] = interiorCell;
var driver = new WalkFrameDriver(
fx.Dispatcher,
new RecordingLeafRenderer(log),
worldData,
new RecordingTrace(log));
IWalkEventSink sink = driver;
using DrawScope draw = fx.BeginDraw();
driver.BeginFrame(ctx, Matrix4x4.Identity, Vector3.Zero);
sink.Emit(WalkEvent.Landscape(activeViewCount: 1));
var landscapeViews = new WalkPortalView();
WalkCopyView.AppendFullViewportQuad(
landscapeViews,
ctx.Rays,
ctx.WorldViewpoint,
ctx.ViewportWidth,
ctx.ViewportHeight);
sink.OnLandscapeViews(landscapeViews);
sink.OnLandscapeCellTurn(outdoorCellId);
sink.OnInteriorFloodDrawTurn([interiorCellId]);
driver.EndFrame();
driver.Replay(draw.Frame, draw.Pass);
List<GpuRecordedMultiDrawIndirect> mdiCalls =
[.. fx.Device.Calls.OfType<GpuRecordedMultiDrawIndirect>()];
Assert.Equal(2, mdiCalls.Count);
Assert.All(mdiCalls, call => Assert.Equal(1u, call.DrawCount));
Assert.Equal(2, mdiCalls.Sum(call => (int)call.DrawCount));
Assert.Equal(2, log.Count(entry => entry == "FLUSH:1:OutdoorStatic"
|| entry == "FLUSH:1:CellStatic"));
}
// ── Deliverable: the ov==0 interior case — no exit view survives, so
@ -479,11 +554,7 @@ public sealed class WalkFrameDriverTests
Assert.Equal([0x104u], driver.LookInCells);
Assert.Collection(
leaf.Shells,
shell =>
{
Assert.Equal(0x104u, shell.CellId);
Assert.NotEqual(0u, shell.ClipSlot);
});
shell => Assert.Equal(0x104u, shell));
WalkPortalView capturedView = ctx.Cells[0x104].PortalViews[0];
WalkViewPoly capturedPoly = Assert.Single(capturedView.View.Polys);
Vector2 capturedCenter = Vector2.Zero;
@ -515,6 +586,101 @@ public sealed class WalkFrameDriverTests
Assert.Equal(3, mdiCalls.Sum(c => (int)c.DrawCount));
}
[Fact]
public void RepeatedFloodTurns_DrawEnvCellShellWholeOncePerRetailFrameStamp()
{
using var fx = new DispatcherFixture();
var log = new List<string>();
var leaf = new RecordingLeafRenderer(log);
var ctx = new TestContext();
const uint cellId = 0xF4180112u;
var cell = new WalkCell { CellId = cellId };
cell.PushView();
WalkCopyView.AppendFullViewportQuad(
cell.TopView,
ctx.Rays,
ctx.WorldViewpoint,
ctx.ViewportWidth,
ctx.ViewportHeight);
ctx.Cells[cellId] = cell;
var driver = new WalkFrameDriver(
fx.Dispatcher,
leaf,
new FakeWorldData());
IWalkEventSink sink = driver;
using DrawScope draw = fx.BeginDraw();
driver.BeginFrame(ctx, Matrix4x4.Identity, Vector3.Zero);
sink.OnInteriorFloodDrawTurn([cellId]);
sink.OnInteriorFloodDrawTurn([cellId]);
driver.EndFrame();
driver.Replay(draw.Frame, draw.Pass);
Assert.Equal([cellId], leaf.Shells);
Assert.Equal(1, log.Count(entry => entry == "SHELL:f4180112"));
Assert.Equal(2, log.Count(entry => entry == "CLEAR"));
Assert.Equal(2, log.Count(entry => entry == "SEALS"));
}
[Fact]
public void LandscapeStampBoundary_RearmsWholeShellForPostClearRootRepaint()
{
using var fx = new DispatcherFixture();
var log = new List<string>();
var leaf = new RecordingLeafRenderer(log);
var ctx = new TestContext();
const uint cellId = 0xF4180112u;
var cell = new WalkCell { CellId = cellId };
cell.PushView();
WalkCopyView.AppendFullViewportQuad(
cell.TopView,
ctx.Rays,
ctx.WorldViewpoint,
ctx.ViewportWidth,
ctx.ViewportHeight);
ctx.Cells[cellId] = cell;
var driver = new WalkFrameDriver(
fx.Dispatcher,
leaf,
new FakeWorldData());
IWalkEventSink sink = driver;
using DrawScope draw = fx.BeginDraw();
driver.BeginFrame(ctx, Matrix4x4.Identity, Vector3.Zero);
// LScape::draw has begun. A building look-in reached this cell before
// PView::DrawCells advances m_nFrameStamp and clears interior depth.
sink.Emit(WalkEvent.Landscape(activeViewCount: 1));
var landscapeViews = new WalkPortalView();
WalkCopyView.AppendFullViewportQuad(
landscapeViews,
ctx.Rays,
ctx.WorldViewpoint,
ctx.ViewportWidth,
ctx.ViewportHeight);
sink.OnLandscapeViews(landscapeViews);
sink.OnBuildingTurn(new WalkBuilding());
sink.Emit(WalkEvent.DrawCells(outsideViewCount: 0, [cellId]));
// The same shell must draw again after the retail stamp increment and
// full depth clear; otherwise the pre-clear color survives unpaired
// with depth and bleeds through the root's walls.
sink.OnInteriorFloodDrawTurn([cellId]);
driver.EndFrame();
driver.Replay(draw.Frame, draw.Pass);
Assert.Equal([cellId, cellId], leaf.Shells);
Assert.Equal(2, log.Count(entry => entry == "SHELL:f4180112"));
Assert.True(
log.IndexOf("SHELL:f4180112") < log.IndexOf("CLEAR"),
"The look-in shell must precede the interior clear.");
Assert.True(
log.LastIndexOf("SHELL:f4180112") > log.IndexOf("SEALS"),
"The rearmed root shell must repaint after the clear and seals.");
}
// ── Fail-loud: a DrawCells turn with no preceding DrawInside/Building
// turn is a walk/driver desync, not a silent skip. ─────────────────────