feat(render) Campaign FW3.2b-2: the walk shadow probe (I5 pattern)

ACDREAM_PROBE_WALK_SHADOW=1 (documented row; throwaway - dies with the
flip commit) runs the PRODUCTION retail frame walk per frame in shadow
over the FW3.1 registries - WalkProductionFrameContext from the live
camera, SetViewer recentring, interior rooting via LoadedCell.Walk -
and prints one [walk-shadow] divergence line per frame whose visited
cell set differs from the old path (main flood + look-ins), plus a
loud PROBE FAULT line on any exception. No draws change. This is the
I5 dual-shadow pattern applied to the FW3 static cutover: it proves
the production walk world data live and quantifies old-vs-walk
divergence before any pixel moves. CellVisibility joins the renderer
plumbing as the walk cell registry.

Suites: full Release build 0 warnings; hermetic 6,753/0;
LaunchOptionsDocumentationTests green (both directions).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-08-30 14:47:15 +02:00
parent d80d47d611
commit 878533597d
4 changed files with 131 additions and 3 deletions

View file

@ -96,18 +96,21 @@ public sealed class RetailPViewRenderer
// Campaign FW3.2b-2: the walk's production world-data registries
// (published/retired by LandblockRenderPublisher) plus the per-frame
// driver state. Null until the composition passes them; the static
// cutover requires both.
// cutover requires all three.
private readonly Walk.WalkBuildingRegistry? _walkBuildings;
private readonly Walk.WalkLandscapeAssembler? _walkLandscape;
private readonly CellVisibility? _walkCellRegistry;
internal RetailPViewRenderer(
InteriorEntityPartition.IObserver? partitionObserver,
RenderScenePViewFrameProductController? sceneFrameProduct = null,
Walk.WalkBuildingRegistry? walkBuildings = null,
Walk.WalkLandscapeAssembler? walkLandscape = null)
Walk.WalkLandscapeAssembler? walkLandscape = null,
CellVisibility? walkCellRegistry = null)
{
_walkBuildings = walkBuildings;
_walkLandscape = walkLandscape;
_walkCellRegistry = walkCellRegistry;
_partitionObserver = partitionObserver;
_candidateObserver = partitionObserver as ICurrentRenderPViewObserver;
_sceneFrameProduct = sceneFrameProduct;
@ -293,6 +296,13 @@ public sealed class RetailPViewRenderer
partition);
passes.EmitDiagnostics(ctx, result);
// Campaign FW3.2b-2 flip apparatus (ACDREAM_PROBE_WALK_SHADOW=1,
// throwaway — dies with the flip commit): run the PRODUCTION
// retail frame walk in shadow and report set divergence vs this
// frame's old-path visibility. No draws change.
if (AcDream.Core.Rendering.RenderingDiagnostics.ProbeWalkShadowEnabled)
RunWalkShadowProbe(ctx, prepareCells);
// #118: stage assignment for dynamics under an INTERIOR root. Retail
// draws the OUTSIDE world's objects inside the landscape stage —
// PView::DrawCells runs LScape::draw FIRST (pc:432719), then the gated
@ -870,6 +880,111 @@ public sealed class RetailPViewRenderer
}
}
/// <summary>Campaign FW3.2b-2 flip apparatus (the I5 dual-shadow
/// pattern): drive the production walk over the FW3.1 registries with a
/// set-collecting sink and print one <c>[walk-shadow]</c> line per frame
/// whose visited cells diverge from the old path's
/// <paramref name="oldPathCells"/> (main flood look-ins). Divergence is
/// EXPECTED where the walk's retail model deliberately differs from the
/// old builder — the probe's value is proving the production data
/// pipeline live and QUANTIFYING the difference for the flip review. A
/// probe exception prints loudly and never kills the frame (it is the
/// probe's own signal, not a production fault).</summary>
private void RunWalkShadowProbe(
RetailPViewFrameInput ctx, HashSet<uint> oldPathCells)
{
if (_walkBuildings is null || _walkLandscape is null
|| _walkCellRegistry is null)
{
return;
}
try
{
// Forward = -(view column 3): System.Numerics CreateLookAt's
// zaxis is eye-target (backward). Viewport: the walk's SETS are
// viewport-scale-tolerant (every screen projection shares the
// same constants), so the shadow pins retail's capture size; the
// flip itself will use the real attachment extent.
Matrix4x4 view = ctx.CameraView;
var forward = Vector3.Normalize(new Vector3(-view.M13, -view.M23, -view.M33));
var context = new Walk.WalkProductionFrameContext(
_walkCellRegistry,
_walkBuildings,
ctx.ViewerEyePos,
forward,
ctx.ViewProjection,
viewportWidth: 1024f,
viewportHeight: 720f);
Walk.WalkLandscape landscape = _walkLandscape.Landscape;
_walkLandscape.SetViewer(ctx.ViewerCellId, ctx.ViewerEyePos);
Walk.WalkCell? cameraCell = null;
if ((ctx.ViewerCellId & 0xFFFFu) >= 0x100)
{
cameraCell = _walkCellRegistry.TryGetCell(ctx.ViewerCellId, out LoadedCell? loaded)
? loaded?.Walk
: null;
if (cameraCell is null)
{
Console.WriteLine(
$"[walk-shadow] root={ctx.ViewerCellId:x8} interior camera cell has no walk data");
return;
}
}
var sink = new WalkShadowSink();
_walkShadowFrameWalk.WalkFrame(
ctx.ViewerCellId, cameraCell, landscape, context, sink);
int onlyWalk = 0;
foreach (uint id in sink.Cells)
if (!oldPathCells.Contains(id))
onlyWalk++;
int onlyOld = 0;
foreach (uint id in oldPathCells)
if (!sink.Cells.Contains(id))
onlyOld++;
if (onlyWalk != 0 || onlyOld != 0)
{
Console.WriteLine(
$"[walk-shadow] root={ctx.ViewerCellId:x8} walkCells={sink.Cells.Count} "
+ $"oldCells={oldPathCells.Count} onlyWalk={onlyWalk} onlyOld={onlyOld} "
+ $"walkBuildings={sink.BuildingCount} landscapeTurns={sink.LandscapeCount}");
}
}
catch (Exception failure)
{
Console.WriteLine($"[walk-shadow] PROBE FAULT root={ctx.ViewerCellId:x8}: {failure}");
}
}
private readonly Walk.RetailFrameWalk _walkShadowFrameWalk = new();
private sealed class WalkShadowSink : Walk.IWalkEventSink
{
public readonly HashSet<uint> Cells = new();
public int BuildingCount;
public int LandscapeCount;
public void Emit(in Walk.WalkEvent walkEvent)
{
switch (walkEvent.Kind)
{
case Walk.WalkEventKind.DrawInside:
Cells.Add(walkEvent.CellId);
break;
case Walk.WalkEventKind.DrawCells:
foreach (uint id in walkEvent.Cells)
Cells.Add(id);
break;
case Walk.WalkEventKind.Building:
BuildingCount++;
break;
case Walk.WalkEventKind.Landscape:
LandscapeCount++;
break;
}
}
}
private void DrawLandscapeThroughOutsideView(
RetailPViewFrameInput ctx,
IRetailPViewPassExecutor passes,