feat(rendering): index incremental scene queries

Maintain packed render worksets as lifecycle deltas arrive and synchronize active animated statics without scanning the resident world. This keeps Slice F non-drawing while preparing exact spatial and feature queries for shadow comparison.

Release: 8,206 passed, 5 skipped.
This commit is contained in:
Erik 2026-07-24 22:12:26 +02:00
parent 58e7c2eb99
commit ff5d86175f
8 changed files with 745 additions and 16 deletions

View file

@ -304,6 +304,50 @@ internal readonly record struct RenderProjectionCounts(
};
}
internal enum RenderSceneIndex : byte
{
OutdoorStatic,
IndoorCellStatic,
Dynamic,
OutdoorDynamic,
PortalStraddlingDynamic,
Translucent,
Selectable,
LightCandidate,
Dirty,
}
internal readonly record struct RenderSceneIndexCounts(
int OutdoorStatic,
int IndoorCellStatic,
int Dynamic,
int OutdoorDynamic,
int PortalStraddlingDynamic,
int Translucent,
int Selectable,
int LightCandidate,
int Dirty)
{
public int For(RenderSceneIndex index) =>
index switch
{
RenderSceneIndex.OutdoorStatic => OutdoorStatic,
RenderSceneIndex.IndoorCellStatic => IndoorCellStatic,
RenderSceneIndex.Dynamic => Dynamic,
RenderSceneIndex.OutdoorDynamic => OutdoorDynamic,
RenderSceneIndex.PortalStraddlingDynamic =>
PortalStraddlingDynamic,
RenderSceneIndex.Translucent => Translucent,
RenderSceneIndex.Selectable => Selectable,
RenderSceneIndex.LightCandidate => LightCandidate,
RenderSceneIndex.Dirty => Dirty,
_ => throw new ArgumentOutOfRangeException(
nameof(index),
index,
null),
};
}
internal readonly record struct RenderDeltaApplyResult(
int Applied,
int Registered,
@ -357,6 +401,7 @@ internal sealed class RenderSceneDigestBuffer
internal interface IRenderSceneQuerySource
{
RenderProjectionCounts GetCounts(RenderSceneGeneration generation);
RenderSceneIndexCounts GetIndexCounts(RenderSceneGeneration generation);
bool TryGet(
RenderSceneGeneration generation,
@ -367,6 +412,22 @@ internal interface IRenderSceneQuerySource
RenderSceneGeneration generation,
RenderProjectionClass? projectionClass,
Span<RenderProjectionRecord> destination);
int CopyIndexTo(
RenderSceneGeneration generation,
RenderSceneIndex index,
Span<RenderProjectionRecord> destination);
int GetCellCount(
RenderSceneGeneration generation,
uint fullCellId,
bool dynamic);
int CopyCellTo(
RenderSceneGeneration generation,
uint fullCellId,
bool dynamic,
Span<RenderProjectionRecord> destination);
}
internal readonly struct RenderSceneQuery
@ -386,6 +447,9 @@ internal readonly struct RenderSceneQuery
public RenderProjectionCounts Counts =>
Source.GetCounts(Generation);
public RenderSceneIndexCounts IndexCounts =>
Source.GetIndexCounts(Generation);
public bool TryGet(
RenderProjectionId id,
out RenderProjectionRecord record) =>
@ -399,6 +463,35 @@ internal readonly struct RenderSceneQuery
Span<RenderProjectionRecord> destination) =>
Source.CopyTo(Generation, projectionClass, destination);
public int CopyIndexTo(
RenderSceneIndex index,
Span<RenderProjectionRecord> destination) =>
Source.CopyIndexTo(Generation, index, destination);
public int GetCellStaticCount(uint fullCellId) =>
Source.GetCellCount(Generation, fullCellId, dynamic: false);
public int CopyCellStaticsTo(
uint fullCellId,
Span<RenderProjectionRecord> destination) =>
Source.CopyCellTo(
Generation,
fullCellId,
dynamic: false,
destination);
public int GetCellDynamicCount(uint fullCellId) =>
Source.GetCellCount(Generation, fullCellId, dynamic: true);
public int CopyCellDynamicsTo(
uint fullCellId,
Span<RenderProjectionRecord> destination) =>
Source.CopyCellTo(
Generation,
fullCellId,
dynamic: true,
destination);
private IRenderSceneQuerySource Source =>
_source
?? throw new InvalidOperationException("The render-scene query is uninitialized.");
@ -420,5 +513,7 @@ internal interface IRenderScene : IDisposable
RenderSceneQuery OpenQuery();
void ClearDirty();
void Clear(RenderSceneGeneration replacementGeneration);
}