Revert "perf(rendering): draw retained frame product"
This reverts commit ef1d263337.
This commit is contained in:
parent
624e1119ca
commit
2c848d4167
13 changed files with 268 additions and 1334 deletions
|
|
@ -113,15 +113,16 @@ internal interface IRenderFrameProductSnapshotSource
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Owns the same-frame PView product. Diagnostic composition may compare it
|
||||
/// with the retired current-path observer; production borrows the exact same
|
||||
/// arena and supplies its ordered ranges directly to the dispatcher.
|
||||
/// G1 compare-only owner. It builds the candidate frame product directly from
|
||||
/// the incremental scene after the accepted PView traversal, borrows it in the
|
||||
/// same render frame, and compares route membership against the current-path
|
||||
/// observer. It never supplies a production draw input.
|
||||
/// </summary>
|
||||
internal sealed class RenderScenePViewFrameProductController :
|
||||
IRenderFrameProductSnapshotSource
|
||||
{
|
||||
private readonly RenderSceneShadowRuntime _shadow;
|
||||
private readonly CurrentRenderSceneOracle? _current;
|
||||
private readonly CurrentRenderSceneOracle _current;
|
||||
private readonly WbDrawDispatcher? _dispatcher;
|
||||
private readonly RenderScenePViewFrameBuilder _builder = new();
|
||||
private readonly RenderFrameExchange _exchange = new();
|
||||
|
|
@ -154,12 +155,12 @@ internal sealed class RenderScenePViewFrameProductController :
|
|||
|
||||
public RenderScenePViewFrameProductController(
|
||||
RenderSceneShadowRuntime shadow,
|
||||
CurrentRenderSceneOracle? current = null,
|
||||
CurrentRenderSceneOracle current,
|
||||
Action<string>? log = null,
|
||||
WbDrawDispatcher? dispatcher = null)
|
||||
{
|
||||
_shadow = shadow ?? throw new ArgumentNullException(nameof(shadow));
|
||||
_current = current;
|
||||
_current = current ?? throw new ArgumentNullException(nameof(current));
|
||||
_log = log;
|
||||
_dispatcher = dispatcher;
|
||||
Snapshot = RenderFrameProductComparisonSnapshot.Disabled with
|
||||
|
|
@ -170,56 +171,6 @@ internal sealed class RenderScenePViewFrameProductController :
|
|||
|
||||
public RenderFrameProductComparisonSnapshot Snapshot { get; private set; }
|
||||
|
||||
private CurrentRenderSceneOracle Current =>
|
||||
_current
|
||||
?? throw new InvalidOperationException(
|
||||
"Current-path comparison was requested without a referee.");
|
||||
|
||||
public RenderFrameView BuildAndBorrow(
|
||||
PortalVisibilityFrame portalFrame,
|
||||
ClipFrameAssembly clipAssembly,
|
||||
ViewconeCuller viewcone,
|
||||
IReadOnlyList<PortalVisibilityFrame> lookInFrames,
|
||||
HashSet<uint> drawableCells,
|
||||
IRetailPViewCellSource cells,
|
||||
HashSet<uint>? animatedEntityIds,
|
||||
bool rootIsOutdoor)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(portalFrame);
|
||||
ArgumentNullException.ThrowIfNull(clipAssembly);
|
||||
ArgumentNullException.ThrowIfNull(viewcone);
|
||||
ArgumentNullException.ThrowIfNull(lookInFrames);
|
||||
ArgumentNullException.ThrowIfNull(drawableCells);
|
||||
ArgumentNullException.ThrowIfNull(cells);
|
||||
|
||||
ulong frameSequence = checked(++_productFrameSequence);
|
||||
RenderSceneQuery scene = _shadow.Query;
|
||||
RenderSceneDigest sourceDigest = _current is null
|
||||
? new RenderSceneDigest(
|
||||
scene.Generation,
|
||||
scene.Counts,
|
||||
default)
|
||||
: _shadow.BuildDigest();
|
||||
var input = new RenderScenePViewBuildInput(
|
||||
scene,
|
||||
sourceDigest,
|
||||
portalFrame,
|
||||
clipAssembly,
|
||||
viewcone,
|
||||
lookInFrames,
|
||||
drawableCells,
|
||||
cells,
|
||||
animatedEntityIds,
|
||||
rootIsOutdoor);
|
||||
_builder.Build(_exchange, frameSequence, in input);
|
||||
return _exchange.BorrowLatest(
|
||||
scene.Generation,
|
||||
frameSequence);
|
||||
}
|
||||
|
||||
public void Release(in RenderFrameView view) =>
|
||||
_exchange.Release(in view);
|
||||
|
||||
public void BuildAndCompare(
|
||||
PortalVisibilityFrame portalFrame,
|
||||
ClipFrameAssembly clipAssembly,
|
||||
|
|
@ -232,7 +183,18 @@ internal sealed class RenderScenePViewFrameProductController :
|
|||
bool rootIsOutdoor,
|
||||
Vector3 cameraWorldPosition = default)
|
||||
{
|
||||
RenderFrameView view = BuildAndBorrow(
|
||||
ArgumentNullException.ThrowIfNull(portalFrame);
|
||||
ArgumentNullException.ThrowIfNull(clipAssembly);
|
||||
ArgumentNullException.ThrowIfNull(viewcone);
|
||||
ArgumentNullException.ThrowIfNull(lookInFrames);
|
||||
ArgumentNullException.ThrowIfNull(drawableCells);
|
||||
ArgumentNullException.ThrowIfNull(cells);
|
||||
|
||||
ulong frameSequence = checked(++_productFrameSequence);
|
||||
RenderSceneQuery scene = _shadow.Query;
|
||||
var input = new RenderScenePViewBuildInput(
|
||||
scene,
|
||||
_shadow.BuildDigest(),
|
||||
portalFrame,
|
||||
clipAssembly,
|
||||
viewcone,
|
||||
|
|
@ -241,6 +203,10 @@ internal sealed class RenderScenePViewFrameProductController :
|
|||
cells,
|
||||
animatedEntityIds,
|
||||
rootIsOutdoor);
|
||||
_builder.Build(_exchange, frameSequence, in input);
|
||||
RenderFrameView view = _exchange.BorrowLatest(
|
||||
scene.Generation,
|
||||
frameSequence);
|
||||
try
|
||||
{
|
||||
Compare(
|
||||
|
|
@ -250,92 +216,26 @@ internal sealed class RenderScenePViewFrameProductController :
|
|||
}
|
||||
finally
|
||||
{
|
||||
Release(in view);
|
||||
_exchange.Release(in view);
|
||||
}
|
||||
}
|
||||
|
||||
public void CompleteProduction(in RenderFrameView view)
|
||||
{
|
||||
_packedClassification =
|
||||
_dispatcher?.PackedClassificationSnapshot ?? default;
|
||||
if (_current is null)
|
||||
{
|
||||
_shadow.ClearDirty();
|
||||
Snapshot = Snapshot with
|
||||
{
|
||||
Enabled = true,
|
||||
ProductFrameSequence = view.FrameSequence,
|
||||
ActualCandidateCount = view.RouteCandidates.Length,
|
||||
PackedClassificationProjectionCount =
|
||||
_packedClassification.ProjectionCount,
|
||||
PackedClassificationStaticRebuildCount =
|
||||
_packedClassification.StaticRebuildCount,
|
||||
PackedClassificationSameFrameReuseCount =
|
||||
_packedClassification.SameFrameReuseCount,
|
||||
PackedClassificationCrossFrameReuseCount =
|
||||
_packedClassification.CrossFrameReuseCount,
|
||||
PackedClassificationAnimatedCount =
|
||||
_packedClassification.AnimatedClassificationCount,
|
||||
PackedClassificationRetiredCount =
|
||||
_packedClassification.RetiredProjectionCount,
|
||||
PackedClassificationRetainedPayloadBytes =
|
||||
_packedClassification.RetainedPayloadBytes,
|
||||
ProductCounts = view.DiagnosticCounts,
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
CandidateComparison candidates =
|
||||
CompareCandidateMembership(in view);
|
||||
if (candidates.Successful)
|
||||
_shadow.ClearDirty();
|
||||
Snapshot = Snapshot with
|
||||
{
|
||||
Enabled = true,
|
||||
ProductFrameSequence = view.FrameSequence,
|
||||
CurrentPViewFrameSequence =
|
||||
Current.Snapshot.CompletedPViewFrameSequence,
|
||||
ComparisonCount = _comparisonCount,
|
||||
SuccessfulComparisonCount = _successfulComparisonCount,
|
||||
ExpectedCandidateCount = _expected.Count,
|
||||
ActualCandidateCount = _actual.Count,
|
||||
MismatchCount = _mismatchCount,
|
||||
FirstMismatch = _firstMismatch,
|
||||
ExpectedDigest = candidates.ExpectedDigest,
|
||||
ActualDigest = candidates.ActualDigest,
|
||||
PackedClassificationProjectionCount =
|
||||
_packedClassification.ProjectionCount,
|
||||
PackedClassificationStaticRebuildCount =
|
||||
_packedClassification.StaticRebuildCount,
|
||||
PackedClassificationSameFrameReuseCount =
|
||||
_packedClassification.SameFrameReuseCount,
|
||||
PackedClassificationCrossFrameReuseCount =
|
||||
_packedClassification.CrossFrameReuseCount,
|
||||
PackedClassificationAnimatedCount =
|
||||
_packedClassification.AnimatedClassificationCount,
|
||||
PackedClassificationRetiredCount =
|
||||
_packedClassification.RetiredProjectionCount,
|
||||
PackedClassificationRetainedPayloadBytes =
|
||||
_packedClassification.RetainedPayloadBytes,
|
||||
ProductCounts = view.DiagnosticCounts,
|
||||
};
|
||||
}
|
||||
|
||||
private CandidateComparison CompareCandidateMembership(
|
||||
in RenderFrameView view)
|
||||
private void Compare(
|
||||
in RenderFrameView view,
|
||||
uint tupleLandblockId,
|
||||
Vector3 cameraWorldPosition)
|
||||
{
|
||||
_comparisonCount = checked(_comparisonCount + 1);
|
||||
_expected.Clear();
|
||||
_actual.Clear();
|
||||
|
||||
IReadOnlyList<CurrentRenderPViewCandidateFingerprint> expected =
|
||||
Current.PViewCandidates;
|
||||
_current.PViewCandidates;
|
||||
if (_expected.Capacity < expected.Count)
|
||||
_expected.Capacity = expected.Count;
|
||||
for (int index = 0; index < expected.Count; index++)
|
||||
for (int i = 0; i < expected.Count; i++)
|
||||
{
|
||||
CurrentRenderPViewCandidateFingerprint candidate =
|
||||
expected[index];
|
||||
CurrentRenderPViewCandidateFingerprint candidate = expected[i];
|
||||
CurrentRenderProjectionFingerprint projection =
|
||||
candidate.Projection;
|
||||
_expected.Add(new CandidateKey(
|
||||
|
|
@ -345,15 +245,11 @@ internal sealed class RenderScenePViewFrameProductController :
|
|||
ExpectedId(in projection)));
|
||||
}
|
||||
|
||||
ReadOnlySpan<RenderFrameCandidateRange> ranges =
|
||||
view.RouteRanges;
|
||||
ReadOnlySpan<RenderProjectionRecord> records =
|
||||
view.RouteCandidates;
|
||||
ReadOnlySpan<RenderFrameCandidateRange> ranges = view.RouteRanges;
|
||||
ReadOnlySpan<RenderProjectionRecord> records = view.RouteCandidates;
|
||||
if (_actual.Capacity < records.Length)
|
||||
_actual.Capacity = records.Length;
|
||||
for (int rangeIndex = 0;
|
||||
rangeIndex < ranges.Length;
|
||||
rangeIndex++)
|
||||
for (int rangeIndex = 0; rangeIndex < ranges.Length; rangeIndex++)
|
||||
{
|
||||
RenderFrameCandidateRange range = ranges[rangeIndex];
|
||||
int end = checked(range.Offset + range.Count);
|
||||
|
|
@ -389,32 +285,10 @@ internal sealed class RenderScenePViewFrameProductController :
|
|||
{
|
||||
_firstMismatch = mismatch;
|
||||
_log?.Invoke(
|
||||
"[render-frame-product] first mismatch: "
|
||||
+ mismatch);
|
||||
"[render-frame-product] first mismatch: " + mismatch);
|
||||
}
|
||||
}
|
||||
|
||||
return new CandidateComparison(
|
||||
mismatch is null,
|
||||
expectedDigest,
|
||||
actualDigest);
|
||||
}
|
||||
|
||||
private void Compare(
|
||||
in RenderFrameView view,
|
||||
uint tupleLandblockId,
|
||||
Vector3 cameraWorldPosition)
|
||||
{
|
||||
CandidateComparison candidates =
|
||||
CompareCandidateMembership(in view);
|
||||
RenderSceneHash128 expectedDigest =
|
||||
candidates.ExpectedDigest;
|
||||
RenderSceneHash128 actualDigest =
|
||||
candidates.ActualDigest;
|
||||
string? mismatch = candidates.Successful
|
||||
? null
|
||||
: _firstMismatch;
|
||||
|
||||
PackedInputComparison packed =
|
||||
ComparePackedInput(in view, tupleLandblockId);
|
||||
ClassifiedOutputComparison classified =
|
||||
|
|
@ -438,7 +312,7 @@ internal sealed class RenderScenePViewFrameProductController :
|
|||
Enabled: true,
|
||||
ProductFrameSequence: view.FrameSequence,
|
||||
CurrentPViewFrameSequence:
|
||||
Current.Snapshot.CompletedPViewFrameSequence,
|
||||
_current.Snapshot.CompletedPViewFrameSequence,
|
||||
ComparisonCount: _comparisonCount,
|
||||
SuccessfulComparisonCount: _successfulComparisonCount,
|
||||
ExpectedCandidateCount: _expected.Count,
|
||||
|
|
@ -521,7 +395,7 @@ internal sealed class RenderScenePViewFrameProductController :
|
|||
_packedClassification =
|
||||
dispatcher.PackedClassificationSnapshot;
|
||||
IReadOnlyList<CurrentRenderDispatcherSubmission> expected =
|
||||
Current.DispatcherSubmissions;
|
||||
_current.DispatcherSubmissions;
|
||||
IReadOnlyList<CurrentRenderDispatcherSubmission> actual =
|
||||
dispatcher.PackedDispatcherSubmissions;
|
||||
RenderSceneHash128 expectedDigest =
|
||||
|
|
@ -552,7 +426,7 @@ internal sealed class RenderScenePViewFrameProductController :
|
|||
}
|
||||
|
||||
IReadOnlyList<CurrentRenderSelectionFingerprint>
|
||||
expectedSelection = Current.SelectionParts;
|
||||
expectedSelection = _current.SelectionParts;
|
||||
IReadOnlyList<CurrentRenderSelectionFingerprint>
|
||||
actualSelection = dispatcher.PackedSelectionParts;
|
||||
BuildSelectionKeys(
|
||||
|
|
@ -754,7 +628,7 @@ internal sealed class RenderScenePViewFrameProductController :
|
|||
_packedActual.Clear();
|
||||
|
||||
IReadOnlyList<CurrentRenderDispatcherFingerprint> expected =
|
||||
Current.DispatcherCandidates;
|
||||
_current.DispatcherCandidates;
|
||||
if (_packedExpected.Capacity < expected.Count)
|
||||
_packedExpected.Capacity = expected.Count;
|
||||
for (int index = 0; index < expected.Count; index++)
|
||||
|
|
@ -876,10 +750,10 @@ internal sealed class RenderScenePViewFrameProductController :
|
|||
|
||||
private string? ComparePackedInputKeys(int actualDrawCount)
|
||||
{
|
||||
if (Current.Snapshot.DispatcherDrawCount != actualDrawCount)
|
||||
if (_current.Snapshot.DispatcherDrawCount != actualDrawCount)
|
||||
{
|
||||
return $"field=drawCount expected="
|
||||
+ $"{Current.Snapshot.DispatcherDrawCount} "
|
||||
+ $"{_current.Snapshot.DispatcherDrawCount} "
|
||||
+ $"actual={actualDrawCount}";
|
||||
}
|
||||
if (_packedExpected.Count != _packedActual.Count)
|
||||
|
|
@ -1017,11 +891,6 @@ internal sealed class RenderScenePViewFrameProductController :
|
|||
RenderSceneHash128 ExpectedDigest,
|
||||
RenderSceneHash128 ActualDigest);
|
||||
|
||||
private readonly record struct CandidateComparison(
|
||||
bool Successful,
|
||||
RenderSceneHash128 ExpectedDigest,
|
||||
RenderSceneHash128 ActualDigest);
|
||||
|
||||
private readonly record struct ClassifiedOutputComparison(
|
||||
bool Successful,
|
||||
int ExpectedDrawCount,
|
||||
|
|
@ -1124,19 +993,11 @@ internal sealed class RenderScenePViewFrameBuilder
|
|||
private RenderProjectionRecord[] _outdoor = [];
|
||||
private RenderProjectionRecord[] _dynamics = [];
|
||||
private RenderProjectionRecord[] _cell = [];
|
||||
private RenderProjectionRecord[] _dirty = [];
|
||||
private RenderProjectionRecord[] _survivors = [];
|
||||
private RenderProjectionRecord[] _cellRoute = [];
|
||||
private readonly Dictionary<RenderProjectionId, int>
|
||||
_outdoorPositions = [];
|
||||
private readonly Dictionary<RenderProjectionId, int>
|
||||
_dynamicPositions = [];
|
||||
private int _outdoorCount;
|
||||
private int _dynamicCount;
|
||||
private int _cellRouteCount;
|
||||
private int _dirtyCount;
|
||||
private RenderSceneGeneration _indexGeneration;
|
||||
private ulong _indexRevision;
|
||||
|
||||
public void Build(
|
||||
RenderFrameExchange exchange,
|
||||
|
|
@ -1162,7 +1023,6 @@ internal sealed class RenderScenePViewFrameBuilder
|
|||
BuildCellStaticRoute(writer, in input);
|
||||
BuildDynamicLastRoute(writer, in input);
|
||||
writer.Publish();
|
||||
AcknowledgeCachedDirtyRecords();
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
|
@ -1174,97 +1034,21 @@ internal sealed class RenderScenePViewFrameBuilder
|
|||
private void LoadSceneIndices(RenderSceneQuery scene)
|
||||
{
|
||||
RenderSceneIndexCounts counts = scene.IndexCounts;
|
||||
ulong revision = scene.IndexRevision;
|
||||
if (scene.Generation != _indexGeneration
|
||||
|| revision != _indexRevision)
|
||||
{
|
||||
EnsureCapacity(ref _outdoor, counts.OutdoorStatic);
|
||||
_outdoorCount = scene.CopyIndexTo(
|
||||
RenderSceneIndex.OutdoorStatic,
|
||||
_outdoor);
|
||||
_outdoorCount = CompactAndSort(
|
||||
_outdoor,
|
||||
_outdoorCount);
|
||||
BuildPositionIndex(
|
||||
_outdoor,
|
||||
_outdoorCount,
|
||||
_outdoorPositions);
|
||||
EnsureCapacity(ref _outdoor, counts.OutdoorStatic);
|
||||
_outdoorCount = scene.CopyIndexTo(
|
||||
RenderSceneIndex.OutdoorStatic,
|
||||
_outdoor);
|
||||
_outdoorCount = CompactAndSort(
|
||||
_outdoor,
|
||||
_outdoorCount);
|
||||
|
||||
EnsureCapacity(ref _dynamics, counts.Dynamic);
|
||||
_dynamicCount = scene.CopyIndexTo(
|
||||
RenderSceneIndex.Dynamic,
|
||||
_dynamics);
|
||||
_dynamicCount = CompactAndSort(
|
||||
_dynamics,
|
||||
_dynamicCount);
|
||||
BuildPositionIndex(
|
||||
_dynamics,
|
||||
_dynamicCount,
|
||||
_dynamicPositions);
|
||||
|
||||
_indexGeneration = scene.Generation;
|
||||
_indexRevision = revision;
|
||||
}
|
||||
|
||||
EnsureCapacity(ref _dirty, counts.Dirty);
|
||||
_dirtyCount = scene.CopyIndexTo(
|
||||
RenderSceneIndex.Dirty,
|
||||
_dirty);
|
||||
for (int index = 0; index < _dirtyCount; index++)
|
||||
{
|
||||
RenderProjectionRecord record = _dirty[index];
|
||||
if (_outdoorPositions.TryGetValue(
|
||||
record.Id,
|
||||
out int outdoorPosition))
|
||||
{
|
||||
_outdoor[outdoorPosition] = record;
|
||||
}
|
||||
if (_dynamicPositions.TryGetValue(
|
||||
record.Id,
|
||||
out int dynamicPosition))
|
||||
{
|
||||
_dynamics[dynamicPosition] = record;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void AcknowledgeCachedDirtyRecords()
|
||||
{
|
||||
for (int index = 0; index < _dirtyCount; index++)
|
||||
{
|
||||
RenderProjectionId id = _dirty[index].Id;
|
||||
if (_outdoorPositions.TryGetValue(
|
||||
id,
|
||||
out int outdoorPosition))
|
||||
{
|
||||
_outdoor[outdoorPosition] =
|
||||
_outdoor[outdoorPosition] with
|
||||
{
|
||||
DirtyMask = RenderDirtyMask.None,
|
||||
};
|
||||
}
|
||||
if (_dynamicPositions.TryGetValue(
|
||||
id,
|
||||
out int dynamicPosition))
|
||||
{
|
||||
_dynamics[dynamicPosition] =
|
||||
_dynamics[dynamicPosition] with
|
||||
{
|
||||
DirtyMask = RenderDirtyMask.None,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void BuildPositionIndex(
|
||||
RenderProjectionRecord[] records,
|
||||
int count,
|
||||
Dictionary<RenderProjectionId, int> positions)
|
||||
{
|
||||
positions.Clear();
|
||||
positions.EnsureCapacity(count);
|
||||
for (int index = 0; index < count; index++)
|
||||
positions.Add(records[index].Id, index);
|
||||
EnsureCapacity(ref _dynamics, counts.Dynamic);
|
||||
_dynamicCount = scene.CopyIndexTo(
|
||||
RenderSceneIndex.Dynamic,
|
||||
_dynamics);
|
||||
_dynamicCount = CompactAndSort(
|
||||
_dynamics,
|
||||
_dynamicCount);
|
||||
}
|
||||
|
||||
private void BuildOutdoorRoutes(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue