fix(render): FW4 slice 3 - the outside-stage predicate reads the walk flood

The cathedral falls persisted through the slice-2 seal fix; the probe
already held the tell: the same two emitter entities (f4243/f4285) draw
phase=pre on good frames and phase=post on bad ones. They are
interior-parented, so DynamicDrawsInOutsideStage takes the indoor arm,
whose first gate is flood membership - and that still read the OLD
apparatus flood, which drops cells at the #456 seam band. On those
frames the falls fell to the post-clear last pass and splatted across
the cleared depth (terrain and water alike).

Both predicate call sites (the frame product's BuildOutsideDynamicRoutes
via BuildAndBorrow's input, and the renderer's own outside-stage
classification) now receive the walk's VisitedCells on walk frames -
root flood plus look-in floods, all of whose objects retail draws inside
LScape::draw, pre-clear. drawableCells keeps its other roles. Also adds
the probe-gated [walk-dyn] per-entity classification dump (parent cell,
outside/cone verdicts) so a surviving repro pins the failing gate
directly.

Hermetic 6,762/0, Walk lane 213/1.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-08-30 19:28:57 +02:00
parent c40aecfc8c
commit 5f7ccdeab5
2 changed files with 40 additions and 13 deletions

View file

@ -1141,6 +1141,10 @@ internal sealed class RenderScenePViewFrameBuilder
private readonly Dictionary<RenderProjectionId, int>
_dynamicPositions = [];
private int _dynamicCount;
// ACDREAM_PROBE_WALK_ROOT companion (throwaway): rate limiter for the
// [walk-dyn] outside-stage classification dump.
private uint _probeDynFrameCounter;
private int _dirtyCount;
private RenderSceneGeneration _indexGeneration;
private ulong _indexRevision;
@ -1320,6 +1324,9 @@ internal sealed class RenderScenePViewFrameBuilder
return;
int sliceCount = input.ClipAssembly.OutsideViewSlices.Length;
bool probeDynamics =
AcDream.Core.Rendering.RenderingDiagnostics.ProbeWalkRootEnabled
&& ++_probeDynFrameCounter % 120 == 0;
for (int sliceIndex = 0; sliceIndex < sliceCount; sliceIndex++)
{
int count = 0;
@ -1328,19 +1335,23 @@ internal sealed class RenderScenePViewFrameBuilder
{
RenderProjectionRecord record = _dynamics[i];
Sphere(in record, out Vector3 center, out float radius);
if (!RetailPViewRenderer.DynamicDrawsInOutsideStage(
ParentCell(in record),
center,
radius,
input.DrawableCells,
input.Cells)
|| !input.Viewcone.SphereVisibleInOutsideSlice(
sliceIndex,
in center,
radius))
bool outside = RetailPViewRenderer.DynamicDrawsInOutsideStage(
ParentCell(in record),
center,
radius,
input.DrawableCells,
input.Cells);
bool cone = input.Viewcone.SphereVisibleInOutsideSlice(
sliceIndex, in center, radius);
if (probeDynamics)
{
continue;
Console.WriteLine(
$"[walk-dyn] slice={sliceIndex} id={record.Source.LocalEntityId:x} "
+ $"parent={ParentCell(in record)?.ToString("x8") ?? "null"} "
+ $"r={radius:F1} outside={(outside ? 1 : 0)} cone={(cone ? 1 : 0)}");
}
if (!outside || !cone)
continue;
_survivors[count++] = record;
writer.AddDynamic(in record);