feat(rendering): prove packed dispatcher output parity
Build a compare-only dispatcher classifier from RenderFrameView and compare complete opaque, alpha, selection, clip, light, texture, transform, and draw payloads against the accepted path. Preserve retail's stable equal-CYpt ordering with explicit draw-local submission ordinals so material-group history cannot affect alpha ties.
This commit is contained in:
parent
58b712c6ec
commit
29195fb255
11 changed files with 1264 additions and 65 deletions
|
|
@ -318,6 +318,9 @@ public sealed class CurrentRenderSceneOracleTests
|
|||
OpaqueGroupCount: 1,
|
||||
TransparentGroupCount: 1,
|
||||
TransparentDeferred: true,
|
||||
OpaqueDigest: new RenderSceneHash128(11, 12),
|
||||
TransparentDigest: new RenderSceneHash128(21, 22),
|
||||
TransparentSetDigest: new RenderSceneHash128(31, 32),
|
||||
Digest: new RenderSceneHash128(101, 202));
|
||||
oracle.ObserveDispatcherSubmission(in submission);
|
||||
CurrentRenderSceneOracleSnapshot first = oracle.Snapshot;
|
||||
|
|
|
|||
|
|
@ -86,6 +86,58 @@ public class InstanceGroupClearTests
|
|||
Assert.Equal(6, immediate.ImmediateInstances);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DispatcherFingerprint_EqualDistanceAlphaUsesOriginalSubmissionOrder()
|
||||
{
|
||||
WbDrawDispatcher.InstanceGroup first = MakeCompleteGroup(
|
||||
textureHandle: 0xAA,
|
||||
submissionOrder: 0);
|
||||
WbDrawDispatcher.InstanceGroup second = MakeCompleteGroup(
|
||||
textureHandle: 0xBB,
|
||||
submissionOrder: 1);
|
||||
var scratch = new List<WbDrawDispatcher.AlphaFingerprint>();
|
||||
|
||||
var forward = WbDrawDispatcher.CreateDispatcherSubmission(
|
||||
visibleInstanceCount: 2,
|
||||
immediateInstanceCount: 0,
|
||||
deferTransparent: true,
|
||||
opaque: [],
|
||||
transparent: [first, second],
|
||||
cameraWorldPosition: Vector3.Zero,
|
||||
alphaScratch: scratch);
|
||||
var reversedMaterialGroups =
|
||||
WbDrawDispatcher.CreateDispatcherSubmission(
|
||||
visibleInstanceCount: 2,
|
||||
immediateInstanceCount: 0,
|
||||
deferTransparent: true,
|
||||
opaque: [],
|
||||
transparent: [second, first],
|
||||
cameraWorldPosition: Vector3.Zero,
|
||||
alphaScratch: scratch);
|
||||
|
||||
Assert.Equal(
|
||||
forward.TransparentDigest,
|
||||
reversedMaterialGroups.TransparentDigest);
|
||||
|
||||
first.SubmissionOrders[0] = 1;
|
||||
second.SubmissionOrders[0] = 0;
|
||||
var reversedSubmission = WbDrawDispatcher.CreateDispatcherSubmission(
|
||||
visibleInstanceCount: 2,
|
||||
immediateInstanceCount: 0,
|
||||
deferTransparent: true,
|
||||
opaque: [],
|
||||
transparent: [first, second],
|
||||
cameraWorldPosition: Vector3.Zero,
|
||||
alphaScratch: scratch);
|
||||
|
||||
Assert.NotEqual(
|
||||
forward.TransparentDigest,
|
||||
reversedSubmission.TransparentDigest);
|
||||
Assert.Equal(
|
||||
forward.TransparentSetDigest,
|
||||
reversedSubmission.TransparentSetDigest);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CachedGroupHandle_RequiresLiveMatchingRegistration()
|
||||
{
|
||||
|
|
@ -210,9 +262,34 @@ public class InstanceGroupClearTests
|
|||
return group;
|
||||
}
|
||||
|
||||
private static WbDrawDispatcher.InstanceGroup MakeCompleteGroup(
|
||||
ulong textureHandle,
|
||||
int submissionOrder)
|
||||
{
|
||||
var group = new WbDrawDispatcher.InstanceGroup
|
||||
{
|
||||
FirstIndex = 0,
|
||||
BaseVertex = 0,
|
||||
IndexCount = 6,
|
||||
BindlessTextureHandle = textureHandle,
|
||||
TextureLayer = 0,
|
||||
Translucency = TranslucencyKind.AlphaBlend,
|
||||
};
|
||||
group.Matrices.Add(Matrix4x4.CreateTranslation(10f, 0f, 0f));
|
||||
group.LocalSortCenters.Add(Vector3.Zero);
|
||||
group.SubmissionOrders.Add(submissionOrder);
|
||||
group.Slots.Add(0u);
|
||||
group.LightSets.Add(WbDrawDispatcher.InstanceLightSet.Disabled);
|
||||
group.IndoorFlags.Add(0u);
|
||||
group.Opacities.Add(1f);
|
||||
group.SelectionLighting.Add(new Vector2(0f, 1f));
|
||||
return group;
|
||||
}
|
||||
|
||||
// #193 (regression from #188, 2026-07-09): WbDrawDispatcher's InstanceGroup holds
|
||||
// seven per-instance parallel lists — Matrices, LocalSortCenters, Slots,
|
||||
// LightSets, IndoorFlags, Opacities, SelectionLighting — appended in lockstep
|
||||
// eight per-instance parallel lists — Matrices, LocalSortCenters,
|
||||
// SubmissionOrders, Slots, LightSets, IndoorFlags, Opacities, and
|
||||
// SelectionLighting — appended in lockstep
|
||||
// (one entry per drawn instance) every frame. The
|
||||
// per-frame reset must clear ALL of them. #188 added Opacities but left it out of
|
||||
// the inline clear loop, so it grew one float per instance per frame forever; as
|
||||
|
|
@ -225,6 +302,7 @@ public class InstanceGroupClearTests
|
|||
var grp = new WbDrawDispatcher.InstanceGroup();
|
||||
grp.Matrices.Add(Matrix4x4.Identity);
|
||||
grp.LocalSortCenters.Add(Vector3.Zero);
|
||||
grp.SubmissionOrders.Add(0);
|
||||
grp.Slots.Add(1u);
|
||||
grp.LightSets.Add(WbDrawDispatcher.InstanceLightSet.Disabled);
|
||||
grp.IndoorFlags.Add(0u);
|
||||
|
|
@ -235,6 +313,7 @@ public class InstanceGroupClearTests
|
|||
|
||||
Assert.Empty(grp.Matrices);
|
||||
Assert.Empty(grp.LocalSortCenters);
|
||||
Assert.Empty(grp.SubmissionOrders);
|
||||
Assert.Empty(grp.Slots);
|
||||
Assert.Empty(grp.LightSets);
|
||||
Assert.Empty(grp.IndoorFlags);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue