refactor(render): delete superseded alpha sidecars
Remove the dead classic-group CachedBatch/InstanceGroup sort-center sidecar and its cache, append, reset, and diagnostic-digest plumbing. Remove the discarded camera parameter chain from grouped alpha deferral and dispatcher submission diagnostics while preserving walk/particle CYpt keys, FIFO submission ordinals, and opaque camera distance. Add production-facing reflection/source pins for the deleted shapes and camera chain, retained per-cell and opaque owners, the exact three AlphaFlushCounts reasons, and deleted alpha-order symbols. Update directly affected cache/digest/group lifecycle tests and record the complete section 22 result. Gates: Release 0W/0E; focused App 132/132 plus Core 29/29; new pins 4/4; real allocation pins 2/2 at 0 B; shaders 32/32; hermetic 16755/16755; InstalledDat exactly 385 pass, 10 documented fail, 1 skip; diff-check clean. Mutations: InstanceGroup and CachedBatch sidecars fail their Assert.Null pins; Defer and digest camera parameters fail method-shape pins; false count prose fails the exact-reason pin; RetailAlphaOrdering resurrection fails the deletion pin. Each was restored independently before the final matrix. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
a0523e6057
commit
26e97ba412
7 changed files with 224 additions and 105 deletions
|
|
@ -345,6 +345,54 @@ public sealed class WalkStaticStreamPopulatorTests
|
|||
Assert.Contains("0x005A06B7..0x005A0720", register, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ClassicGroupedAlphaSourceTruth_DeletesDeadOrderingChainAndPreservesLiveOwners()
|
||||
{
|
||||
string root = FindRepoRoot();
|
||||
string dispatcher = File.ReadAllText(Path.Combine(
|
||||
root, "src", "AcDream.App", "Rendering", "Wb", "WbDrawDispatcher.cs"));
|
||||
string cachedBatch = File.ReadAllText(Path.Combine(
|
||||
root, "src", "AcDream.App", "Rendering", "Wb", "CachedBatch.cs"));
|
||||
string walkClassifier = File.ReadAllText(Path.Combine(
|
||||
root, "src", "AcDream.App", "Rendering", "Wb", "WbDrawDispatcher.WalkClassify.cs"));
|
||||
string alphaProduction = dispatcher + cachedBatch + walkClassifier;
|
||||
|
||||
Assert.Contains(
|
||||
"Vector3.DistanceSquared(cameraWorldPosition, groupPosition)",
|
||||
dispatcher,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains("group.SortDistance =", dispatcher, StringComparison.Ordinal);
|
||||
Assert.Contains("Vector3 LocalSortCenter", walkClassifier, StringComparison.Ordinal);
|
||||
Assert.Contains("float SortDistanceSq", walkClassifier, StringComparison.Ordinal);
|
||||
Assert.DoesNotContain("RetailAlphaOrdering", alphaProduction, StringComparison.Ordinal);
|
||||
Assert.DoesNotContain("FlushFartherThan(", alphaProduction, StringComparison.Ordinal);
|
||||
Assert.DoesNotContain("viewerDistance", alphaProduction, StringComparison.Ordinal);
|
||||
Assert.DoesNotContain("_ = cameraWorldPosition", dispatcher, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AlphaFlushCountKnownFailure_StatesOnlyTheThreeExactReasons()
|
||||
{
|
||||
string root = FindRepoRoot();
|
||||
string alphaTranscript = File.ReadAllText(Path.Combine(
|
||||
root,
|
||||
"tests",
|
||||
"AcDream.App.Tests",
|
||||
"Rendering",
|
||||
"Walk",
|
||||
"WalkTraceConformanceTests.AlphaDepthTranscript.cs"));
|
||||
|
||||
Assert.Contains("THREE independent reasons", alphaTranscript, StringComparison.Ordinal);
|
||||
Assert.Contains("GfxObj/particle mesh content at all", alphaTranscript, StringComparison.Ordinal);
|
||||
Assert.Contains("AP-238 coalesces transparent", alphaTranscript, StringComparison.Ordinal);
|
||||
Assert.Contains("one token per <c>(cell,list)</c>", alphaTranscript, StringComparison.Ordinal);
|
||||
Assert.Contains("AP-239/AP-240 change", alphaTranscript, StringComparison.Ordinal);
|
||||
Assert.Contains(
|
||||
"former broad \"per instance versus per subset\" explanation was false.",
|
||||
alphaTranscript,
|
||||
StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
private static string FindRepoRoot()
|
||||
{
|
||||
string? directory = AppContext.BaseDirectory;
|
||||
|
|
@ -907,7 +955,7 @@ public sealed class WalkStaticStreamPopulatorTests
|
|||
"DeferTransparentGroups",
|
||||
BindingFlags.Instance | BindingFlags.NonPublic)!;
|
||||
|
||||
defer.Invoke(fx.Dispatcher, [Vector3.Zero, Matrix4x4.Identity]);
|
||||
defer.Invoke(fx.Dispatcher, [Matrix4x4.Identity]);
|
||||
|
||||
Assert.Equal(0, fx.AlphaQueue!.PendingCount);
|
||||
Assert.Contains(
|
||||
|
|
@ -947,7 +995,6 @@ public sealed class WalkStaticStreamPopulatorTests
|
|||
Translucency = TranslucencyKind.AlphaBlend,
|
||||
};
|
||||
group.Matrices.Add(Matrix4x4.Identity);
|
||||
group.LocalSortCenters.Add(Vector3.Zero);
|
||||
group.SubmissionOrders.Add(0);
|
||||
group.Slots.Add(0);
|
||||
group.LightSets.Add(WbDrawDispatcher.InstanceLightSet.Disabled);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using System.Numerics;
|
||||
using System.Reflection;
|
||||
using AcDream.App.Rendering.Scene;
|
||||
using AcDream.App.Rendering.Wb;
|
||||
using AcDream.Core.Meshing;
|
||||
|
|
@ -104,7 +105,6 @@ public class InstanceGroupClearTests
|
|||
deferTransparent: true,
|
||||
opaque: [],
|
||||
transparent: [first, second],
|
||||
cameraWorldPosition: Vector3.Zero,
|
||||
alphaScratch: scratch);
|
||||
var reversedMaterialGroups =
|
||||
WbDrawDispatcher.CreateDispatcherSubmission(
|
||||
|
|
@ -113,7 +113,6 @@ public class InstanceGroupClearTests
|
|||
deferTransparent: true,
|
||||
opaque: [],
|
||||
transparent: [second, first],
|
||||
cameraWorldPosition: Vector3.Zero,
|
||||
alphaScratch: scratch);
|
||||
|
||||
Assert.Equal(
|
||||
|
|
@ -128,7 +127,6 @@ public class InstanceGroupClearTests
|
|||
deferTransparent: true,
|
||||
opaque: [],
|
||||
transparent: [first, second],
|
||||
cameraWorldPosition: Vector3.Zero,
|
||||
alphaScratch: scratch);
|
||||
|
||||
Assert.NotEqual(
|
||||
|
|
@ -154,7 +152,6 @@ public class InstanceGroupClearTests
|
|||
deferTransparent: false,
|
||||
opaque: [],
|
||||
transparent: [],
|
||||
cameraWorldPosition: Vector3.Zero,
|
||||
alphaScratch: scratch);
|
||||
CurrentRenderDispatcherSubmission actual =
|
||||
WbDrawDispatcher.CreateDispatcherSubmission(
|
||||
|
|
@ -163,7 +160,6 @@ public class InstanceGroupClearTests
|
|||
deferTransparent: false,
|
||||
opaque: [stale],
|
||||
transparent: [stale],
|
||||
cameraWorldPosition: Vector3.Zero,
|
||||
alphaScratch: scratch);
|
||||
|
||||
Assert.Equal(expected, actual);
|
||||
|
|
@ -188,7 +184,6 @@ public class InstanceGroupClearTests
|
|||
deferTransparent: true,
|
||||
opaque: [],
|
||||
transparent: [ordinary],
|
||||
cameraWorldPosition: Vector3.Zero,
|
||||
alphaScratch: scratch);
|
||||
CurrentRenderDispatcherSubmission buildingSubmission =
|
||||
WbDrawDispatcher.CreateDispatcherSubmission(
|
||||
|
|
@ -197,7 +192,6 @@ public class InstanceGroupClearTests
|
|||
deferTransparent: true,
|
||||
opaque: [],
|
||||
transparent: [building],
|
||||
cameraWorldPosition: Vector3.Zero,
|
||||
alphaScratch: scratch);
|
||||
|
||||
Assert.NotEqual(
|
||||
|
|
@ -208,6 +202,63 @@ public class InstanceGroupClearTests
|
|||
buildingSubmission.TransparentSetDigest);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ClassicGroupedShapes_DeleteDeadSortCenterSidecarsButRetainWalkCyptKey()
|
||||
{
|
||||
Assert.Null(typeof(CachedBatch).GetProperty("LocalSortCenter"));
|
||||
Assert.Null(typeof(WbDrawDispatcher.InstanceGroup).GetField("LocalSortCenters"));
|
||||
|
||||
Type walkBatch = typeof(WbDrawDispatcher).GetNestedType(
|
||||
"WalkClassifiedBatch",
|
||||
BindingFlags.NonPublic)
|
||||
?? throw new InvalidOperationException("WalkClassifiedBatch was not found.");
|
||||
Assert.Equal(typeof(Vector3), walkBatch.GetProperty("LocalSortCenter")?.PropertyType);
|
||||
Assert.Equal(typeof(float), walkBatch.GetProperty("SortDistanceSq")?.PropertyType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AlphaSubmissionShapes_DeleteDeadCameraChainButRetainOpaqueCameraDistance()
|
||||
{
|
||||
Type dispatcher = typeof(WbDrawDispatcher);
|
||||
MethodInfo defer = dispatcher.GetMethod(
|
||||
"DeferTransparentGroups",
|
||||
BindingFlags.Instance | BindingFlags.NonPublic)
|
||||
?? throw new InvalidOperationException("DeferTransparentGroups was not found.");
|
||||
MethodInfo transparentDigest = dispatcher.GetMethod(
|
||||
"BuildTransparentSubmissionDigest",
|
||||
BindingFlags.Static | BindingFlags.NonPublic)
|
||||
?? throw new InvalidOperationException("BuildTransparentSubmissionDigest was not found.");
|
||||
MethodInfo createSubmission = dispatcher.GetMethod(
|
||||
"CreateDispatcherSubmission",
|
||||
BindingFlags.Static | BindingFlags.NonPublic)
|
||||
?? throw new InvalidOperationException("CreateDispatcherSubmission was not found.");
|
||||
MethodInfo observeCurrent = dispatcher.GetMethod(
|
||||
"ObserveCurrentDispatcherSubmission",
|
||||
BindingFlags.Instance | BindingFlags.NonPublic)
|
||||
?? throw new InvalidOperationException("ObserveCurrentDispatcherSubmission was not found.");
|
||||
MethodInfo observeClassified = dispatcher.GetMethod(
|
||||
"ObserveClassifiedDispatcherSubmission",
|
||||
BindingFlags.Instance | BindingFlags.NonPublic)
|
||||
?? throw new InvalidOperationException("ObserveClassifiedDispatcherSubmission was not found.");
|
||||
|
||||
Assert.Equal([typeof(Matrix4x4)], defer.GetParameters().Select(static p => p.ParameterType));
|
||||
Assert.DoesNotContain(transparentDigest.GetParameters(), static p => p.ParameterType == typeof(Vector3));
|
||||
Assert.DoesNotContain(createSubmission.GetParameters(), static p => p.ParameterType == typeof(Vector3));
|
||||
Assert.DoesNotContain(observeCurrent.GetParameters(), static p => p.ParameterType == typeof(Vector3));
|
||||
Assert.DoesNotContain(observeClassified.GetParameters(), static p => p.ParameterType == typeof(Vector3));
|
||||
|
||||
MethodInfo partition = dispatcher.GetMethod(
|
||||
"PartitionInstanceGroups",
|
||||
BindingFlags.Static | BindingFlags.NonPublic)
|
||||
?? throw new InvalidOperationException("PartitionInstanceGroups was not found.");
|
||||
Assert.Contains(
|
||||
partition.GetParameters(),
|
||||
static p => p.Name == "cameraWorldPosition" && p.ParameterType == typeof(Vector3));
|
||||
Assert.Equal(
|
||||
typeof(float),
|
||||
typeof(WbDrawDispatcher.InstanceGroup).GetField("SortDistance")?.FieldType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CachedGroupHandle_RequiresLiveMatchingRegistration()
|
||||
{
|
||||
|
|
@ -392,7 +443,6 @@ public class InstanceGroupClearTests
|
|||
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);
|
||||
|
|
@ -404,9 +454,9 @@ public class InstanceGroupClearTests
|
|||
}
|
||||
|
||||
// #193 (regression from #188, 2026-07-09): WbDrawDispatcher's InstanceGroup holds
|
||||
// nine per-instance parallel lists — Matrices, LocalSortCenters,
|
||||
// SubmissionOrders, Slots, LightSets, IndoorFlags, Opacities, and
|
||||
// DetailCategories, SelectionLighting — appended in lockstep
|
||||
// eight per-instance parallel lists — Matrices, SubmissionOrders, Slots,
|
||||
// LightSets, IndoorFlags, Opacities, DetailCategories, 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
|
||||
|
|
@ -418,7 +468,6 @@ 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);
|
||||
|
|
@ -430,7 +479,6 @@ public class InstanceGroupClearTests
|
|||
grp.ClearPerInstanceData();
|
||||
|
||||
Assert.Empty(grp.Matrices);
|
||||
Assert.Empty(grp.LocalSortCenters);
|
||||
Assert.Empty(grp.SubmissionOrders);
|
||||
Assert.Empty(grp.Slots);
|
||||
Assert.Empty(grp.LightSets);
|
||||
|
|
|
|||
|
|
@ -417,8 +417,7 @@ public sealed class WbDrawDispatcherBucketingTests
|
|||
uint firstIndex,
|
||||
int indexCount,
|
||||
uint texSlot,
|
||||
Matrix4x4? restPose = null,
|
||||
Vector3? localSortCenter = null)
|
||||
Matrix4x4? restPose = null)
|
||||
{
|
||||
var key = new GroupKey(
|
||||
FirstIndex: firstIndex,
|
||||
|
|
@ -431,8 +430,7 @@ public sealed class WbDrawDispatcherBucketingTests
|
|||
return new CachedBatch(
|
||||
key,
|
||||
new AcDream.App.Rendering.Gpu.GpuTextureSlot(texSlot),
|
||||
restPose ?? Matrix4x4.Identity,
|
||||
localSortCenter ?? Vector3.Zero);
|
||||
restPose ?? Matrix4x4.Identity);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -488,8 +486,7 @@ public sealed class WbDrawDispatcherBucketingTests
|
|||
// Production code: this is the !isAnimated && _cache.TryGet branch
|
||||
// at the top of the per-entity loop body in Draw.
|
||||
var groups = new Dictionary<GroupKey, List<Matrix4x4>>();
|
||||
var sortCenters = new List<Vector3>();
|
||||
void AppendInstance(GroupKey k, Matrix4x4 m, Vector3 localSortCenter)
|
||||
void AppendInstance(GroupKey k, Matrix4x4 m)
|
||||
{
|
||||
if (!groups.TryGetValue(k, out var list))
|
||||
{
|
||||
|
|
@ -497,7 +494,6 @@ public sealed class WbDrawDispatcherBucketingTests
|
|||
groups[k] = list;
|
||||
}
|
||||
list.Add(m);
|
||||
sortCenters.Add(localSortCenter);
|
||||
}
|
||||
|
||||
Assert.True(cache.TryGet(EntityId, LandblockId, out var entryHit));
|
||||
|
|
@ -519,35 +515,6 @@ public sealed class WbDrawDispatcherBucketingTests
|
|||
// appended matrix must equal entityWorld.
|
||||
foreach (var (_, list) in groups)
|
||||
Assert.Equal(entityWorld, list[0]);
|
||||
Assert.All(sortCenters, center => Assert.Equal(Vector3.Zero, center));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ApplyCacheHit_PreservesAuthoredSortCenter()
|
||||
{
|
||||
Vector3 authoredCenter = new(1.25f, -2.5f, 7.75f);
|
||||
var entry = new EntityCacheEntry
|
||||
{
|
||||
EntityId = 100,
|
||||
LandblockHint = 0xA9B40000u,
|
||||
Batches =
|
||||
[
|
||||
MakeCachedBatch(
|
||||
ibo: 1,
|
||||
firstIndex: 0,
|
||||
indexCount: 6,
|
||||
texSlot: 0xAA,
|
||||
localSortCenter: authoredCenter),
|
||||
],
|
||||
};
|
||||
Vector3 observedCenter = default;
|
||||
|
||||
WbDrawDispatcher.ApplyCacheHit(
|
||||
entry,
|
||||
Matrix4x4.Identity,
|
||||
(_, _, center) => observedCenter = center);
|
||||
|
||||
Assert.Equal(authoredCenter, observedCenter);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -788,7 +755,7 @@ public sealed class WbDrawDispatcherBucketingTests
|
|||
const uint EntityId = 100;
|
||||
const int MeshRefCount = 3;
|
||||
|
||||
void AppendInstance(GroupKey k, Matrix4x4 m, Vector3 localSortCenter)
|
||||
void AppendInstance(GroupKey k, Matrix4x4 m)
|
||||
{
|
||||
if (!groups.TryGetValue(k, out var list))
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue