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:
Erik 2026-07-25 00:44:58 +02:00
parent 720578592b
commit d8d9897376
13 changed files with 593 additions and 24 deletions

View file

@ -50,7 +50,10 @@ internal readonly record struct CurrentRenderDispatcherFingerprint(
int MeshRefIndex,
uint TupleLandblockId,
uint CacheLandblockId,
CurrentRenderProjectionFingerprint Projection);
CurrentRenderProjectionFingerprint Projection,
uint GfxObjId,
Matrix4x4 PartTransform,
RenderSceneHash128 SurfaceOverrides);
internal readonly record struct CurrentRenderDispatcherSubmission(
int VisibleInstanceCount,
@ -535,7 +538,13 @@ internal sealed class CurrentRenderSceneOracle :
MeshRefIndex: tuple.MeshRefIndex,
TupleLandblockId: tuple.LandblockId,
CacheLandblockId: cacheLandblockId,
Projection: projection);
Projection: projection,
GfxObjId: tuple.Entity.MeshRefs[tuple.MeshRefIndex].GfxObjId,
PartTransform:
tuple.Entity.MeshRefs[tuple.MeshRefIndex].PartTransform,
SurfaceOverrides: CreateSurfaceOverrideFingerprint(
tuple.Entity.MeshRefs[tuple.MeshRefIndex]
.SurfaceOverrides));
_dispatcherCandidates.Add(candidate);
AddDispatcherCandidate(ref _dispatcherHash, in candidate);
}
@ -730,6 +739,7 @@ internal sealed class CurrentRenderSceneOracle :
MeshRef mesh = entity.MeshRefs[meshIndex];
geometry.Add(mesh.GfxObjId);
geometry.Add(mesh.PartTransform);
AddSurfaceOverrides(ref geometry, mesh.SurfaceOverrides);
}
StableRenderHash128 appearance = StableRenderHash128.Create();
@ -795,6 +805,54 @@ internal sealed class CurrentRenderSceneOracle :
Appearance: appearance.Finish());
}
private static void AddSurfaceOverrides(
ref StableRenderHash128 geometry,
IReadOnlyDictionary<uint, uint>? overrides)
{
RenderSceneHash128 fingerprint =
CreateSurfaceOverrideFingerprint(overrides);
geometry.Add(fingerprint.Low);
geometry.Add(fingerprint.High);
}
internal static RenderSceneHash128 CreateSurfaceOverrideFingerprint(
IReadOnlyDictionary<uint, uint>? overrides)
{
if (overrides is null)
{
StableRenderHash128 missing = StableRenderHash128.Create();
missing.Add(-1);
return missing.Finish();
}
ulong xorLow = 0;
ulong xorHigh = 0;
ulong sumLow = 0;
ulong sumHigh = 0;
foreach ((uint surfaceId, uint replacementId) in overrides)
{
StableRenderHash128 pair = StableRenderHash128.Create();
pair.Add(surfaceId);
pair.Add(replacementId);
RenderSceneHash128 value = pair.Finish();
xorLow ^= value.Low;
xorHigh ^= value.High;
unchecked
{
sumLow += value.Low;
sumHigh += value.High;
}
}
StableRenderHash128 geometry = StableRenderHash128.Create();
geometry.Add(overrides.Count);
geometry.Add(xorLow);
geometry.Add(xorHigh);
geometry.Add(sumLow);
geometry.Add(sumHigh);
return geometry.Finish();
}
private static RenderSceneHash128 FingerprintSelectionGeometry(
RetailSelectionMesh mesh)
{
@ -854,6 +912,10 @@ internal sealed class CurrentRenderSceneOracle :
hash.Add(candidate.MeshRefIndex);
hash.Add(candidate.TupleLandblockId);
hash.Add(candidate.CacheLandblockId);
hash.Add(candidate.GfxObjId);
hash.Add(candidate.PartTransform);
hash.Add(candidate.SurfaceOverrides.Low);
hash.Add(candidate.SurfaceOverrides.High);
CurrentRenderProjectionFingerprint projection = candidate.Projection;
AddProjection(ref hash, in projection);
}