fix(streaming): retire stale portal-region entities
Port retail's 25-second leave-visibility lifetime over canonical live records, retaining spatially resident and owned entities while using the conservative ACE visibility envelope for nonresident records. Route expiry through the normal generation-safe F747 teardown so animations, effects, physics, and render owners unwind symmetrically. Replace the append-only modern mesh buffer with coalescing vertex/index ranges and upload each mesh's vertices once instead of once per material. Released zero-reference meshes can now reuse GPU ranges after portal and cache churn. A connected five-region round trip returned animation ownership to baseline, recreated the starting region on revisit, and held normal FPS. Release build succeeds and all 5,927 tests pass with five intentional skips. Co-authored-by: OpenAI Codex <codex@openai.com>
This commit is contained in:
parent
2cbf34a668
commit
3971997689
13 changed files with 918 additions and 117 deletions
|
|
@ -0,0 +1,84 @@
|
|||
using AcDream.App.Rendering.Wb;
|
||||
|
||||
namespace AcDream.App.Tests.Rendering.Wb;
|
||||
|
||||
public sealed class ContiguousRangeAllocatorTests
|
||||
{
|
||||
[Fact]
|
||||
public void ReleasedRangesAreReusedWithoutGrowing()
|
||||
{
|
||||
var allocator = new ContiguousRangeAllocator(100);
|
||||
|
||||
Assert.True(allocator.TryAllocate(30, out MeshBufferRange first));
|
||||
Assert.True(allocator.TryAllocate(20, out MeshBufferRange second));
|
||||
allocator.Release(first);
|
||||
|
||||
Assert.True(allocator.TryAllocate(25, out MeshBufferRange reused));
|
||||
Assert.Equal(0, reused.Offset);
|
||||
Assert.Equal(25, reused.Length);
|
||||
Assert.Equal(45, allocator.Used);
|
||||
Assert.Equal(100, allocator.Capacity);
|
||||
Assert.Equal(50, allocator.LargestFreeRange);
|
||||
Assert.Equal(30, second.Offset);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AdjacentReleasedRangesCoalesceInEitherOrder()
|
||||
{
|
||||
var allocator = new ContiguousRangeAllocator(100);
|
||||
Assert.True(allocator.TryAllocate(20, out MeshBufferRange first));
|
||||
Assert.True(allocator.TryAllocate(30, out MeshBufferRange second));
|
||||
Assert.True(allocator.TryAllocate(10, out MeshBufferRange third));
|
||||
|
||||
allocator.Release(second);
|
||||
allocator.Release(first);
|
||||
allocator.Release(third);
|
||||
|
||||
Assert.Equal(0, allocator.Used);
|
||||
Assert.Equal(100, allocator.LargestFreeRange);
|
||||
Assert.True(allocator.TryAllocate(100, out MeshBufferRange whole));
|
||||
Assert.Equal(new MeshBufferRange(0, 100), whole);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GrowthJoinsTheTrailingFreeRange()
|
||||
{
|
||||
var allocator = new ContiguousRangeAllocator(64);
|
||||
Assert.True(allocator.TryAllocate(48, out _));
|
||||
|
||||
allocator.Grow(128);
|
||||
|
||||
Assert.Equal(80, allocator.LargestFreeRange);
|
||||
Assert.True(allocator.TryAllocate(72, out MeshBufferRange allocation));
|
||||
Assert.Equal(48, allocation.Offset);
|
||||
Assert.Equal(120, allocator.HighWaterMark);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DoubleReleaseIsRejectedBeforeAccountingChanges()
|
||||
{
|
||||
var allocator = new ContiguousRangeAllocator(32);
|
||||
Assert.True(allocator.TryAllocate(8, out MeshBufferRange allocation));
|
||||
allocator.Release(allocation);
|
||||
|
||||
Assert.Throws<InvalidOperationException>(() => allocator.Release(allocation));
|
||||
Assert.Equal(0, allocator.Used);
|
||||
Assert.Equal(32, allocator.LargestFreeRange);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BestFitPreservesTheLargerHole()
|
||||
{
|
||||
var allocator = new ContiguousRangeAllocator(100);
|
||||
Assert.True(allocator.TryAllocate(20, out MeshBufferRange small));
|
||||
Assert.True(allocator.TryAllocate(10, out _));
|
||||
Assert.True(allocator.TryAllocate(40, out MeshBufferRange large));
|
||||
Assert.True(allocator.TryAllocate(30, out _));
|
||||
allocator.Release(small);
|
||||
allocator.Release(large);
|
||||
|
||||
Assert.True(allocator.TryAllocate(18, out MeshBufferRange selected));
|
||||
Assert.Equal(small.Offset, selected.Offset);
|
||||
Assert.Equal(40, allocator.LargestFreeRange);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue