refactor(render): delete legacy pview execution machinery

This commit is contained in:
Erik 2026-08-31 05:27:25 +02:00
parent 1be4889c1c
commit 69e69408e8
9 changed files with 58 additions and 3627 deletions

View file

@ -86,37 +86,12 @@ internal interface IOutdoorSceneParticleOwnerSource
IReadOnlySet<uint> OutdoorSceneParticleEntityIds { get; }
}
internal readonly record struct RenderFrameEntityDrawRequest(
RenderFrameView View,
RenderFrameCandidateRoute Route,
int RouteIndex,
uint CellId,
uint TupleLandblockId);
internal interface IRenderFrameEntityPassExecutor
{
void BeginEntityFrame(in RenderFrameView view);
bool DrawEntityRoute(
ICamera camera,
in RenderFrameView view,
RenderFrameCandidateRoute route,
int routeIndex,
uint cellId,
uint tupleLandblockId);
void CompleteEntityFrame(in RenderFrameView view);
void AbortEntityFrame();
}
/// <summary>
/// Campaign V slice V6j: backend-neutral. The order it implements is retail's and
/// is written once; the four places it touches graphics state directly are owned
/// by <see cref="IWorldPassSurface"/>.
/// </summary>
internal sealed partial class RetailPViewPassExecutor :
IRetailPViewPassExecutor,
IOutdoorSceneParticleOwnerSource
{
private readonly IWorldPassSurface _surface;
@ -134,15 +109,9 @@ internal sealed partial class RetailPViewPassExecutor :
private readonly TerrainDrawDiagnosticsController _terrainDiagnostics;
private readonly RetailPViewParticleClassifications _particleClassifications = new();
private readonly HashSet<uint> _noSceneParticleEntityIds = [];
private readonly Dictionary<uint, int> _singleCellClipRouting = new(1);
private readonly Dictionary<uint, int> _noCellClipRouting = new(0);
// ACDREAM_PROBE_WALK_ROOT / cathedral FW4: observation-only counters.
// They distinguish the walk-owned far-Z portal punches from the retired
// legacy look-in punch route. RetailPViewRenderer samples them for the
// diagnostic comparison after the walk-turn look-in routes have replayed.
// ACDREAM_PROBE_WALK_ROOT / cathedral FW4: observation-only counter for
// the walk-owned far-Z portal punches.
internal int WalkLookInPunchCountThisFrame { get; private set; }
internal int LegacyLookInPunchCountThisFrame { get; private set; }
/// <summary>
/// Borrowed until the next late landscape pass. The outdoor-root post-world
@ -190,7 +159,6 @@ internal sealed partial class RetailPViewPassExecutor :
{
AcDream.Core.Rendering.RenderingDiagnostics.WalkRootPhase = "pre";
WalkLookInPunchCountThisFrame = 0;
LegacyLookInPunchCountThisFrame = 0;
}
}
@ -242,11 +210,6 @@ internal sealed partial class RetailPViewPassExecutor :
ClipFrameAssembly reuseAssembly) =>
ClipFrameAssembler.Assemble(_clipFrame, portalFrame, reuseAssembly);
public void AppendLookInClipFrames(
IReadOnlyList<PortalVisibilityFrame> lookInFrames,
ClipFrameAssembly assembly) =>
ClipFrameAssembler.AppendLookInFrames(_clipFrame, lookInFrames, assembly);
public void PrepareClipFrame(int terrainUploadCount) =>
_surface.PrepareClipFrame(terrainUploadCount);
@ -263,24 +226,6 @@ internal sealed partial class RetailPViewPassExecutor :
_entities.ClearClipRouting();
}
public void UseCellPortalViewRouting(uint cellId, ClipViewSlice slice)
{
_singleCellClipRouting.Clear();
_singleCellClipRouting.Add(cellId, slice.Slot);
_envCells.SetClipRouting(_singleCellClipRouting);
// Retail DrawMesh only viewcone-checks an object's sphere under the
// installed PortalList and then draws the mesh whole. Hard clipping the
// object here slices a stationary player when the chase camera crosses
// into the opposite cathedral cell while the player remains behind.
_entities.ClearClipRouting();
}
private void UseOutdoorPortalViewRouting(ClipViewSlice slice) =>
_entities.SetClipRouting(
_noCellClipRouting,
outdoorSlot: slice.Slot,
outdoorVisible: true);
public void PrepareCellBatches(
RetailPViewFrameInput frame,
HashSet<uint> visibleCellIds) =>
@ -298,112 +243,9 @@ internal sealed partial class RetailPViewPassExecutor :
public bool CellHasTransparentShell(uint cellId) =>
_envCells.CellHasTransparent(cellId);
public void DrawTransparentCellShells(HashSet<uint> cellIds) =>
_envCells.Render(WbRenderPass.Transparent, cellIds);
public void DrawTransparentCellShellsOrdered(IReadOnlyList<uint> cellIds) =>
_envCells.RenderTransparentOrdered(cellIds);
public void DrawEntityBucket(
RetailPViewFrameInput frame,
IReadOnlyList<WorldEntity> entities,
HashSet<uint>? visibleCellIds)
{
uint landblockId = frame.PlayerLandblockId ?? 0u;
var entry = (
landblockId,
Vector3.Zero,
Vector3.Zero,
entities,
(IReadOnlyDictionary<uint, WorldEntity>?)null);
_entities.Draw(
frame.Camera,
new[] { entry },
frame.Frustum,
neverCullLandblockId: frame.PlayerLandblockId,
visibleCellIds: visibleCellIds,
animatedEntityIds: frame.AnimatedEntityIds);
}
public void EmitClipRouteProbe(
ClipFrameAssembly clipAssembly,
ClipViewSlice slice,
int sliceIndex) =>
_diagnostics.EmitClipRouteProbe(
RenderingDiagnostics.ProbeClipRouteEnabled,
_clipFrame,
clipAssembly,
slice,
sliceIndex);
public void DrawLandscapeSlice(
RetailPViewFrameInput frame,
RetailPViewLandscapeSliceContext context)
{
ClipViewSlice slice = context.Slice;
bool scissor = BeginDoorwayScissor(slice.NdcAabb);
_diagnostics.EmitClipRouteScissorProbe(
RenderingDiagnostics.ProbeClipRouteEnabled,
scissor,
slice.NdcAabb);
_surface.BindTerrainClip();
EnableClipDistances();
if (frame.RenderSky)
{
_sky?.RenderSky(
frame.Camera,
frame.CameraWorldPosition,
frame.DayFraction,
frame.ActiveDayGroup,
frame.SkyKeyframe,
frame.EnvironOverrideActive);
}
DisableClipDistances();
if (frame.RenderSky && _particles is not null && _particleRenderer is not null)
{
_particleRenderer.Draw(
frame.Camera,
frame.CameraWorldPosition,
ParticleRenderPass.SkyPreScene);
}
EnableClipDistances();
_terrainDiagnostics.Begin();
_terrain?.Draw(
frame.Camera,
frame.Frustum,
neverCullLandblockId: frame.PlayerLandblockId,
clipPlanes: slice.Planes,
ndcClipAabb: slice.NdcAabb);
_terrainDiagnostics.Complete();
DisableClipDistances();
if (context.OutdoorEntities.Count > 0)
{
var sceneryEntry = (
frame.PlayerLandblockId ?? 0u,
Vector3.Zero,
Vector3.Zero,
context.OutdoorEntities,
(IReadOnlyDictionary<uint, WorldEntity>?)null);
_entities.Draw(
frame.Camera,
new[] { sceneryEntry },
frame.Frustum,
neverCullLandblockId: frame.PlayerLandblockId,
visibleCellIds: null,
animatedEntityIds: frame.AnimatedEntityIds);
}
if (scissor)
_surface.EndScissor();
_entities.ClearClipRouting();
DisableClipDistances();
}
public void DrawLandscapeSliceLate(
RetailPViewFrameInput frame,
RetailPViewLandscapeLateSliceContext context)
@ -503,38 +345,6 @@ internal sealed partial class RetailPViewPassExecutor :
DisableClipDistances();
}
public void DrawLandscapeBuildingShellSlice(
RetailPViewFrameInput frame,
RetailPViewLandscapeBuildingShellSliceContext context)
{
UseOutdoorPortalViewRouting(context.Slice);
bool scissor = BeginDoorwayScissor(context.Slice.NdcAabb);
_surface.BindTerrainClip();
DisableClipDistances();
if (context.BuildingShells.Count > 0)
{
var buildingEntry = (
frame.PlayerLandblockId ?? 0u,
Vector3.Zero,
Vector3.Zero,
context.BuildingShells,
(IReadOnlyDictionary<uint, WorldEntity>?)null);
_entities.Draw(
frame.Camera,
new[] { buildingEntry },
frame.Frustum,
neverCullLandblockId: frame.PlayerLandblockId,
visibleCellIds: null,
animatedEntityIds: frame.AnimatedEntityIds);
}
if (scissor)
_surface.EndScissor();
_entities.ClearClipRouting();
DisableClipDistances();
}
public void ClearInteriorDepth()
{
if (AcDream.Core.Rendering.RenderingDiagnostics.ProbeWalkRootEnabled)
@ -547,23 +357,6 @@ internal sealed partial class RetailPViewPassExecutor :
RetailPViewCellSliceContext context) =>
DrawPortalDepthWrite(context, frame, forceFarZ: frame.RootCell.IsOutdoorNode);
public void DrawLookInPortalPunch(
RetailPViewFrameInput frame,
RetailPViewCellSliceContext context,
int portalIndex)
{
if (AcDream.Core.Rendering.RenderingDiagnostics.ProbeWalkRootEnabled)
{
LegacyLookInPunchCountThisFrame++;
Console.WriteLine(
$"[lookin-punch] source=legacy viewer=0x{frame.ViewerCellId:X8} "
+ $"root=0x{frame.RootCell.CellId:X8} cell=0x{context.CellId:X8} "
+ $"portal={portalIndex} planes={context.Slice.Planes.Length} "
+ $"phase={AcDream.Core.Rendering.RenderingDiagnostics.WalkRootPhase}");
}
DrawPortalDepthWrite(context, frame, forceFarZ: true, portalIndex);
}
public void DrawUnattachedSceneParticles(
RetailPViewFrameInput frame,
bool outdoorCells)
@ -643,9 +436,6 @@ internal sealed partial class RetailPViewPassExecutor :
public void FlushLandscapeAlpha() => _alpha.Flush();
public void FlushLandscapeAlphaFartherThan(float minViewerDistance) =>
_alpha.FlushFartherThan(minViewerDistance);
public void DrawCellParticles(
RetailPViewFrameInput frame,
RetailPViewCellSliceContext context)
@ -676,29 +466,6 @@ internal sealed partial class RetailPViewPassExecutor :
DisableClipDistances();
}
public void DrawDynamicsParticles(
RetailPViewFrameInput frame,
IReadOnlySet<uint> ownerIds)
{
if (_particles is null || _particleRenderer is null || ownerIds.Count == 0)
return;
HashSet<uint> dynamics = _particleClassifications.Dynamics;
dynamics.Clear();
dynamics.UnionWith(ownerIds);
if (dynamics.Count == 0)
return;
DisableClipDistances();
ProbeWalkParticleRoute("dyn-owners", dynamics);
_particleRenderer.DrawForOwners(
frame.Camera,
frame.CameraWorldPosition,
ParticleRenderPass.Scene,
dynamics);
DisableClipDistances();
}
public void EmitDiagnostics(
RetailPViewFrameInput frame,
RetailPViewFrameResult result) =>

File diff suppressed because it is too large Load diff

View file

@ -30,8 +30,7 @@ namespace AcDream.App.Rendering.Walk;
/// </list>
///
/// The tuple landblock id handed to the classifier is the frame's player
/// landblock — the packed path's own convention for every
/// <c>RenderFrameEntityDrawRequest</c>.
/// landblock, matching the production walk's retained-scene query convention.
///
/// <para>Campaign FW3.4a: <see cref="GetCellStatics"/>, <see cref="GetOutdoorStatics"/>,
/// and <see cref="GetBuildingShellStatics"/> used to materialize their result

View file

@ -41,12 +41,12 @@ internal interface IPreparedWorldSceneFramePhase : IWorldSceneFramePhase
internal sealed class WorldScenePViewRenderer : IWorldScenePViewRenderer
{
private readonly RetailPViewRenderer _renderer;
private readonly IRetailPViewPassExecutor _passes;
private readonly RetailPViewPassExecutor _passes;
private readonly IOutdoorSceneParticleOwnerSource _particles;
public WorldScenePViewRenderer(
RetailPViewRenderer renderer,
IRetailPViewPassExecutor passes,
RetailPViewPassExecutor passes,
IOutdoorSceneParticleOwnerSource particles)
{
_renderer = renderer ?? throw new ArgumentNullException(nameof(renderer));