feat(overhaul): port S5 particle cell visibility
Publish the exact completed walk landscape set as the typed retained particle-view product. Apply retail CLandCell membership versus constant-true non-null CEnvCell eligibility while preserving the x87 distance and AP-116 behavior. Delete the null-root terrain visibility reconstruction and the dead drawable-cell point-light feedback chain. Retire AP-117, correct AP-85 and AD-21, and keep directional shadows, building degrade, AP-232, probes, RHI, shaders, and DAT outside this chunk. Automated return: Release 0 warnings/0 errors; Core VFX 111/111; App particle/frame/renderer/terrain 146/146; warmed production allocation 1/1 at 0 B. First official hermetic artifact s5-c1-hermetic-20260904 is preserved at 16759/16760 with only the stale 162-row assertion; after the bounded 161 correction, exact pin 1/1 and fresh s5-c1-hermetic-corrected-20260904 16760/16760. InstalledDat 385 pass, 10 documented failures, 1 documented skip, no new identity. Mutation 1: making EnvCell eligibility set-dependent first failed ParticleSystemTests.cs:553 Assert.True, expected true actual false. Mutation 2: making outdoor eligibility constant true first failed ParticleSystemTests.cs:559 Assert.False, expected false actual true. Mutation 3: feeding the diagnostic union first failed WorldSceneRendererTests.cs:279 HashSet equality, expected [16842755], actual [16843008, 16842755]. Mutation 4: restoring CollectVisibleCells first failed TerrainParticleCellVisibilityTests.cs:37 and named TerrainModernRenderer.cs. Mutation 5: restoring ObserveDrawableCells first failed TerrainParticleCellVisibilityTests.cs:37 and named WorldRenderFrameBuilder.cs. Mutation 6: changing the inclusive boundary from <= to < first failed ParticleSystemTests.cs:519 Assert.True, expected true actual false. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
efb0756190
commit
94a6b5ef39
18 changed files with 352 additions and 269 deletions
|
|
@ -28,7 +28,7 @@ public sealed class ParticleVisibilityControllerTests
|
|||
|
||||
controller.BeginFrame(Vector3.Zero);
|
||||
controller.UseWorldView();
|
||||
controller.MarkVisibleCells(new HashSet<uint> { 0x01010001u });
|
||||
controller.MarkVisibleLandscapeCells(new HashSet<uint> { 0x01010001u });
|
||||
controller.CompleteFrame();
|
||||
controller.Apply(particles, 1f);
|
||||
|
||||
|
|
@ -84,15 +84,125 @@ public sealed class ParticleVisibilityControllerTests
|
|||
|
||||
controller.BeginFrame(Vector3.Zero);
|
||||
controller.UseWorldView();
|
||||
controller.MarkVisibleCells([0x01010001u]);
|
||||
controller.MarkVisibleLandscapeCells([0x01010001u]);
|
||||
controller.CompleteFrame();
|
||||
|
||||
controller.BeginFrame(new Vector3(1000f, 1000f, 0f));
|
||||
controller.UseWorldView();
|
||||
controller.MarkVisibleCells([0x02020001u]);
|
||||
controller.MarkVisibleLandscapeCells([0x02020001u]);
|
||||
controller.AbortFrame();
|
||||
controller.Apply(particles, 1f);
|
||||
|
||||
Assert.True(Assert.Single(particles.EnumerateEmitters()).ViewEligible);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CompleteAbortAndResetPublishOnlyCompleteLandscapeTransactions()
|
||||
{
|
||||
var particles = new ParticleSystem(new EmitterDescRegistry(), new Random(1));
|
||||
int first = particles.SpawnEmitter(
|
||||
new EmitterDesc
|
||||
{
|
||||
DatId = 0x32000004u,
|
||||
Type = ParticleType.Still,
|
||||
MaxDegradeDistance = 100f,
|
||||
MaxParticles = 1,
|
||||
},
|
||||
Vector3.Zero,
|
||||
attachedObjectId: 43u);
|
||||
int second = particles.SpawnEmitter(
|
||||
new EmitterDesc
|
||||
{
|
||||
DatId = 0x32000005u,
|
||||
Type = ParticleType.Still,
|
||||
MaxDegradeDistance = 100f,
|
||||
MaxParticles = 1,
|
||||
},
|
||||
Vector3.Zero,
|
||||
attachedObjectId: 44u);
|
||||
particles.UpdateEmitterOwnerCell(first, 0x0101_0001u);
|
||||
particles.UpdateEmitterOwnerCell(second, 0x0101_0002u);
|
||||
var controller = new ParticleVisibilityController();
|
||||
|
||||
controller.BeginFrame(Vector3.Zero);
|
||||
controller.UseWorldView();
|
||||
controller.MarkVisibleLandscapeCells([0x0101_0001u]);
|
||||
controller.CompleteFrame();
|
||||
|
||||
controller.BeginFrame(new Vector3(1000f, 0f, 0f));
|
||||
controller.UseWorldView();
|
||||
controller.MarkVisibleLandscapeCells([0x0101_0002u]);
|
||||
controller.AbortFrame();
|
||||
controller.Apply(particles, 1f);
|
||||
Assert.True(particles.EnumerateEmitters().Single(e => e.Handle == first).ViewEligible);
|
||||
Assert.False(particles.EnumerateEmitters().Single(e => e.Handle == second).ViewEligible);
|
||||
|
||||
controller.BeginFrame(Vector3.Zero);
|
||||
controller.UseWorldView();
|
||||
controller.MarkVisibleLandscapeCells([0x0101_0002u]);
|
||||
controller.CompleteFrame();
|
||||
controller.Apply(particles, 1f);
|
||||
Assert.False(particles.EnumerateEmitters().Single(e => e.Handle == first).ViewEligible);
|
||||
Assert.True(particles.EnumerateEmitters().Single(e => e.Handle == second).ViewEligible);
|
||||
|
||||
controller.Reset();
|
||||
controller.Apply(particles, 1f);
|
||||
Assert.All(particles.EnumerateEmitters(), emitter => Assert.False(emitter.ViewEligible));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(0u)]
|
||||
[InlineData(0x0101_0100u)]
|
||||
public void MarkVisibleLandscapeCells_RejectsNonLandscapeIds(uint cellId)
|
||||
{
|
||||
var controller = new ParticleVisibilityController();
|
||||
controller.BeginFrame(Vector3.Zero);
|
||||
controller.UseWorldView();
|
||||
|
||||
ArgumentException error = Assert.Throws<ArgumentException>(
|
||||
() => controller.MarkVisibleLandscapeCells([cellId]));
|
||||
|
||||
Assert.Contains($"0x{cellId:X8}", error.Message, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProductionApply_WarmedParticleViewPathDoesNotAllocate()
|
||||
{
|
||||
var particles = new ParticleSystem(new EmitterDescRegistry(), new Random(1));
|
||||
int outdoor = particles.SpawnEmitter(
|
||||
new EmitterDesc
|
||||
{
|
||||
DatId = 0x32000006u,
|
||||
Type = ParticleType.Still,
|
||||
MaxDegradeDistance = 100f,
|
||||
MaxParticles = 1,
|
||||
},
|
||||
Vector3.Zero,
|
||||
attachedObjectId: 45u);
|
||||
int environment = particles.SpawnEmitter(
|
||||
new EmitterDesc
|
||||
{
|
||||
DatId = 0x32000007u,
|
||||
Type = ParticleType.Still,
|
||||
MaxDegradeDistance = 100f,
|
||||
MaxParticles = 1,
|
||||
},
|
||||
Vector3.Zero,
|
||||
attachedObjectId: 46u);
|
||||
particles.UpdateEmitterOwnerCell(outdoor, 0x0101_0001u);
|
||||
particles.UpdateEmitterOwnerCell(environment, 0x0101_0100u);
|
||||
var controller = new ParticleVisibilityController();
|
||||
controller.BeginFrame(Vector3.Zero);
|
||||
controller.UseWorldView();
|
||||
controller.MarkVisibleLandscapeCells([0x0101_0001u]);
|
||||
controller.CompleteFrame();
|
||||
|
||||
long allocated = ZeroAllocationProbe.MeasureWarmed(
|
||||
() => controller.Apply(particles, 1f),
|
||||
batchSize: 256,
|
||||
warmupBatches: 2,
|
||||
samples: 4);
|
||||
|
||||
Assert.True(allocated == 0, $"Particle view allocated {allocated} bytes.");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue