perf(rendering): retain packed classification
Retain appearance classification per projection while refreshing transforms, clip slots, lights, selection lighting, and group instance payloads each frame. Incomplete resources and active animation remain on the live classification path, and only an exact full packed comparison acknowledges scene dirtiness.
This commit is contained in:
parent
f10dec58ba
commit
54d17eb446
7 changed files with 731 additions and 30 deletions
|
|
@ -51,6 +51,13 @@ internal readonly record struct RenderFrameProductComparisonSnapshot(
|
|||
string? SelectionOutputFirstMismatch,
|
||||
RenderSceneHash128 SelectionOutputExpectedDigest,
|
||||
RenderSceneHash128 SelectionOutputActualDigest,
|
||||
int PackedClassificationProjectionCount,
|
||||
int PackedClassificationStaticRebuildCount,
|
||||
int PackedClassificationSameFrameReuseCount,
|
||||
int PackedClassificationCrossFrameReuseCount,
|
||||
int PackedClassificationAnimatedCount,
|
||||
int PackedClassificationRetiredCount,
|
||||
long PackedClassificationRetainedPayloadBytes,
|
||||
RenderFrameDiagnosticCounts ProductCounts)
|
||||
{
|
||||
public static RenderFrameProductComparisonSnapshot Disabled { get; } =
|
||||
|
|
@ -90,6 +97,13 @@ internal readonly record struct RenderFrameProductComparisonSnapshot(
|
|||
SelectionOutputFirstMismatch: null,
|
||||
SelectionOutputExpectedDigest: RenderSceneHash128.Empty,
|
||||
SelectionOutputActualDigest: RenderSceneHash128.Empty,
|
||||
PackedClassificationProjectionCount: 0,
|
||||
PackedClassificationStaticRebuildCount: 0,
|
||||
PackedClassificationSameFrameReuseCount: 0,
|
||||
PackedClassificationCrossFrameReuseCount: 0,
|
||||
PackedClassificationAnimatedCount: 0,
|
||||
PackedClassificationRetiredCount: 0,
|
||||
PackedClassificationRetainedPayloadBytes: 0,
|
||||
ProductCounts: default);
|
||||
}
|
||||
|
||||
|
|
@ -136,6 +150,8 @@ internal sealed class RenderScenePViewFrameProductController :
|
|||
private ulong _selectionOutputSuccessfulComparisonCount;
|
||||
private long _selectionOutputMismatchCount;
|
||||
private string? _selectionOutputFirstMismatch;
|
||||
private PackedClassificationCacheSnapshot
|
||||
_packedClassification;
|
||||
|
||||
public RenderScenePViewFrameProductController(
|
||||
RenderSceneShadowRuntime shadow,
|
||||
|
|
@ -280,6 +296,17 @@ internal sealed class RenderScenePViewFrameProductController :
|
|||
in view,
|
||||
tupleLandblockId,
|
||||
cameraWorldPosition);
|
||||
if (_dispatcher is not null
|
||||
&& mismatch is null
|
||||
&& packed.Successful
|
||||
&& classified.Successful)
|
||||
{
|
||||
// The frame product and retained classifier have consumed every
|
||||
// dirty fact and matched the production oracle. A later update
|
||||
// starts the next dirty epoch; a mismatch or exception above
|
||||
// deliberately leaves dirtiness intact for the next rebuild.
|
||||
_shadow.ClearDirty();
|
||||
}
|
||||
|
||||
Snapshot = new RenderFrameProductComparisonSnapshot(
|
||||
Enabled: true,
|
||||
|
|
@ -335,6 +362,20 @@ internal sealed class RenderScenePViewFrameProductController :
|
|||
classified.ExpectedSelectionDigest,
|
||||
SelectionOutputActualDigest:
|
||||
classified.ActualSelectionDigest,
|
||||
PackedClassificationProjectionCount:
|
||||
_packedClassification.ProjectionCount,
|
||||
PackedClassificationStaticRebuildCount:
|
||||
_packedClassification.StaticRebuildCount,
|
||||
PackedClassificationSameFrameReuseCount:
|
||||
_packedClassification.SameFrameReuseCount,
|
||||
PackedClassificationCrossFrameReuseCount:
|
||||
_packedClassification.CrossFrameReuseCount,
|
||||
PackedClassificationAnimatedCount:
|
||||
_packedClassification.AnimatedClassificationCount,
|
||||
PackedClassificationRetiredCount:
|
||||
_packedClassification.RetiredProjectionCount,
|
||||
PackedClassificationRetainedPayloadBytes:
|
||||
_packedClassification.RetainedPayloadBytes,
|
||||
ProductCounts: view.DiagnosticCounts);
|
||||
}
|
||||
|
||||
|
|
@ -351,6 +392,8 @@ internal sealed class RenderScenePViewFrameProductController :
|
|||
in view,
|
||||
tupleLandblockId,
|
||||
cameraWorldPosition);
|
||||
_packedClassification =
|
||||
dispatcher.PackedClassificationSnapshot;
|
||||
IReadOnlyList<CurrentRenderDispatcherSubmission> expected =
|
||||
_current.DispatcherSubmissions;
|
||||
IReadOnlyList<CurrentRenderDispatcherSubmission> actual =
|
||||
|
|
@ -420,6 +463,7 @@ internal sealed class RenderScenePViewFrameProductController :
|
|||
}
|
||||
|
||||
return new ClassifiedOutputComparison(
|
||||
Successful: mismatch is null && selectionMismatch is null,
|
||||
expected.Count,
|
||||
actual.Count,
|
||||
expectedDigest,
|
||||
|
|
@ -661,7 +705,10 @@ internal sealed class RenderScenePViewFrameProductController :
|
|||
}
|
||||
}
|
||||
|
||||
return new PackedInputComparison(expectedDigest, actualDigest);
|
||||
return new PackedInputComparison(
|
||||
Successful: mismatch is null,
|
||||
expectedDigest,
|
||||
actualDigest);
|
||||
}
|
||||
|
||||
private static uint DispatcherCacheLandblock(
|
||||
|
|
@ -780,10 +827,12 @@ internal sealed class RenderScenePViewFrameProductController :
|
|||
RenderProjectionId ProjectionId);
|
||||
|
||||
private readonly record struct PackedInputComparison(
|
||||
bool Successful,
|
||||
RenderSceneHash128 ExpectedDigest,
|
||||
RenderSceneHash128 ActualDigest);
|
||||
|
||||
private readonly record struct ClassifiedOutputComparison(
|
||||
bool Successful,
|
||||
int ExpectedDrawCount,
|
||||
int ActualDrawCount,
|
||||
RenderSceneHash128 ExpectedDigest,
|
||||
|
|
|
|||
|
|
@ -223,6 +223,7 @@ internal sealed class RenderSceneShadowComparisonController :
|
|||
private readonly RenderSceneShadowRuntime _shadow;
|
||||
private readonly CurrentRenderSceneOracle _oracle;
|
||||
private readonly Action<string>? _log;
|
||||
private readonly bool _acknowledgeDirty;
|
||||
private readonly List<RenderProjectionRecord> _sceneRecords = [];
|
||||
private readonly HashSet<RenderProjectionId> _expectedIds = [];
|
||||
private ulong _renderFrameSequence;
|
||||
|
|
@ -236,11 +237,13 @@ internal sealed class RenderSceneShadowComparisonController :
|
|||
public RenderSceneShadowComparisonController(
|
||||
RenderSceneShadowRuntime shadow,
|
||||
CurrentRenderSceneOracle oracle,
|
||||
Action<string>? log = null)
|
||||
Action<string>? log = null,
|
||||
bool acknowledgeDirty = true)
|
||||
{
|
||||
_shadow = shadow ?? throw new ArgumentNullException(nameof(shadow));
|
||||
_oracle = oracle ?? throw new ArgumentNullException(nameof(oracle));
|
||||
_log = log;
|
||||
_acknowledgeDirty = acknowledgeDirty;
|
||||
Snapshot = BuildSnapshot();
|
||||
}
|
||||
|
||||
|
|
@ -300,7 +303,8 @@ internal sealed class RenderSceneShadowComparisonController :
|
|||
}
|
||||
}
|
||||
|
||||
_shadow.ClearDirty();
|
||||
if (_acknowledgeDirty && mismatch is null)
|
||||
_shadow.ClearDirty();
|
||||
Snapshot = BuildSnapshot();
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue