fix(rendering): reconcile shadow roots from live runtime
Recover ordinary live roots from LiveEntityRuntime's canonical active spatial workset instead of relying on already-retained derived records. Keep attached children callback-authoritative, cache immutable selection geometry fingerprints, and pin zero-allocation retained update paths with regression tests. Release gate: 3,733 App tests / 3 skips; 8,217 complete-solution tests / 5 skips. Co-Authored-By: OpenAI Codex <codex@openai.com>
This commit is contained in:
parent
056bbd4efd
commit
91463db551
7 changed files with 272 additions and 15 deletions
|
|
@ -211,6 +211,8 @@ internal sealed class CurrentRenderSceneOracle :
|
|||
new(ReferenceEqualityComparer.Instance);
|
||||
private readonly List<CurrentRenderSelectionFingerprint>
|
||||
_selectionParts = [];
|
||||
private readonly Dictionary<uint, SelectionGeometryCacheEntry>
|
||||
_selectionGeometryByGfxObj = [];
|
||||
private ulong _frameSequence;
|
||||
private int _abortedFrames;
|
||||
private int _outdoorStaticCount;
|
||||
|
|
@ -637,16 +639,15 @@ internal sealed class CurrentRenderSceneOracle :
|
|||
}
|
||||
ArgumentNullException.ThrowIfNull(mesh);
|
||||
|
||||
StableRenderHash128 geometry = StableRenderHash128.Create();
|
||||
geometry.Add(mesh.SphereCenter);
|
||||
geometry.Add(mesh.SphereRadius);
|
||||
geometry.Add(mesh.Polygons.Count);
|
||||
foreach (RetailSelectionPolygon polygon in mesh.Polygons)
|
||||
if (!_selectionGeometryByGfxObj.TryGetValue(
|
||||
gfxObjId,
|
||||
out SelectionGeometryCacheEntry cachedGeometry)
|
||||
|| !ReferenceEquals(cachedGeometry.Mesh, mesh))
|
||||
{
|
||||
geometry.Add(polygon.SingleSided);
|
||||
geometry.Add(polygon.Vertices.Count);
|
||||
foreach (Vector3 vertex in polygon.Vertices)
|
||||
geometry.Add(vertex);
|
||||
cachedGeometry = new SelectionGeometryCacheEntry(
|
||||
mesh,
|
||||
FingerprintSelectionGeometry(mesh));
|
||||
_selectionGeometryByGfxObj[gfxObjId] = cachedGeometry;
|
||||
}
|
||||
|
||||
var fingerprint = new CurrentRenderSelectionFingerprint(
|
||||
|
|
@ -656,7 +657,7 @@ internal sealed class CurrentRenderSceneOracle :
|
|||
PartIndex: partIndex,
|
||||
GfxObjId: gfxObjId,
|
||||
LocalToWorld: localToWorld,
|
||||
Geometry: geometry.Finish());
|
||||
Geometry: cachedGeometry.Fingerprint);
|
||||
_selectionParts.Add(fingerprint);
|
||||
_selectionHash.Add(fingerprint.Sequence);
|
||||
_selectionHash.Add(fingerprint.ServerGuid);
|
||||
|
|
@ -722,8 +723,11 @@ internal sealed class CurrentRenderSceneOracle :
|
|||
|
||||
StableRenderHash128 geometry = StableRenderHash128.Create();
|
||||
geometry.Add(entity.MeshRefs.Count);
|
||||
foreach (MeshRef mesh in entity.MeshRefs)
|
||||
for (int meshIndex = 0;
|
||||
meshIndex < entity.MeshRefs.Count;
|
||||
meshIndex++)
|
||||
{
|
||||
MeshRef mesh = entity.MeshRefs[meshIndex];
|
||||
geometry.Add(mesh.GfxObjId);
|
||||
geometry.Add(mesh.PartTransform);
|
||||
}
|
||||
|
|
@ -734,8 +738,12 @@ internal sealed class CurrentRenderSceneOracle :
|
|||
appearance.Add(true);
|
||||
appearance.Add(palette.BasePaletteId);
|
||||
appearance.Add(palette.SubPalettes.Count);
|
||||
foreach (PaletteOverride.SubPaletteRange range in palette.SubPalettes)
|
||||
for (int rangeIndex = 0;
|
||||
rangeIndex < palette.SubPalettes.Count;
|
||||
rangeIndex++)
|
||||
{
|
||||
PaletteOverride.SubPaletteRange range =
|
||||
palette.SubPalettes[rangeIndex];
|
||||
appearance.Add(range.SubPaletteId);
|
||||
appearance.Add(range.Offset);
|
||||
appearance.Add(range.Length);
|
||||
|
|
@ -747,8 +755,11 @@ internal sealed class CurrentRenderSceneOracle :
|
|||
}
|
||||
|
||||
appearance.Add(entity.PartOverrides.Count);
|
||||
foreach (PartOverride part in entity.PartOverrides)
|
||||
for (int partIndex = 0;
|
||||
partIndex < entity.PartOverrides.Count;
|
||||
partIndex++)
|
||||
{
|
||||
PartOverride part = entity.PartOverrides[partIndex];
|
||||
appearance.Add(part.PartIndex);
|
||||
appearance.Add(part.GfxObjId);
|
||||
}
|
||||
|
|
@ -784,6 +795,31 @@ internal sealed class CurrentRenderSceneOracle :
|
|||
Appearance: appearance.Finish());
|
||||
}
|
||||
|
||||
private static RenderSceneHash128 FingerprintSelectionGeometry(
|
||||
RetailSelectionMesh mesh)
|
||||
{
|
||||
StableRenderHash128 geometry = StableRenderHash128.Create();
|
||||
geometry.Add(mesh.SphereCenter);
|
||||
geometry.Add(mesh.SphereRadius);
|
||||
geometry.Add(mesh.Polygons.Count);
|
||||
for (int polygonIndex = 0;
|
||||
polygonIndex < mesh.Polygons.Count;
|
||||
polygonIndex++)
|
||||
{
|
||||
RetailSelectionPolygon polygon = mesh.Polygons[polygonIndex];
|
||||
geometry.Add(polygon.SingleSided);
|
||||
geometry.Add(polygon.Vertices.Count);
|
||||
for (int vertexIndex = 0;
|
||||
vertexIndex < polygon.Vertices.Count;
|
||||
vertexIndex++)
|
||||
{
|
||||
geometry.Add(polygon.Vertices[vertexIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
return geometry.Finish();
|
||||
}
|
||||
|
||||
private static InteriorEntityPartition.ProjectionClass ProjectionClassOf(
|
||||
WorldEntity entity) =>
|
||||
entity.ServerGuid != 0
|
||||
|
|
@ -792,6 +828,10 @@ internal sealed class CurrentRenderSceneOracle :
|
|||
? InteriorEntityPartition.ProjectionClass.CellStatic
|
||||
: InteriorEntityPartition.ProjectionClass.OutdoorStatic;
|
||||
|
||||
private readonly record struct SelectionGeometryCacheEntry(
|
||||
RetailSelectionMesh Mesh,
|
||||
RenderSceneHash128 Fingerprint);
|
||||
|
||||
private static void AddPViewCandidate(
|
||||
ref StableRenderHash128 hash,
|
||||
in CurrentRenderPViewCandidateFingerprint candidate)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue