refactor(render): detach packed pview product from production
This commit is contained in:
parent
ef12170a3c
commit
c9fb7e7d4c
4 changed files with 54 additions and 180 deletions
|
|
@ -15,8 +15,7 @@ public sealed class RetailPViewRenderer
|
|||
{
|
||||
private readonly InteriorEntityPartition.IObserver? _partitionObserver;
|
||||
private readonly ICurrentRenderPViewObserver? _candidateObserver;
|
||||
private readonly RenderScenePViewFrameProductController?
|
||||
_sceneFrameProduct;
|
||||
private readonly RenderSceneShadowRuntime? _renderSceneShadow;
|
||||
private readonly PortalVisibilityFrame _mainPortalFrameScratch = new();
|
||||
private readonly ClipFrameAssembly _clipAssemblyScratch = new();
|
||||
private readonly ViewconeCuller _viewconeScratch = new();
|
||||
|
|
@ -133,7 +132,7 @@ public sealed class RetailPViewRenderer
|
|||
|
||||
internal RetailPViewRenderer(
|
||||
InteriorEntityPartition.IObserver? partitionObserver,
|
||||
RenderScenePViewFrameProductController? sceneFrameProduct = null,
|
||||
RenderSceneShadowRuntime? renderSceneShadow = null,
|
||||
Walk.WalkBuildingRegistry? walkBuildings = null,
|
||||
Walk.WalkLandscapeAssembler? walkLandscape = null,
|
||||
CellVisibility? walkCellRegistry = null)
|
||||
|
|
@ -146,7 +145,7 @@ public sealed class RetailPViewRenderer
|
|||
: null;
|
||||
_partitionObserver = partitionObserver;
|
||||
_candidateObserver = partitionObserver as ICurrentRenderPViewObserver;
|
||||
_sceneFrameProduct = sceneFrameProduct;
|
||||
_renderSceneShadow = renderSceneShadow;
|
||||
}
|
||||
|
||||
// T2 (BR-4): retail has NO distance constant on the flood-admission chain
|
||||
|
|
@ -225,7 +224,7 @@ public sealed class RetailPViewRenderer
|
|||
// required — the walk submits through WbDrawDispatcher.SubmitOrderedStream
|
||||
// and needs a real GPU frame/encoder (RequireWalkSubmission), which no
|
||||
// test IRetailPViewPassExecutor fake can supply. Whenever a concrete
|
||||
// executor IS present, the packed entity-route product must ALSO be
|
||||
// executor IS present, the retained render scene must ALSO be
|
||||
// wired with all three walk registries — a scene product without the
|
||||
// walk data (or vice versa) is a production miswiring, not a
|
||||
// legacy/diagnostic shape, so it fails loud rather than silently
|
||||
|
|
@ -237,12 +236,12 @@ public sealed class RetailPViewRenderer
|
|||
&& _walkCellRegistry is not null
|
||||
&& _walkWorldData is not null;
|
||||
if (walkExecutor is not null
|
||||
&& _sceneFrameProduct is not null
|
||||
&& _renderSceneShadow is not null
|
||||
&& !walkRegistriesReady)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"RetailPViewRenderer has a concrete pass executor and a "
|
||||
+ "RenderScenePViewFrameProductController but the walk registries "
|
||||
+ "RenderSceneShadowRuntime but the walk registries "
|
||||
+ "(WalkBuildingRegistry/WalkLandscapeAssembler/CellVisibility) are "
|
||||
+ "not all wired — the Campaign FW3.2b-2 static cutover requires "
|
||||
+ "every piece together; see FrameRootComposition's "
|
||||
|
|
@ -250,7 +249,7 @@ public sealed class RetailPViewRenderer
|
|||
}
|
||||
bool walkActive =
|
||||
walkExecutor is not null
|
||||
&& _sceneFrameProduct is not null
|
||||
&& _renderSceneShadow is not null
|
||||
&& walkRegistriesReady;
|
||||
|
||||
// Campaign FW3.4a: THE ONE WALK. Builds walkContext/walkLandscape/
|
||||
|
|
@ -320,7 +319,7 @@ public sealed class RetailPViewRenderer
|
|||
}
|
||||
|
||||
_walkWorldData!.BeginFrame(
|
||||
_sceneFrameProduct!.SceneQuery,
|
||||
_renderSceneShadow!.Query,
|
||||
ctx.PlayerLandblockId ?? 0u,
|
||||
ctx.RenderCenterLbX,
|
||||
ctx.RenderCenterLbY);
|
||||
|
|
@ -496,16 +495,11 @@ public sealed class RetailPViewRenderer
|
|||
ctx.ViewProjection,
|
||||
_viewconeScratch);
|
||||
|
||||
// Packed frame routes no longer participate in production. These
|
||||
// placeholders keep the standalone legacy/fake path self-contained
|
||||
// until FW4 removes that shell completely.
|
||||
IRenderFrameEntityPassExecutor? frameEntityPasses = null;
|
||||
if (_sceneFrameProduct is not null)
|
||||
{
|
||||
frameEntityPasses = passes as IRenderFrameEntityPassExecutor
|
||||
?? throw new InvalidOperationException(
|
||||
"The production frame product requires a packed entity-pass executor.");
|
||||
}
|
||||
RenderFrameView frameView = default;
|
||||
bool frameViewBorrowed = false;
|
||||
bool entityFrameOpen = false;
|
||||
_candidateObserver?.BeginPViewFrame();
|
||||
try
|
||||
{
|
||||
|
|
@ -531,32 +525,11 @@ public sealed class RetailPViewRenderer
|
|||
_rootFloodSetScratch.Add(cellId);
|
||||
}
|
||||
|
||||
if (_sceneFrameProduct is not null)
|
||||
{
|
||||
frameView = _sceneFrameProduct.BuildAndBorrow(
|
||||
pvFrame,
|
||||
clipAssembly,
|
||||
viewcone,
|
||||
walkActive ? walkDriver!.LookInCellTurns : [],
|
||||
walkActive ? walkDriver : null,
|
||||
outsideStageFlood,
|
||||
ctx.Cells,
|
||||
ctx.AnimatedEntityIds,
|
||||
ctx.RootCell.IsOutdoorNode,
|
||||
// Non-walk frames (diagnostic fakes / legacy fallback)
|
||||
// keep the pre-split admission: drawableCells WAS the
|
||||
// flood in the legacy meaning.
|
||||
walkActive ? _rootFloodSetScratch : drawableCells);
|
||||
frameViewBorrowed = true;
|
||||
frameEntityPasses!.BeginEntityFrame(in frameView);
|
||||
entityFrameOpen = true;
|
||||
}
|
||||
|
||||
// The retained scene product is the production object source.
|
||||
// Rebuild the former WorldEntity partition only for the standalone
|
||||
// fallback and explicitly enabled comparison/probe paths.
|
||||
// The walk reads the retained scene directly. Rebuild the former
|
||||
// WorldEntity partition only for the standalone fallback and
|
||||
// explicitly enabled comparison/probe paths.
|
||||
InteriorEntityPartition.Result? partition = null;
|
||||
if (_sceneFrameProduct is null || LegacyPartitionDiagnosticsEnabled)
|
||||
if (!walkActive || LegacyPartitionDiagnosticsEnabled)
|
||||
{
|
||||
InteriorEntityPartition.Partition(
|
||||
_partitionResult,
|
||||
|
|
@ -568,11 +541,14 @@ public sealed class RetailPViewRenderer
|
|||
partition = _partitionResult;
|
||||
}
|
||||
|
||||
RenderFrameDiagnosticCounts counts = frameViewBorrowed
|
||||
? frameView.DiagnosticCounts
|
||||
RenderProjectionCounts retainedCounts = walkActive
|
||||
? _renderSceneShadow!.Counts
|
||||
: default;
|
||||
RenderFrameDiagnosticCounts counts = walkActive
|
||||
? WalkDiagnosticCounts(retainedCounts)
|
||||
: LegacyDiagnosticCounts(partition!);
|
||||
RenderProjectionCounts sourceCounts = frameViewBorrowed
|
||||
? frameView.SourceDigest.Counts
|
||||
RenderProjectionCounts sourceCounts = walkActive
|
||||
? retainedCounts
|
||||
: LegacySourceCounts(partition!);
|
||||
// prepareCells is exactly "main flood ∪ look-in cells" — the cells
|
||||
// this traversal actually reached, i.e. retail's in-view set.
|
||||
|
|
@ -761,27 +737,14 @@ public sealed class RetailPViewRenderer
|
|||
// Outdoor-cell unattached emitters drew in the landscape stage.
|
||||
passes.DrawUnattachedSceneParticles(ctx, outdoorCells: false);
|
||||
|
||||
if (entityFrameOpen)
|
||||
{
|
||||
frameEntityPasses!.CompleteEntityFrame(in frameView);
|
||||
entityFrameOpen = false;
|
||||
}
|
||||
_candidateObserver?.CompletePViewFrame();
|
||||
_sceneFrameProduct?.CompleteProduction(in frameView);
|
||||
return result;
|
||||
}
|
||||
catch
|
||||
{
|
||||
if (entityFrameOpen)
|
||||
frameEntityPasses!.AbortEntityFrame();
|
||||
_candidateObserver?.AbortPViewFrame();
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (frameViewBorrowed)
|
||||
_sceneFrameProduct!.Release(in frameView);
|
||||
}
|
||||
}
|
||||
|
||||
// R-A2: group the nearby building cells by BuildingId and run one per-building flood per group
|
||||
|
|
@ -2408,6 +2371,27 @@ public sealed class RetailPViewRenderer
|
|||
|| AcDream.Core.Rendering.RenderingDiagnostics.ProbeFlapEnabled
|
||||
|| AcDream.App.Streaming.EntityVanishProbe.Enabled;
|
||||
|
||||
private static RenderFrameDiagnosticCounts WalkDiagnosticCounts(
|
||||
RenderProjectionCounts source)
|
||||
{
|
||||
int dynamics = checked(
|
||||
source.LiveDynamicRoot
|
||||
+ source.ActiveAnimatedStatic
|
||||
+ source.EquippedChild);
|
||||
return new RenderFrameDiagnosticCounts(
|
||||
source.OutdoorStatic,
|
||||
source.IndoorCellStatic,
|
||||
dynamics,
|
||||
TransformCount: source.Total,
|
||||
OpaqueClassificationCount: 0,
|
||||
AlphaClassificationCount: 0,
|
||||
LightSetCount: 0,
|
||||
SelectionPartCount: 0,
|
||||
RouteCandidateCount: source.Total,
|
||||
EntityCandidateCount: source.Total,
|
||||
MeshPartCount: 0);
|
||||
}
|
||||
|
||||
internal static RenderFrameDiagnosticCounts LegacyDiagnosticCounts(
|
||||
InteriorEntityPartition.Result partition)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue