fix(rendering): bound portal resource lifetime
Separate logical ownership, render publication, and GPU retirement across live entities, landblocks, particles, textures, mesh arenas, portal/UI teardown, and per-frame scratch storage. Add bounded DAT/texture caches, upload budgets, three-frame fence retirement, exact-incarnation appearance reconciliation, frame pacing, and extensive lifetime conformance coverage.\n\nThe seven-destination connected route now cuts peak working/private memory roughly in half, returns Caul to 125-153 FPS locally, and produces no WER or AMD reset.\n\nCo-authored-by: OpenAI Codex <codex@openai.com>
This commit is contained in:
parent
3971997689
commit
749e8ceeb1
225 changed files with 29107 additions and 3914 deletions
130
tests/AcDream.App.Tests/Rendering/ClipFrameUploadTests.cs
Normal file
130
tests/AcDream.App.Tests/Rendering/ClipFrameUploadTests.cs
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
using AcDream.App.Rendering;
|
||||
using Xunit;
|
||||
|
||||
namespace AcDream.App.Tests.Rendering;
|
||||
|
||||
public sealed class ClipFrameUploadTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(1, 144)]
|
||||
[InlineData(16, 144)]
|
||||
[InlineData(64, 192)]
|
||||
[InlineData(256, 256)]
|
||||
[InlineData(512, 512)]
|
||||
public void TerrainArena_RecordStride_RespectsDriverAlignment(
|
||||
int alignment,
|
||||
int expectedStride)
|
||||
{
|
||||
Assert.Equal(expectedStride, ClipFrameArenaLayout.RecordStride(alignment));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TerrainArena_AssignsEverySliceAUniqueOrderedRange()
|
||||
{
|
||||
const int stride = 256;
|
||||
Assert.Equal(0, ClipFrameArenaLayout.RecordOffset(0, stride));
|
||||
Assert.Equal(256, ClipFrameArenaLayout.RecordOffset(1, stride));
|
||||
Assert.Equal(512, ClipFrameArenaLayout.RecordOffset(2, stride));
|
||||
Assert.Equal(1280, ClipFrameArenaLayout.RequiredBytes(5, stride));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UploadState_RegionsOnce_AndTerrainRangesInSubmissionOrder()
|
||||
{
|
||||
var state = new ClipFrameUploadState();
|
||||
state.BeginFrame();
|
||||
state.ValidateRegionsNotUploaded();
|
||||
state.MarkRegionsUploaded();
|
||||
Assert.True(state.RegionsUploaded);
|
||||
Assert.Throws<InvalidOperationException>(state.ValidateRegionsNotUploaded);
|
||||
|
||||
state.ValidateTerrainReservation(4);
|
||||
state.CommitTerrainReservation(4);
|
||||
Assert.Equal(new[] { 0, 1, 2, 3 }, new[]
|
||||
{
|
||||
state.NextTerrainRecord(),
|
||||
state.NextTerrainRecord(),
|
||||
state.NextTerrainRecord(),
|
||||
state.NextTerrainRecord(),
|
||||
});
|
||||
Assert.Equal(4, state.TerrainUploaded);
|
||||
Assert.Throws<InvalidOperationException>(() => state.NextTerrainRecord());
|
||||
|
||||
state.BeginFrame();
|
||||
Assert.False(state.RegionsUploaded);
|
||||
Assert.Equal(0, state.TerrainReserved);
|
||||
Assert.Equal(0, state.TerrainUploaded);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ResourceRing_RetainsAtMostOneResourcePerFencedFrameSlot()
|
||||
{
|
||||
var ring = new ClipFrameResourceRing<object>(ClipFrame.FrameSlotCount);
|
||||
for (int slot = 0; slot < ClipFrame.FrameSlotCount; slot++)
|
||||
ring.Set(slot, new object());
|
||||
|
||||
// Pathological slice counts reuse ranges in the frame slot's one arena;
|
||||
// they cannot add another GL object to the ring.
|
||||
for (int slice = 0; slice < 10_000; slice++)
|
||||
Assert.True(ring.TryGet(slice % ClipFrame.FrameSlotCount, out _));
|
||||
|
||||
Assert.Equal(ClipFrame.FrameSlotCount, ring.Count);
|
||||
Assert.Throws<InvalidOperationException>(() => ring.Set(0, new object()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CapacityPolicy_ShrinksOneOffPathologicalPeakAfterHysteresis()
|
||||
{
|
||||
var policy = new ClipBufferCapacityPolicy();
|
||||
int peak = policy.SelectCapacity(0, 1_000_000);
|
||||
Assert.True(peak >= 1_000_000);
|
||||
|
||||
int first = policy.SelectCapacity(peak, 4_096);
|
||||
int second = policy.SelectCapacity(first, 4_096);
|
||||
int third = policy.SelectCapacity(second, 4_096);
|
||||
|
||||
Assert.Equal(peak, first);
|
||||
Assert.Equal(peak, second);
|
||||
Assert.Equal(4_096, third);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CapacityPolicy_OrdinaryDemandJitterCancelsPendingShrink()
|
||||
{
|
||||
var policy = new ClipBufferCapacityPolicy();
|
||||
int capacity = policy.SelectCapacity(0, 65_536);
|
||||
capacity = policy.SelectCapacity(capacity, 4_096);
|
||||
capacity = policy.SelectCapacity(capacity, 20_000); // above 25% utilization
|
||||
capacity = policy.SelectCapacity(capacity, 4_096);
|
||||
capacity = policy.SelectCapacity(capacity, 4_096);
|
||||
|
||||
Assert.Equal(65_536, capacity);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CapacityTransaction_PublishesOnlySuccessfulResize()
|
||||
{
|
||||
int capacity = 4_096;
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
ClipBufferCapacityTransaction.Resize(
|
||||
ref capacity,
|
||||
8_192,
|
||||
(_, _) => throw new InvalidOperationException("BufferData failed")));
|
||||
Assert.Equal(4_096, capacity);
|
||||
|
||||
ClipBufferCapacityTransaction.Resize(
|
||||
ref capacity,
|
||||
8_192,
|
||||
(previous, next) =>
|
||||
{
|
||||
Assert.Equal(4_096, previous);
|
||||
Assert.Equal(8_192, next);
|
||||
});
|
||||
Assert.Equal(8_192, capacity);
|
||||
|
||||
// A later stage failure must not roll accounting back to the old store.
|
||||
Action laterFailure = () => throw new InvalidOperationException("later bind failed");
|
||||
Assert.Throws<InvalidOperationException>(laterFailure);
|
||||
Assert.Equal(8_192, capacity);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue