refactor(render): flush alpha at retail walk barriers

This commit is contained in:
Erik 2026-08-31 04:25:34 +02:00
parent 877e935ac4
commit a40a57b9b3
3 changed files with 15 additions and 24 deletions

View file

@ -189,10 +189,8 @@ internal sealed partial class RetailPViewPassExecutor
/// <item><see cref="ClearInteriorDepth"/>/<see cref="DrawExitSeals"/> → /// <item><see cref="ClearInteriorDepth"/>/<see cref="DrawExitSeals"/> →
/// caller-supplied actions (the renderer owns the pass scope and the /// caller-supplied actions (the renderer owns the pass scope and the
/// root-flood seal iteration; the adapter only provides the turns).</item> /// root-flood seal iteration; the adapter only provides the turns).</item>
/// <item><see cref="AlphaBarrier"/> → <c>FlushLandscapeAlphaFartherThan</c> /// <item><see cref="AlphaBarrier"/> → <c>FlushLandscapeAlpha</c>, retail's
/// (the <c>DrawBuilding</c> barrier; retail's flush-all /// flush-all <c>FlushAlphaList(0f)</c> @0x0059f30b.</item>
/// <c>FlushAlphaList(0f)</c> @0x0059f30b is the FW4 adjudication
/// candidate recorded on the driver's interface).</item>
/// </list> /// </list>
/// </summary> /// </summary>
internal sealed class WalkProductionLeafRenderer : IWalkFrameLeafRenderer internal sealed class WalkProductionLeafRenderer : IWalkFrameLeafRenderer
@ -257,6 +255,5 @@ internal sealed class WalkProductionLeafRenderer : IWalkFrameLeafRenderer
public void DrawPunchFan(WalkPolygon worldPolygon, int activeViewIndex) => public void DrawPunchFan(WalkPolygon worldPolygon, int activeViewIndex) =>
_passes.DrawWalkPunchFan(_frame, _clipAssembly, worldPolygon, activeViewIndex); _passes.DrawWalkPunchFan(_frame, _clipAssembly, worldPolygon, activeViewIndex);
public void AlphaBarrier(float viewerDistance) => public void AlphaBarrier() => _passes.FlushLandscapeAlpha();
_passes.FlushLandscapeAlphaFartherThan(viewerDistance);
} }

View file

@ -180,17 +180,11 @@ internal interface IWalkFrameLeafRenderer
/// that view's slice planes.</summary> /// that view's slice planes.</summary>
void DrawPunchFan(WalkPolygon worldPolygon, int activeViewIndex); void DrawPunchFan(WalkPolygon worldPolygon, int activeViewIndex);
/// <summary><c>RetailAlphaQueue.FlushFartherThan</c>'s <c>DrawBuilding</c> /// <summary>Retail <c>D3DPolyRender::FlushAlphaList(0f)</c>
/// barrier — retail's own call site is /// @0x0059f30b. The walk is positional: only farther cells have submitted
/// <c>D3DPolyRender::FlushAlphaList(0f)</c> @0x0059f30b, a FLUSH-ALL, not /// alpha when a building turn fires, so this is a full drain with no
/// a distance-gated flush; this stage keeps the DISPATCHED /// synthetic viewer-distance threshold.</summary>
/// <c>FlushFartherThan(viewerDistanceTo(building))</c> shape (the two void AlphaBarrier();
/// coincide under the walk's far-to-near landscape order, since a nearer
/// emitter has not been inserted into the alpha queue yet — see
/// <c>RetailAlphaQueue.FlushFartherThan</c>'s own doc comment) and flags
/// the 0f/address detail as an FW4 adjudication candidate rather than
/// silently reinterpreting the dispatched design.</summary>
void AlphaBarrier(float viewerDistance);
} }
/// <summary> /// <summary>
@ -353,8 +347,8 @@ internal readonly struct WalkFrameEvent
internal static WalkFrameEvent PunchFan(WalkPolygon worldPolygon, int activeViewIndex) => internal static WalkFrameEvent PunchFan(WalkPolygon worldPolygon, int activeViewIndex) =>
new(WalkFrameEventKind.PunchFan, activeViewIndex, 0, 0f, worldPolygon); new(WalkFrameEventKind.PunchFan, activeViewIndex, 0, 0f, worldPolygon);
internal static WalkFrameEvent AlphaBarrier(float viewerDistance) => internal static WalkFrameEvent AlphaBarrier() =>
new(WalkFrameEventKind.AlphaBarrier, 0, 0, viewerDistance, null); new(WalkFrameEventKind.AlphaBarrier, 0, 0, 0f, null);
internal static WalkFrameEvent LandscapeCellParticles(uint cellId) => internal static WalkFrameEvent LandscapeCellParticles(uint cellId) =>
new(WalkFrameEventKind.StaticParticles, 0, cellId, 0f, null); new(WalkFrameEventKind.StaticParticles, 0, cellId, 0f, null);
@ -711,7 +705,7 @@ internal sealed class WalkFrameDriver : IWalkEventSink, IWalkLookInViewSource
_leafRenderer.DrawPunchFan(e.Polygon!, e.IntArg); _leafRenderer.DrawPunchFan(e.Polygon!, e.IntArg);
break; break;
case WalkFrameEventKind.AlphaBarrier: case WalkFrameEventKind.AlphaBarrier:
_leafRenderer.AlphaBarrier(e.FloatArg); _leafRenderer.AlphaBarrier();
break; break;
case WalkFrameEventKind.ClearInteriorDepth: case WalkFrameEventKind.ClearInteriorDepth:
_leafRenderer.ClearInteriorDepth(); _leafRenderer.ClearInteriorDepth();
@ -840,7 +834,7 @@ internal sealed class WalkFrameDriver : IWalkEventSink, IWalkLookInViewSource
void IWalkEventSink.OnBuildingTurn(WalkBuilding building) void IWalkEventSink.OnBuildingTurn(WalkBuilding building)
{ {
ArgumentNullException.ThrowIfNull(building); ArgumentNullException.ThrowIfNull(building);
IWalkBuildingFrameContext ctx = RequireOpenFrame(); RequireOpenFrame();
VisitedBuildings.Add(building); VisitedBuildings.Add(building);
// D3DPolyRender::FlushAlphaList(0f) @0x0059f30b — retail's alpha // D3DPolyRender::FlushAlphaList(0f) @0x0059f30b — retail's alpha
@ -848,7 +842,7 @@ internal sealed class WalkFrameDriver : IWalkEventSink, IWalkLookInViewSource
// look-ins) follows this call; the building's own shell content is // look-ins) follows this call; the building's own shell content is
// appended only once that pass completes (OnBuildingShellTurn). // appended only once that pass completes (OnBuildingShellTurn).
MarkIfGrown(); MarkIfGrown();
_events.Add(WalkFrameEvent.AlphaBarrier(ctx.ViewerDistanceTo(building))); _events.Add(WalkFrameEvent.AlphaBarrier());
_currentDcStage = WalkDrawStage.LookInStatic; _currentDcStage = WalkDrawStage.LookInStatic;
} }

View file

@ -60,7 +60,7 @@ public sealed class WalkFrameDriverTests
log.Add($"PUNCH:{worldPolygon.Vertices.Length}@v{activeViewIndex}"); log.Add($"PUNCH:{worldPolygon.Vertices.Length}@v{activeViewIndex}");
} }
public void AlphaBarrier(float viewerDistance) => log.Add($"ALPHA:{viewerDistance:F2}"); public void AlphaBarrier() => log.Add("ALPHA");
public void DrawStaticParticles(IReadOnlySet<uint> ownerIds) public void DrawStaticParticles(IReadOnlySet<uint> ownerIds)
{ {
@ -447,7 +447,7 @@ public sealed class WalkFrameDriverTests
// submit at the shell turn, after the shell content flushes. // submit at the shell turn, after the shell content flushes.
new[] new[]
{ {
"ALPHA:12.50", "PUNCH:4@v0", "SHELL:00000104", "ALPHA", "PUNCH:4@v0", "SHELL:00000104",
"FLUSH:1:LookInStatic", "FLUSH:1:Dynamic", "FLUSH:1:LookInStatic", "FLUSH:1:Dynamic",
"CELL-PARTICLES:00000104:ca,cb", "CELL-PARTICLES:00000104:ca,cb",
"FLUSH:1:BuildingShell", "PARTICLES:c9", "FLUSH:1:BuildingShell", "PARTICLES:c9",