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:
parent
d80d47d611
commit
878533597d
4 changed files with 131 additions and 3 deletions
|
|
@ -314,6 +314,7 @@ issue is closed, the strip was missed; delete both.
|
||||||
| `ACDREAM_PROBE_CELL_CACHE` | indoor walking phase d | `=1` | gates one `[cell-cache]` line per EnvCell first-cached in `PhysicsDataCache.CacheCellStruct` (poly counts, BSP root structure) | print-only; fires at most once per EnvCell (cache is no-op after first population); no DebugPanel mirror | `PhysicsDiagnostics.ProbeCellCacheEnabled` |
|
| `ACDREAM_PROBE_CELL_CACHE` | indoor walking phase d | `=1` | gates one `[cell-cache]` line per EnvCell first-cached in `PhysicsDataCache.CacheCellStruct` (poly counts, BSP root structure) | print-only; fires at most once per EnvCell (cache is no-op after first population); no DebugPanel mirror | `PhysicsDiagnostics.ProbeCellCacheEnabled` |
|
||||||
| `ACDREAM_PROBE_CHILD_CELL` | c4 route 7 | `=1` | gates one `[child-cell]` line per Runtime committed-child canonical-cell write in `RuntimeLiveEntitySessionController`, `RuntimeEntityObjectLifetime`, `RuntimeEntityDirectory` (parent/child guid, old/new cell, cause tag) | print-only | `PhysicsDiagnostics.ProbeChildCellEnabled` |
|
| `ACDREAM_PROBE_CHILD_CELL` | c4 route 7 | `=1` | gates one `[child-cell]` line per Runtime committed-child canonical-cell write in `RuntimeLiveEntitySessionController`, `RuntimeEntityObjectLifetime`, `RuntimeEntityDirectory` (parent/child guid, old/new cell, cause tag) | print-only | `PhysicsDiagnostics.ProbeChildCellEnabled` |
|
||||||
| `ACDREAM_PROBE_CLIPROUTE` | "throwaway apparatus — strip once §4 ships" | `=1` | print-on-change `[clip-route]` / `[clip-route-disp]` / `[clip-route-scis]` lines: outside-slice clip routing, region-SSBO bytes, terrain-UBO head, actual GL/RHI scissor state | print-only | `RenderingDiagnostics.ProbeClipRouteEnabled` |
|
| `ACDREAM_PROBE_CLIPROUTE` | "throwaway apparatus — strip once §4 ships" | `=1` | print-on-change `[clip-route]` / `[clip-route-disp]` / `[clip-route-scis]` lines: outside-slice clip routing, region-SSBO bytes, terrain-UBO head, actual GL/RHI scissor state | print-only | `RenderingDiagnostics.ProbeClipRouteEnabled` |
|
||||||
|
| `ACDREAM_PROBE_WALK_SHADOW` | Campaign FW3.2b-2 flip apparatus — dies with the flip commit | `=1` | runs the PRODUCTION retail frame walk per frame in SHADOW (no draws change) and prints one `[walk-shadow]` line per frame whose visited cell/building sets diverge from the old visibility path (the I5 dual-shadow pattern applied to the FW3 static cutover) | print-only; adds the per-frame CPU cost of the shadow walk while set | `RenderingDiagnostics.ProbeWalkShadowEnabled` |
|
||||||
| `ACDREAM_PROBE_CONTACT_PLANE` | spike-only, 2026-05-20 | `=1` | gates one `[cp-write]` line per write to `CollisionInfo.ContactPlane*`/`LastKnownContactPlane*` fields (field, old→new, caller method via stack walk, source line); only logs on actual value changes | print-only, but performs a stack walk to identify the caller method when firing — real CPU cost per write while on (not just a string format); suppresses no-op writes to bound volume | `PhysicsDiagnostics.ProbeContactPlaneEnabled` |
|
| `ACDREAM_PROBE_CONTACT_PLANE` | spike-only, 2026-05-20 | `=1` | gates one `[cp-write]` line per write to `CollisionInfo.ContactPlane*`/`LastKnownContactPlane*` fields (field, old→new, caller method via stack walk, source line); only logs on actual value changes | print-only, but performs a stack walk to identify the caller method when firing — real CPU cost per write while on (not just a string format); suppresses no-op writes to bound volume | `PhysicsDiagnostics.ProbeContactPlaneEnabled` |
|
||||||
| `ACDREAM_PROBE_ENT` | #138 | `="1"` | Traces the persistent player entity across teleport streaming churn: presence in the render draw-set flat view vs. survival of the dynamics cull, to distinguish "missing from draw set" vs "present but culled" | print-only, "Observation-only — emits no behavior change" (doc comment). `LogPlayerDynOnChange` dedupes by transition to avoid per-frame spam. Marked STRIP-once-root-caused (like the dense-town FPS apparatus). | `EntityVanishProbe.Enabled` (`EntityVanishProbe.cs:23-24`), issue #138-B |
|
| `ACDREAM_PROBE_ENT` | #138 | `="1"` | Traces the persistent player entity across teleport streaming churn: presence in the render draw-set flat view vs. survival of the dynamics cull, to distinguish "missing from draw set" vs "present but culled" | print-only, "Observation-only — emits no behavior change" (doc comment). `LogPlayerDynOnChange` dedupes by transition to avoid per-frame spam. Marked STRIP-once-root-caused (like the dense-town FPS apparatus). | `EntityVanishProbe.Enabled` (`EntityVanishProbe.cs:23-24`), issue #138-B |
|
||||||
| `ACDREAM_PROBE_FLAP` | "throwaway apparatus — strip once the flap mechanism is confirmed" | `=1` | EVERY FRAME (unthrottled, not change-gated) while the camera root is indoor: `[flap]` from `PortalVisibilityBuilder.Build` (portal side-test/traverse/cull/projection) + paired `[flap-cam]` from `PhysicsCameraCollisionProbe`/`[flap-sweep]` (FindCameraCell resolution, eye positions) | print-only, but unthrottled per-frame `StringBuilder` allocation + `Console.WriteLine` on multiple call sites while indoor — heavy log volume/allocation under sustained indoor play; does not alter rendered output | `RenderingDiagnostics.ProbeFlapEnabled` |
|
| `ACDREAM_PROBE_FLAP` | "throwaway apparatus — strip once the flap mechanism is confirmed" | `=1` | EVERY FRAME (unthrottled, not change-gated) while the camera root is indoor: `[flap]` from `PortalVisibilityBuilder.Build` (portal side-test/traverse/cull/projection) + paired `[flap-cam]` from `PhysicsCameraCollisionProbe`/`[flap-sweep]` (FindCameraCell resolution, eye positions) | print-only, but unthrottled per-frame `StringBuilder` allocation + `Console.WriteLine` on multiple call sites while indoor — heavy log volume/allocation under sustained indoor play; does not alter rendered output | `RenderingDiagnostics.ProbeFlapEnabled` |
|
||||||
|
|
|
||||||
|
|
@ -517,7 +517,8 @@ internal sealed class FrameRootCompositionPhase
|
||||||
// data, published/retired with each landblock by the
|
// data, published/retired with each landblock by the
|
||||||
// render publisher (FW3.1).
|
// render publisher (FW3.1).
|
||||||
live.LandblockPipeline.RenderPublisher?.WalkBuildings,
|
live.LandblockPipeline.RenderPublisher?.WalkBuildings,
|
||||||
live.LandblockPipeline.RenderPublisher?.WalkLandscape),
|
live.LandblockPipeline.RenderPublisher?.WalkLandscape,
|
||||||
|
d.CellVisibility),
|
||||||
retailPViewPassExecutor,
|
retailPViewPassExecutor,
|
||||||
retailPViewPassExecutor),
|
retailPViewPassExecutor),
|
||||||
retailPViewCells,
|
retailPViewCells,
|
||||||
|
|
|
||||||
|
|
@ -96,18 +96,21 @@ public sealed class RetailPViewRenderer
|
||||||
// Campaign FW3.2b-2: the walk's production world-data registries
|
// Campaign FW3.2b-2: the walk's production world-data registries
|
||||||
// (published/retired by LandblockRenderPublisher) plus the per-frame
|
// (published/retired by LandblockRenderPublisher) plus the per-frame
|
||||||
// driver state. Null until the composition passes them; the static
|
// 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.WalkBuildingRegistry? _walkBuildings;
|
||||||
private readonly Walk.WalkLandscapeAssembler? _walkLandscape;
|
private readonly Walk.WalkLandscapeAssembler? _walkLandscape;
|
||||||
|
private readonly CellVisibility? _walkCellRegistry;
|
||||||
|
|
||||||
internal RetailPViewRenderer(
|
internal RetailPViewRenderer(
|
||||||
InteriorEntityPartition.IObserver? partitionObserver,
|
InteriorEntityPartition.IObserver? partitionObserver,
|
||||||
RenderScenePViewFrameProductController? sceneFrameProduct = null,
|
RenderScenePViewFrameProductController? sceneFrameProduct = null,
|
||||||
Walk.WalkBuildingRegistry? walkBuildings = null,
|
Walk.WalkBuildingRegistry? walkBuildings = null,
|
||||||
Walk.WalkLandscapeAssembler? walkLandscape = null)
|
Walk.WalkLandscapeAssembler? walkLandscape = null,
|
||||||
|
CellVisibility? walkCellRegistry = null)
|
||||||
{
|
{
|
||||||
_walkBuildings = walkBuildings;
|
_walkBuildings = walkBuildings;
|
||||||
_walkLandscape = walkLandscape;
|
_walkLandscape = walkLandscape;
|
||||||
|
_walkCellRegistry = walkCellRegistry;
|
||||||
_partitionObserver = partitionObserver;
|
_partitionObserver = partitionObserver;
|
||||||
_candidateObserver = partitionObserver as ICurrentRenderPViewObserver;
|
_candidateObserver = partitionObserver as ICurrentRenderPViewObserver;
|
||||||
_sceneFrameProduct = sceneFrameProduct;
|
_sceneFrameProduct = sceneFrameProduct;
|
||||||
|
|
@ -293,6 +296,13 @@ public sealed class RetailPViewRenderer
|
||||||
partition);
|
partition);
|
||||||
passes.EmitDiagnostics(ctx, result);
|
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
|
// #118: stage assignment for dynamics under an INTERIOR root. Retail
|
||||||
// draws the OUTSIDE world's objects inside the landscape stage —
|
// draws the OUTSIDE world's objects inside the landscape stage —
|
||||||
// PView::DrawCells runs LScape::draw FIRST (pc:432719), then the gated
|
// 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(
|
private void DrawLandscapeThroughOutsideView(
|
||||||
RetailPViewFrameInput ctx,
|
RetailPViewFrameInput ctx,
|
||||||
IRetailPViewPassExecutor passes,
|
IRetailPViewPassExecutor passes,
|
||||||
|
|
|
||||||
|
|
@ -160,6 +160,17 @@ public static class RenderingDiagnostics
|
||||||
public static bool ProbeClipRouteEnabled { get; set; } =
|
public static bool ProbeClipRouteEnabled { get; set; } =
|
||||||
Environment.GetEnvironmentVariable("ACDREAM_PROBE_CLIPROUTE") == "1";
|
Environment.GetEnvironmentVariable("ACDREAM_PROBE_CLIPROUTE") == "1";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Campaign FW3.2b-2 flip apparatus (2026-08-30): when true and the walk
|
||||||
|
/// registries are wired, RetailPViewRenderer runs the PRODUCTION retail
|
||||||
|
/// frame walk per frame in SHADOW (no draws change) and emits one
|
||||||
|
/// [walk-shadow] line per frame whose cell/building sets diverge from the
|
||||||
|
/// old visibility path — the I5 dual-shadow pattern applied to the FW3
|
||||||
|
/// static cutover. Throwaway apparatus — dies with the flip commit.
|
||||||
|
/// </summary>
|
||||||
|
public static bool ProbeWalkShadowEnabled { get; set; } =
|
||||||
|
Environment.GetEnvironmentVariable("ACDREAM_PROBE_WALK_SHADOW") == "1";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Bounded-propagation port apparatus (2026-06-08). When true, PortalVisibilityBuilder.Build emits
|
/// Bounded-propagation port apparatus (2026-06-08). When true, PortalVisibilityBuilder.Build emits
|
||||||
/// one [portal-churn] summary line per call: per-cell pop count (re-pops = churn), total re-enqueues,
|
/// one [portal-churn] summary line per call: per-cell pop count (re-pops = churn), total re-enqueues,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue