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
|
|
@ -406,6 +406,41 @@ public sealed class CurrentRenderSceneOracleTests
|
|||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SurfaceOverrideFingerprint_IsOrderIndependentAndContentExact()
|
||||
{
|
||||
var first = new Dictionary<uint, uint>
|
||||
{
|
||||
[0x0800_0002] = 0x0500_0012,
|
||||
[0x0800_0001] = 0x0500_0011,
|
||||
};
|
||||
var reordered = new Dictionary<uint, uint>
|
||||
{
|
||||
[0x0800_0001] = 0x0500_0011,
|
||||
[0x0800_0002] = 0x0500_0012,
|
||||
};
|
||||
var changed = new Dictionary<uint, uint>
|
||||
{
|
||||
[0x0800_0001] = 0x0500_0011,
|
||||
[0x0800_0002] = 0x0500_0013,
|
||||
};
|
||||
|
||||
RenderSceneHash128 expected =
|
||||
CurrentRenderSceneOracle.CreateSurfaceOverrideFingerprint(first);
|
||||
|
||||
Assert.Equal(
|
||||
expected,
|
||||
CurrentRenderSceneOracle.CreateSurfaceOverrideFingerprint(
|
||||
reordered));
|
||||
Assert.NotEqual(
|
||||
expected,
|
||||
CurrentRenderSceneOracle.CreateSurfaceOverrideFingerprint(
|
||||
changed));
|
||||
Assert.NotEqual(
|
||||
expected,
|
||||
CurrentRenderSceneOracle.CreateSurfaceOverrideFingerprint(null));
|
||||
}
|
||||
|
||||
private static CurrentRenderProjectionFingerprint CaptureSingle(
|
||||
WorldEntity entity,
|
||||
uint landblockId,
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ using System.Numerics;
|
|||
using AcDream.App.Rendering;
|
||||
using AcDream.App.Rendering.Scene;
|
||||
using AcDream.Core.Selection;
|
||||
using AcDream.Core.World;
|
||||
|
||||
namespace AcDream.App.Tests.Rendering;
|
||||
|
||||
|
|
@ -26,6 +27,7 @@ public sealed class RenderFrameProductTests
|
|||
dynamic.Id,
|
||||
0,
|
||||
Matrix4x4.CreateTranslation(1, 2, 3)));
|
||||
writer.AddEntityCandidate(in dynamic, animated: true);
|
||||
writer.AddClassification(new RenderFrameClassificationRecord(
|
||||
outdoor.Id,
|
||||
0,
|
||||
|
|
@ -85,8 +87,16 @@ public sealed class RenderFrameProductTests
|
|||
1),
|
||||
view.RouteRanges[0]);
|
||||
Assert.Equal(
|
||||
new RenderFrameDiagnosticCounts(1, 2, 1, 1, 1, 1, 1, 1, 1),
|
||||
new RenderFrameDiagnosticCounts(
|
||||
1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1),
|
||||
view.DiagnosticCounts);
|
||||
RenderFrameEntityCandidate packed = Assert.Single(
|
||||
view.EntityCandidates.ToArray());
|
||||
Assert.Equal(dynamic.Id, packed.Projection.Id);
|
||||
Assert.True(packed.Animated);
|
||||
RenderFrameMeshPart part = Assert.Single(view.MeshParts.ToArray());
|
||||
Assert.Equal(dynamic.Id, part.ProjectionId);
|
||||
Assert.Equal(0, part.PartIndex);
|
||||
Assert.Equal(digest, view.SourceDigest);
|
||||
|
||||
exchange.Release(in view);
|
||||
|
|
@ -231,6 +241,7 @@ public sealed class RenderFrameProductTests
|
|||
record.Id,
|
||||
0,
|
||||
Matrix4x4.Identity));
|
||||
writer.AddEntityCandidate(in record, animated: false);
|
||||
writer.AddClassification(new RenderFrameClassificationRecord(
|
||||
record.Id,
|
||||
0,
|
||||
|
|
@ -277,6 +288,10 @@ public sealed class RenderFrameProductTests
|
|||
Transform = new RenderTransform(Matrix4x4.Identity),
|
||||
PreviousTransform = new PreviousRenderTransform(Matrix4x4.Identity),
|
||||
Flags = RenderProjectionFlags.Draw,
|
||||
EntityPayload = new RenderEntityPayload(
|
||||
[new MeshRef((uint)value, Matrix4x4.Identity)],
|
||||
PaletteOverride: null,
|
||||
IsBuildingShell: false),
|
||||
};
|
||||
|
||||
private static RetailSelectionMesh SelectionMesh() =>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ using System.Numerics;
|
|||
using AcDream.App.Rendering;
|
||||
using AcDream.App.Rendering.Scene;
|
||||
using AcDream.App.Rendering.Scene.Arch;
|
||||
using AcDream.App.Rendering.Wb;
|
||||
using AcDream.Core.World;
|
||||
|
||||
namespace AcDream.App.Tests.Rendering;
|
||||
|
|
@ -81,6 +82,7 @@ public sealed class RenderScenePViewFrameProductTests
|
|||
[],
|
||||
[Cell],
|
||||
EmptyCellSource.Instance,
|
||||
[],
|
||||
RootIsOutdoor: true);
|
||||
|
||||
builder.Build(exchange, frameSequence: 1, in input);
|
||||
|
|
@ -115,8 +117,12 @@ public sealed class RenderScenePViewFrameProductTests
|
|||
AlphaClassificationCount: 0,
|
||||
LightSetCount: 0,
|
||||
SelectionPartCount: 0,
|
||||
RouteCandidateCount: 5),
|
||||
RouteCandidateCount: 5,
|
||||
EntityCandidateCount: 5,
|
||||
MeshPartCount: 5),
|
||||
view.DiagnosticCounts);
|
||||
Assert.Equal(5, view.EntityCandidates.Length);
|
||||
Assert.Equal(5, view.MeshParts.Length);
|
||||
Assert.Same(portal, view.PortalFrame);
|
||||
Assert.Same(clip, view.ClipAssembly);
|
||||
Assert.Equal(digest, view.SourceDigest);
|
||||
|
|
@ -162,6 +168,22 @@ public sealed class RenderScenePViewFrameProductTests
|
|||
0,
|
||||
[outdoorDynamic, cellDynamic]);
|
||||
oracle.CompletePViewFrame();
|
||||
oracle.BeginDispatcherFrame();
|
||||
oracle.ObserveDispatcherDraw(
|
||||
WbDrawDispatcher.EntitySet.All,
|
||||
entitiesWalked: 1,
|
||||
[(outdoor, 0, Landblock)]);
|
||||
oracle.ObserveDispatcherDraw(
|
||||
WbDrawDispatcher.EntitySet.All,
|
||||
entitiesWalked: 1,
|
||||
[(cellStatic, 0, Landblock)]);
|
||||
oracle.ObserveDispatcherDraw(
|
||||
WbDrawDispatcher.EntitySet.All,
|
||||
entitiesWalked: 2,
|
||||
[
|
||||
(outdoorDynamic, 0, Landblock),
|
||||
(cellDynamic, 0, Landblock),
|
||||
]);
|
||||
|
||||
using var shadow = new RenderSceneShadowRuntime(Generation);
|
||||
foreach (WorldEntity entity in entities)
|
||||
|
|
@ -187,6 +209,8 @@ public sealed class RenderScenePViewFrameProductTests
|
|||
[],
|
||||
[Cell],
|
||||
EmptyCellSource.Instance,
|
||||
[],
|
||||
Landblock,
|
||||
rootIsOutdoor: true);
|
||||
|
||||
RenderFrameProductComparisonSnapshot matched = controller.Snapshot;
|
||||
|
|
@ -198,6 +222,15 @@ public sealed class RenderScenePViewFrameProductTests
|
|||
Assert.Equal(0, matched.MismatchCount);
|
||||
Assert.Null(matched.FirstMismatch);
|
||||
Assert.Equal(matched.ExpectedDigest, matched.ActualDigest);
|
||||
Assert.Equal(1uL, matched.PackedInputComparisonCount);
|
||||
Assert.Equal(1uL, matched.PackedInputSuccessfulComparisonCount);
|
||||
Assert.Equal(4, matched.PackedInputExpectedCount);
|
||||
Assert.Equal(4, matched.PackedInputActualCount);
|
||||
Assert.Equal(0, matched.PackedInputMismatchCount);
|
||||
Assert.Null(matched.PackedInputFirstMismatch);
|
||||
Assert.Equal(
|
||||
matched.PackedInputExpectedDigest,
|
||||
matched.PackedInputActualDigest);
|
||||
Assert.Empty(logs);
|
||||
|
||||
RenderProjectionId withdrawnId =
|
||||
|
|
@ -213,6 +246,8 @@ public sealed class RenderScenePViewFrameProductTests
|
|||
[],
|
||||
[Cell],
|
||||
EmptyCellSource.Instance,
|
||||
[],
|
||||
Landblock,
|
||||
rootIsOutdoor: true);
|
||||
|
||||
RenderFrameProductComparisonSnapshot mismatch = controller.Snapshot;
|
||||
|
|
@ -220,7 +255,11 @@ public sealed class RenderScenePViewFrameProductTests
|
|||
Assert.Equal(1uL, mismatch.SuccessfulComparisonCount);
|
||||
Assert.Equal(1, mismatch.MismatchCount);
|
||||
Assert.Contains("field=count expected=4 actual=3", mismatch.FirstMismatch);
|
||||
Assert.Single(logs);
|
||||
Assert.Equal(1, mismatch.PackedInputMismatchCount);
|
||||
Assert.Contains(
|
||||
"field=count expected=4 actual=3",
|
||||
mismatch.PackedInputFirstMismatch);
|
||||
Assert.Equal(2, logs.Count);
|
||||
}
|
||||
|
||||
private static RenderProjectionRecord Project(WorldEntity entity)
|
||||
|
|
@ -286,7 +325,11 @@ public sealed class RenderScenePViewFrameProductTests
|
|||
BuildingShellAnchorCellId: 0,
|
||||
TransformFingerprint: default,
|
||||
GeometryFingerprint: default,
|
||||
AppearanceFingerprint: default));
|
||||
AppearanceFingerprint: default),
|
||||
new RenderEntityPayload(
|
||||
[new MeshRef((uint)id, Matrix4x4.Identity)],
|
||||
PaletteOverride: null,
|
||||
IsBuildingShell: false));
|
||||
}
|
||||
|
||||
private static WorldEntity Entity(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue