feat(rendering): pack scene dispatcher inputs
Capture immutable presentation payloads in the render scene, flatten unique entity and mesh-part records into the borrowed frame arena, and compare every routed dispatcher input tuple without changing the production draw source.
This commit is contained in:
parent
720578592b
commit
d8d9897376
13 changed files with 593 additions and 24 deletions
|
|
@ -1,5 +1,6 @@
|
|||
using System.Numerics;
|
||||
using AcDream.Core.Selection;
|
||||
using AcDream.Core.World;
|
||||
|
||||
namespace AcDream.App.Rendering.Scene;
|
||||
|
||||
|
|
@ -36,6 +37,17 @@ internal readonly record struct RenderFrameTransformRecord(
|
|||
int PartIndex,
|
||||
Matrix4x4 LocalToWorld);
|
||||
|
||||
internal readonly record struct RenderFrameEntityCandidate(
|
||||
RenderProjectionRecord Projection,
|
||||
int MeshPartOffset,
|
||||
int MeshPartCount,
|
||||
bool Animated);
|
||||
|
||||
internal readonly record struct RenderFrameMeshPart(
|
||||
RenderProjectionId ProjectionId,
|
||||
int PartIndex,
|
||||
MeshRef MeshRef);
|
||||
|
||||
internal readonly record struct RenderFrameClassificationRecord(
|
||||
RenderProjectionId ProjectionId,
|
||||
int CandidateIndex,
|
||||
|
|
@ -77,7 +89,9 @@ internal readonly record struct RenderFrameDiagnosticCounts(
|
|||
int AlphaClassificationCount,
|
||||
int LightSetCount,
|
||||
int SelectionPartCount,
|
||||
int RouteCandidateCount);
|
||||
int RouteCandidateCount,
|
||||
int EntityCandidateCount,
|
||||
int MeshPartCount);
|
||||
|
||||
/// <summary>
|
||||
/// A validated borrowed view over one reusable frame arena. Copies are safe:
|
||||
|
|
@ -133,6 +147,12 @@ internal readonly struct RenderFrameView
|
|||
public ReadOnlySpan<RenderFrameTransformRecord> Transforms =>
|
||||
Arena.Transforms;
|
||||
|
||||
public ReadOnlySpan<RenderFrameEntityCandidate> EntityCandidates =>
|
||||
Arena.EntityCandidates;
|
||||
|
||||
public ReadOnlySpan<RenderFrameMeshPart> MeshParts =>
|
||||
Arena.MeshParts;
|
||||
|
||||
public ReadOnlySpan<RenderFrameClassificationRecord> Classifications =>
|
||||
Arena.Classifications;
|
||||
|
||||
|
|
@ -192,6 +212,8 @@ internal sealed class RenderFrameArena
|
|||
private RenderFrameCellRange[] _cellRanges = [];
|
||||
private RenderProjectionRecord[] _dynamics = [];
|
||||
private RenderFrameTransformRecord[] _transforms = [];
|
||||
private RenderFrameEntityCandidate[] _entityCandidates = [];
|
||||
private RenderFrameMeshPart[] _meshParts = [];
|
||||
private RenderFrameClassificationRecord[] _classifications = [];
|
||||
private RenderFrameObjectLightSet[] _lightSets = [];
|
||||
private RenderFrameSelectionPart[] _selectionParts = [];
|
||||
|
|
@ -202,6 +224,8 @@ internal sealed class RenderFrameArena
|
|||
private int _cellRangeCount;
|
||||
private int _dynamicCount;
|
||||
private int _transformCount;
|
||||
private int _entityCandidateCount;
|
||||
private int _meshPartCount;
|
||||
private int _classificationCount;
|
||||
private int _lightSetCount;
|
||||
private int _selectionPartCount;
|
||||
|
|
@ -234,7 +258,9 @@ internal sealed class RenderFrameArena
|
|||
_alphaClassificationCount,
|
||||
_lightSetCount,
|
||||
_selectionPartCount,
|
||||
_routeCandidateCount);
|
||||
_routeCandidateCount,
|
||||
_entityCandidateCount,
|
||||
_meshPartCount);
|
||||
|
||||
internal ReadOnlySpan<RenderProjectionRecord> OutdoorStaticCandidates =>
|
||||
_outdoor.AsSpan(0, _outdoorCount);
|
||||
|
|
@ -251,6 +277,12 @@ internal sealed class RenderFrameArena
|
|||
internal ReadOnlySpan<RenderFrameTransformRecord> Transforms =>
|
||||
_transforms.AsSpan(0, _transformCount);
|
||||
|
||||
internal ReadOnlySpan<RenderFrameEntityCandidate> EntityCandidates =>
|
||||
_entityCandidates.AsSpan(0, _entityCandidateCount);
|
||||
|
||||
internal ReadOnlySpan<RenderFrameMeshPart> MeshParts =>
|
||||
_meshParts.AsSpan(0, _meshPartCount);
|
||||
|
||||
internal ReadOnlySpan<RenderFrameClassificationRecord> Classifications =>
|
||||
_classifications.AsSpan(0, _classificationCount);
|
||||
|
||||
|
|
@ -284,6 +316,8 @@ internal sealed class RenderFrameArena
|
|||
_cellRangeCount = 0;
|
||||
_dynamicCount = 0;
|
||||
_transformCount = 0;
|
||||
_entityCandidateCount = 0;
|
||||
_meshPartCount = 0;
|
||||
_classificationCount = 0;
|
||||
_lightSetCount = 0;
|
||||
_selectionPartCount = 0;
|
||||
|
|
@ -397,6 +431,46 @@ internal sealed class RenderFrameArena
|
|||
_transforms[_transformCount++] = transform;
|
||||
}
|
||||
|
||||
internal void AddEntityCandidate(
|
||||
ulong epoch,
|
||||
in RenderProjectionRecord projection,
|
||||
bool animated)
|
||||
{
|
||||
EnsureBuilding(epoch);
|
||||
IReadOnlyList<MeshRef>? meshRefs =
|
||||
projection.EntityPayload.MeshRefs;
|
||||
int meshPartCount = meshRefs?.Count ?? 0;
|
||||
if (meshPartCount != projection.MeshSet.MeshCount)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"Projection {projection.Id} declares "
|
||||
+ $"{projection.MeshSet.MeshCount} mesh parts but its "
|
||||
+ $"presentation payload contains {meshPartCount}.");
|
||||
}
|
||||
|
||||
int meshPartOffset = _meshPartCount;
|
||||
EnsureCapacity(
|
||||
ref _meshParts,
|
||||
checked(meshPartOffset + meshPartCount));
|
||||
for (int partIndex = 0; partIndex < meshPartCount; partIndex++)
|
||||
{
|
||||
_meshParts[_meshPartCount++] = new RenderFrameMeshPart(
|
||||
projection.Id,
|
||||
partIndex,
|
||||
meshRefs![partIndex]);
|
||||
}
|
||||
|
||||
EnsureCapacity(
|
||||
ref _entityCandidates,
|
||||
_entityCandidateCount + 1);
|
||||
_entityCandidates[_entityCandidateCount++] =
|
||||
new RenderFrameEntityCandidate(
|
||||
projection,
|
||||
meshPartOffset,
|
||||
meshPartCount,
|
||||
animated);
|
||||
}
|
||||
|
||||
internal void AddClassification(
|
||||
ulong epoch,
|
||||
in RenderFrameClassificationRecord classification)
|
||||
|
|
@ -529,6 +603,10 @@ internal sealed class RenderFrameArena
|
|||
{
|
||||
if (_selectionPartCount > 0)
|
||||
Array.Clear(_selectionParts, 0, _selectionPartCount);
|
||||
if (_entityCandidateCount > 0)
|
||||
Array.Clear(_entityCandidates, 0, _entityCandidateCount);
|
||||
if (_meshPartCount > 0)
|
||||
Array.Clear(_meshParts, 0, _meshPartCount);
|
||||
}
|
||||
|
||||
private static void EnsureCapacity<T>(ref T[] values, int required)
|
||||
|
|
@ -603,6 +681,11 @@ internal readonly struct RenderFrameWriter
|
|||
public void AddTransform(in RenderFrameTransformRecord transform) =>
|
||||
Arena.AddTransform(_epoch, in transform);
|
||||
|
||||
public void AddEntityCandidate(
|
||||
in RenderProjectionRecord projection,
|
||||
bool animated) =>
|
||||
Arena.AddEntityCandidate(_epoch, in projection, animated);
|
||||
|
||||
public void AddClassification(
|
||||
in RenderFrameClassificationRecord classification) =>
|
||||
Arena.AddClassification(_epoch, in classification);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue