acdream/tests/AcDream.App.Tests/Rendering/Wb/DirectionalShadowTerrainPreparedDrawTests.cs
Erik a4de2efc4e feat(overhaul): select pack shadows from retail visibility
Borrow the exact prior-completed landscape visibility transaction and S2 CELLARRAY owner for the opt-in IA-24 directional-shadow pack. Select terrain by authored 1..64 cells, ordinary casters by CELLARRAY, and buildings by outdoor EffectCellId with no fallback.

Keep retained caster/material/terrain topology stable across visibility-only frames. Publish exact arbitrary active instance runs and bounded terrain commands through separate selection sequences; preserve transform-journal, fade/retry, deferral, shader/RHI, ordinary world, and pack-off behavior. Amend IA-24 and the S5 ledger.

Pre-commit gates: Release solution build 0 warnings/0 errors; focused visibility/frame/caster/prepared/GPU/terrain/pack lane 137/137; warmed caster/prepared/terrain selectors 0 B; git diff --check clean. Official hermetic and InstalledDat evidence intentionally run post-commit from this exact clean tree.

Mutation evidence (each restored exactly): (1) CELLARRAY->Parent first failed PriorLandscapeSelection expected [201,202,203,205], actual [204,205]. (2) all resident terrain first failed Assert.Single with 3 commands. (3) building EffectCell->anchor first failed expected trailing 205, actual 206. (4) admit missing membership first failed with extra 204. (5) completed->building scratch first failed completed-view Assert.True, expected true/actual false. (6) selection advanced BuildSequence first failed expected 1/actual 2. (7) alternating->prefix first failed active command count expected 3/actual 1.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-09-04 18:20:31 +02:00

123 lines
4.7 KiB
C#

using AcDream.App.Rendering;
using AcDream.App.Rendering.Vfx;
using AcDream.App.Rendering.Wb;
namespace AcDream.App.Tests.Rendering.Wb;
public sealed class DirectionalShadowTerrainPreparedDrawTests
{
[Fact]
public void Product_ContainsEveryResidentRangeWithoutVisibilityClassification()
{
var product = new DirectionalShadowTerrainPreparedDraws();
Assert.True(product.TryBegin(frameSequence: 10, estimatedCommands: 3));
DirectionalShadowTerrainRange[] resident =
[
new(FirstIndex: 0, IndexCount: 384),
new(FirstIndex: 384, IndexCount: 384),
new(FirstIndex: 768, IndexCount: 384),
];
foreach (DirectionalShadowTerrainRange range in resident)
product.Add(in range);
product.Complete(frameSequence: 10);
Assert.Equal(3, product.Commands.Length);
Assert.Equal(0u, product.Commands[0].FirstIndex);
Assert.Equal(384u, product.Commands[1].FirstIndex);
Assert.Equal(768u, product.Commands[2].FirstIndex);
Assert.All(
product.Commands.ToArray(),
static command =>
{
Assert.Equal(384u, command.Count);
Assert.Equal(1u, command.InstanceCount);
Assert.Equal(0, command.BaseVertex);
});
}
[Fact]
public void SameFrame_AllCascadesReuseOneTerrainBuild()
{
var product = new DirectionalShadowTerrainPreparedDraws();
Assert.True(product.TryBegin(frameSequence: 1, estimatedCommands: 1));
var range = new DirectionalShadowTerrainRange(100, 24);
product.Add(in range);
product.Complete(frameSequence: 1);
long retained = product.RetainedScratchBytes;
Assert.False(product.TryBegin(frameSequence: 1, estimatedCommands: 500));
Assert.Equal(1ul, product.BuildSequence);
Assert.Equal(retained, product.RetainedScratchBytes);
Assert.Single(product.Commands.ToArray());
}
[Fact]
public void NextFrame_RebuildsIntoRetainedStorage()
{
var product = new DirectionalShadowTerrainPreparedDraws();
Assert.True(product.TryBegin(frameSequence: 1, estimatedCommands: 2));
var first = new DirectionalShadowTerrainRange(10, 3);
var second = new DirectionalShadowTerrainRange(20, 6);
product.Add(in first);
product.Add(in second);
product.Complete(frameSequence: 1);
long retained = product.RetainedScratchBytes;
Assert.True(product.TryBegin(frameSequence: 2, estimatedCommands: 1));
product.Add(in second);
product.Complete(frameSequence: 2);
Assert.Equal(2ul, product.BuildSequence);
Assert.Equal(retained, product.RetainedScratchBytes);
Assert.Single(product.Commands.ToArray());
Assert.Equal(20u, product.Commands[0].FirstIndex);
}
[Fact]
public void PriorLandscapeSelection_ScansExactAuthoredEightByEightCells()
{
var product = new DirectionalShadowTerrainPreparedDraws();
Assert.True(product.TryBegin(frameSequence: 1, estimatedCommands: 3));
DirectionalShadowTerrainRange[] resident =
[
new(FirstIndex: 0, IndexCount: 384, LandblockId: 0x1111FFFFu),
new(FirstIndex: 384, IndexCount: 384, LandblockId: 0x2222FFFFu),
new(FirstIndex: 768, IndexCount: 384, LandblockId: 0x3333FFFFu),
];
foreach (DirectionalShadowTerrainRange range in resident)
product.Add(in range);
product.Complete(frameSequence: 1);
ulong topologySequence = product.BuildSequence;
var visible = new HashSet<uint>
{
0x11110040u,
0x22220041u, // valid outdoor family, but not this slot's 8x8 cells.
};
var visibility = new RetailLandscapeVisibilityFrame(
visible,
HasCompletedWorldView: true);
product.ApplySelection(in visibility);
DrawElementsIndirectCommand selected = Assert.Single(product.Commands.ToArray());
Assert.Equal(0u, selected.FirstIndex);
Assert.Equal(3, product.ResidentRanges.Length);
Assert.Equal(topologySequence, product.BuildSequence);
var empty = new RetailLandscapeVisibilityFrame(
new HashSet<uint>(),
HasCompletedWorldView: true);
product.ApplySelection(in empty);
Assert.Empty(product.Commands.ToArray());
Assert.Equal(topologySequence, product.BuildSequence);
product.ApplySelection(in visibility);
ZeroAllocationProbe.AssertAllocatesNothing(
"DirectionalShadowTerrainPreparedDraws.ApplySelection",
() => product.ApplySelection(in visibility),
batchSize: 256);
Assert.Equal(topologySequence, product.BuildSequence);
}
}