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
|
|
@ -10,8 +10,7 @@ namespace AcDream.App.Rendering.Scene.Arch;
|
|||
/// projection. Arch identities never leave this namespace; callers only see
|
||||
/// generation-checked acdream value types.
|
||||
///
|
||||
/// Slice F introduced this owner in non-drawing shadow mode; Slice G supplies
|
||||
/// its borrowed frame product to the production renderer.
|
||||
/// Slice F1 deliberately leaves this owner unbound and non-drawing.
|
||||
/// </summary>
|
||||
internal sealed class ArchRenderScene : IRenderScene, IRenderSceneQuerySource
|
||||
{
|
||||
|
|
@ -36,7 +35,6 @@ internal sealed class ArchRenderScene : IRenderScene, IRenderSceneQuerySource
|
|||
private ArchWorld _world;
|
||||
private RenderProjectionCounts _counts;
|
||||
private ulong _lastAppliedJournalSequence;
|
||||
private ulong _indexRevision = 1;
|
||||
private bool _disposed;
|
||||
|
||||
public ArchRenderScene(RenderSceneGeneration initialGeneration)
|
||||
|
|
@ -227,7 +225,6 @@ internal sealed class ArchRenderScene : IRenderScene, IRenderSceneQuerySource
|
|||
_counts = default;
|
||||
_lastAppliedJournalSequence = 0;
|
||||
Generation = replacementGeneration;
|
||||
AdvanceIndexRevision();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
|
@ -277,13 +274,6 @@ internal sealed class ArchRenderScene : IRenderScene, IRenderSceneQuerySource
|
|||
_dirty.Count);
|
||||
}
|
||||
|
||||
ulong IRenderSceneQuerySource.GetIndexRevision(
|
||||
RenderSceneGeneration generation)
|
||||
{
|
||||
EnsureQueryGeneration(generation);
|
||||
return _indexRevision;
|
||||
}
|
||||
|
||||
bool IRenderSceneQuerySource.TryGet(
|
||||
RenderSceneGeneration generation,
|
||||
RenderProjectionId id,
|
||||
|
|
@ -601,12 +591,6 @@ internal sealed class ArchRenderScene : IRenderScene, IRenderSceneQuerySource
|
|||
in RenderProjectionRecord prior,
|
||||
in RenderProjectionRecord current)
|
||||
{
|
||||
if (IndexMembershipEquals(in prior, in current))
|
||||
{
|
||||
SynchronizeDirtyIndex(in current);
|
||||
return;
|
||||
}
|
||||
|
||||
RemoveFromIndices(in prior);
|
||||
AddToIndices(in current);
|
||||
}
|
||||
|
|
@ -651,7 +635,6 @@ internal sealed class ArchRenderScene : IRenderScene, IRenderSceneQuerySource
|
|||
_lightCandidates.Add(record.Id);
|
||||
if (record.DirtyMask != RenderDirtyMask.None)
|
||||
_dirty.Add(record.Id);
|
||||
AdvanceIndexRevision();
|
||||
}
|
||||
|
||||
private void RemoveFromIndices(in RenderProjectionRecord record)
|
||||
|
|
@ -667,46 +650,6 @@ internal sealed class ArchRenderScene : IRenderScene, IRenderSceneQuerySource
|
|||
_dirty.Remove(record.Id);
|
||||
RemoveCell(_cellStatics, record.Residency.FullCellId, record.Id);
|
||||
RemoveCell(_cellDynamics, record.Residency.FullCellId, record.Id);
|
||||
AdvanceIndexRevision();
|
||||
}
|
||||
|
||||
private static bool IndexMembershipEquals(
|
||||
in RenderProjectionRecord left,
|
||||
in RenderProjectionRecord right)
|
||||
{
|
||||
const RenderProjectionFlags indexedFlags =
|
||||
RenderProjectionFlags.Translucent
|
||||
| RenderProjectionFlags.Selectable
|
||||
| RenderProjectionFlags.LightCandidate
|
||||
| RenderProjectionFlags.PortalStraddling
|
||||
| RenderProjectionFlags.SpatiallyResident;
|
||||
|
||||
return left.ProjectionClass == right.ProjectionClass
|
||||
&& left.Source.ParentCellId == right.Source.ParentCellId
|
||||
&& left.Residency.FullCellId == right.Residency.FullCellId
|
||||
&& (left.Flags & indexedFlags) == (right.Flags & indexedFlags)
|
||||
&& left.MeshSet.MeshCount == right.MeshSet.MeshCount
|
||||
&& left.SortKey == right.SortKey;
|
||||
}
|
||||
|
||||
private void SynchronizeDirtyIndex(
|
||||
in RenderProjectionRecord record)
|
||||
{
|
||||
if (record.DirtyMask == RenderDirtyMask.None)
|
||||
_dirty.Remove(record.Id);
|
||||
else
|
||||
_dirty.Add(record.Id);
|
||||
}
|
||||
|
||||
private void AdvanceIndexRevision()
|
||||
{
|
||||
if (_indexRevision == ulong.MaxValue)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Render-scene index revision space was exhausted.");
|
||||
}
|
||||
|
||||
_indexRevision++;
|
||||
}
|
||||
|
||||
private static bool IsDynamic(RenderProjectionClass projectionClass) =>
|
||||
|
|
|
|||
|
|
@ -455,7 +455,6 @@ internal interface IRenderSceneQuerySource
|
|||
{
|
||||
RenderProjectionCounts GetCounts(RenderSceneGeneration generation);
|
||||
RenderSceneIndexCounts GetIndexCounts(RenderSceneGeneration generation);
|
||||
ulong GetIndexRevision(RenderSceneGeneration generation);
|
||||
|
||||
bool TryGet(
|
||||
RenderSceneGeneration generation,
|
||||
|
|
@ -504,9 +503,6 @@ internal readonly struct RenderSceneQuery
|
|||
public RenderSceneIndexCounts IndexCounts =>
|
||||
Source.GetIndexCounts(Generation);
|
||||
|
||||
public ulong IndexRevision =>
|
||||
Source.GetIndexRevision(Generation);
|
||||
|
||||
public bool TryGet(
|
||||
RenderProjectionId id,
|
||||
out RenderProjectionRecord record) =>
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -50,12 +50,10 @@ internal interface IRenderSceneShadowSnapshotSource
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Owner of the derived render projection. Slice F introduced it as a
|
||||
/// diagnostic shadow; Slice G keeps the same generation/incarnation journal
|
||||
/// boundary while lending its frame product to production drawing. Accepted
|
||||
/// world/live lifecycle edges append to one ordered journal, and the update
|
||||
/// thread drains it only after current-frame animation, network, and
|
||||
/// attachment reconciliation.
|
||||
/// Diagnostic-only owner of Slice F's non-drawing render projection. The
|
||||
/// normal runtime never constructs this type. Accepted world/live lifecycle
|
||||
/// edges append to one ordered journal, and the update thread drains it only
|
||||
/// after current-frame animation, network, and attachment reconciliation.
|
||||
/// </summary>
|
||||
internal sealed class RenderSceneShadowRuntime : IDisposable
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue