From a40a57b9b3c26c302ea902288c32ecab9a6a1a94 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 31 Aug 2026 04:25:34 +0200 Subject: [PATCH] refactor(render): flush alpha at retail walk barriers --- .../RetailPViewPassExecutor.WalkLeaf.cs | 9 +++---- .../Rendering/Walk/WalkFrameDriver.cs | 26 +++++++------------ .../Rendering/Walk/WalkFrameDriverTests.cs | 4 +-- 3 files changed, 15 insertions(+), 24 deletions(-) diff --git a/src/AcDream.App/Rendering/RetailPViewPassExecutor.WalkLeaf.cs b/src/AcDream.App/Rendering/RetailPViewPassExecutor.WalkLeaf.cs index e54a014b..64036b1c 100644 --- a/src/AcDream.App/Rendering/RetailPViewPassExecutor.WalkLeaf.cs +++ b/src/AcDream.App/Rendering/RetailPViewPassExecutor.WalkLeaf.cs @@ -189,10 +189,8 @@ internal sealed partial class RetailPViewPassExecutor /// / → /// caller-supplied actions (the renderer owns the pass scope and the /// root-flood seal iteration; the adapter only provides the turns). -/// FlushLandscapeAlphaFartherThan -/// (the DrawBuilding barrier; retail's flush-all -/// FlushAlphaList(0f) @0x0059f30b is the FW4 adjudication -/// candidate recorded on the driver's interface). +/// FlushLandscapeAlpha, retail's +/// flush-all FlushAlphaList(0f) @0x0059f30b. /// /// internal sealed class WalkProductionLeafRenderer : IWalkFrameLeafRenderer @@ -257,6 +255,5 @@ internal sealed class WalkProductionLeafRenderer : IWalkFrameLeafRenderer public void DrawPunchFan(WalkPolygon worldPolygon, int activeViewIndex) => _passes.DrawWalkPunchFan(_frame, _clipAssembly, worldPolygon, activeViewIndex); - public void AlphaBarrier(float viewerDistance) => - _passes.FlushLandscapeAlphaFartherThan(viewerDistance); + public void AlphaBarrier() => _passes.FlushLandscapeAlpha(); } diff --git a/src/AcDream.App/Rendering/Walk/WalkFrameDriver.cs b/src/AcDream.App/Rendering/Walk/WalkFrameDriver.cs index a082c65d..a1bcb3ba 100644 --- a/src/AcDream.App/Rendering/Walk/WalkFrameDriver.cs +++ b/src/AcDream.App/Rendering/Walk/WalkFrameDriver.cs @@ -180,17 +180,11 @@ internal interface IWalkFrameLeafRenderer /// that view's slice planes. void DrawPunchFan(WalkPolygon worldPolygon, int activeViewIndex); - /// RetailAlphaQueue.FlushFartherThan's DrawBuilding - /// barrier — retail's own call site is - /// D3DPolyRender::FlushAlphaList(0f) @0x0059f30b, a FLUSH-ALL, not - /// a distance-gated flush; this stage keeps the DISPATCHED - /// FlushFartherThan(viewerDistanceTo(building)) shape (the two - /// coincide under the walk's far-to-near landscape order, since a nearer - /// emitter has not been inserted into the alpha queue yet — see - /// RetailAlphaQueue.FlushFartherThan's own doc comment) and flags - /// the 0f/address detail as an FW4 adjudication candidate rather than - /// silently reinterpreting the dispatched design. - void AlphaBarrier(float viewerDistance); + /// Retail D3DPolyRender::FlushAlphaList(0f) + /// @0x0059f30b. The walk is positional: only farther cells have submitted + /// alpha when a building turn fires, so this is a full drain with no + /// synthetic viewer-distance threshold. + void AlphaBarrier(); } /// @@ -353,8 +347,8 @@ internal readonly struct WalkFrameEvent internal static WalkFrameEvent PunchFan(WalkPolygon worldPolygon, int activeViewIndex) => new(WalkFrameEventKind.PunchFan, activeViewIndex, 0, 0f, worldPolygon); - internal static WalkFrameEvent AlphaBarrier(float viewerDistance) => - new(WalkFrameEventKind.AlphaBarrier, 0, 0, viewerDistance, null); + internal static WalkFrameEvent AlphaBarrier() => + new(WalkFrameEventKind.AlphaBarrier, 0, 0, 0f, null); internal static WalkFrameEvent LandscapeCellParticles(uint cellId) => new(WalkFrameEventKind.StaticParticles, 0, cellId, 0f, null); @@ -711,7 +705,7 @@ internal sealed class WalkFrameDriver : IWalkEventSink, IWalkLookInViewSource _leafRenderer.DrawPunchFan(e.Polygon!, e.IntArg); break; case WalkFrameEventKind.AlphaBarrier: - _leafRenderer.AlphaBarrier(e.FloatArg); + _leafRenderer.AlphaBarrier(); break; case WalkFrameEventKind.ClearInteriorDepth: _leafRenderer.ClearInteriorDepth(); @@ -840,7 +834,7 @@ internal sealed class WalkFrameDriver : IWalkEventSink, IWalkLookInViewSource void IWalkEventSink.OnBuildingTurn(WalkBuilding building) { ArgumentNullException.ThrowIfNull(building); - IWalkBuildingFrameContext ctx = RequireOpenFrame(); + RequireOpenFrame(); VisitedBuildings.Add(building); // 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 // appended only once that pass completes (OnBuildingShellTurn). MarkIfGrown(); - _events.Add(WalkFrameEvent.AlphaBarrier(ctx.ViewerDistanceTo(building))); + _events.Add(WalkFrameEvent.AlphaBarrier()); _currentDcStage = WalkDrawStage.LookInStatic; } diff --git a/tests/AcDream.App.Tests/Rendering/Walk/WalkFrameDriverTests.cs b/tests/AcDream.App.Tests/Rendering/Walk/WalkFrameDriverTests.cs index 6ee9c6f8..1d03cff3 100644 --- a/tests/AcDream.App.Tests/Rendering/Walk/WalkFrameDriverTests.cs +++ b/tests/AcDream.App.Tests/Rendering/Walk/WalkFrameDriverTests.cs @@ -60,7 +60,7 @@ public sealed class WalkFrameDriverTests 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 ownerIds) { @@ -447,7 +447,7 @@ public sealed class WalkFrameDriverTests // submit at the shell turn, after the shell content flushes. new[] { - "ALPHA:12.50", "PUNCH:4@v0", "SHELL:00000104", + "ALPHA", "PUNCH:4@v0", "SHELL:00000104", "FLUSH:1:LookInStatic", "FLUSH:1:Dynamic", "CELL-PARTICLES:00000104:ca,cb", "FLUSH:1:BuildingShell", "PARTICLES:c9",