fix(rendering): normalize empty dispatcher evidence

This commit is contained in:
Erik 2026-07-25 02:17:42 +02:00
parent e0f36caa70
commit f9829d5f9e
2 changed files with 49 additions and 7 deletions

View file

@ -2569,10 +2569,21 @@ public sealed unsafe partial class WbDrawDispatcher : IDisposable
Vector3 cameraWorldPosition,
List<AlphaFingerprint> alphaScratch)
{
int opaqueGroupCount =
visibleInstanceCount == 0 ? 0 : opaque.Count;
int transparentGroupCount =
visibleInstanceCount == 0 ? 0 : transparent.Count;
// The no-VAO production early-out deliberately skips group
// partitioning, so its reusable opaque/transparent lists may still
// contain the preceding draw's entries. No instances were accepted;
// those stale scratch entries are not part of this submission and
// must not leak into its diagnostic identity.
IReadOnlyList<InstanceGroup> acceptedOpaque =
visibleInstanceCount == 0
? Array.Empty<InstanceGroup>()
: opaque;
IReadOnlyList<InstanceGroup> acceptedTransparent =
visibleInstanceCount == 0
? Array.Empty<InstanceGroup>()
: transparent;
int opaqueGroupCount = acceptedOpaque.Count;
int transparentGroupCount = acceptedTransparent.Count;
StableRenderHash128 hash = StableRenderHash128.Create();
hash.Add(visibleInstanceCount);
hash.Add(immediateInstanceCount);
@ -2580,14 +2591,14 @@ public sealed unsafe partial class WbDrawDispatcher : IDisposable
hash.Add(transparentGroupCount);
hash.Add(deferTransparent);
RenderSceneHash128 opaqueDigest =
BuildOpaqueSubmissionDigest(opaque);
BuildOpaqueSubmissionDigest(acceptedOpaque);
RenderSceneHash128 transparentDigest =
BuildTransparentSubmissionDigest(
transparent,
acceptedTransparent,
cameraWorldPosition,
alphaScratch);
RenderSceneHash128 transparentSetDigest =
BuildOpaqueSubmissionDigest(transparent);
BuildOpaqueSubmissionDigest(acceptedTransparent);
hash.Add(opaqueDigest.Low);
hash.Add(opaqueDigest.High);
hash.Add(transparentDigest.Low);

View file

@ -1,4 +1,5 @@
using System.Numerics;
using AcDream.App.Rendering.Scene;
using AcDream.App.Rendering.Wb;
using AcDream.Core.Meshing;
using Xunit;
@ -138,6 +139,36 @@ public class InstanceGroupClearTests
reversedSubmission.TransparentSetDigest);
}
[Fact]
public void DispatcherFingerprint_ZeroVisibleInstancesIgnoresStaleGroupStorage()
{
WbDrawDispatcher.InstanceGroup stale = MakeCompleteGroup(
textureHandle: 0xAA,
submissionOrder: 0);
var scratch = new List<WbDrawDispatcher.AlphaFingerprint>();
CurrentRenderDispatcherSubmission expected =
WbDrawDispatcher.CreateDispatcherSubmission(
visibleInstanceCount: 0,
immediateInstanceCount: 0,
deferTransparent: false,
opaque: [],
transparent: [],
cameraWorldPosition: Vector3.Zero,
alphaScratch: scratch);
CurrentRenderDispatcherSubmission actual =
WbDrawDispatcher.CreateDispatcherSubmission(
visibleInstanceCount: 0,
immediateInstanceCount: 0,
deferTransparent: false,
opaque: [stale],
transparent: [stale],
cameraWorldPosition: Vector3.Zero,
alphaScratch: scratch);
Assert.Equal(expected, actual);
}
[Fact]
public void CachedGroupHandle_RequiresLiveMatchingRegistration()
{