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>
252 lines
8.7 KiB
C#
252 lines
8.7 KiB
C#
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using AcDream.App.Rendering;
|
|
using Xunit;
|
|
|
|
namespace AcDream.App.Tests.Rendering;
|
|
|
|
public sealed class BuildingGroupScratchTests
|
|
{
|
|
[Fact]
|
|
public void Rebuild_DropsHistoricalKeys_BoundsRetention_AndPreservesEncounterOrder()
|
|
{
|
|
var scratch = new BuildingGroupScratch();
|
|
int pathologicalCount = BuildingGroupScratch.MaxRetainedGroups * 4;
|
|
var pathological = new List<LoadedCell>(pathologicalCount);
|
|
for (int i = 0; i < pathologicalCount; i++)
|
|
{
|
|
pathological.Add(new LoadedCell
|
|
{
|
|
CellId = (uint)i + 1u,
|
|
BuildingId = 0x1000_0000u + (uint)i,
|
|
});
|
|
}
|
|
|
|
scratch.Rebuild(pathological);
|
|
Assert.Equal(pathologicalCount, scratch.ActiveGroupCount);
|
|
Assert.True(scratch.MapCapacity > BuildingGroupScratch.MaxRetainedGroups);
|
|
|
|
var firstA = new LoadedCell { CellId = 0xAA01u, BuildingId = 0x20u };
|
|
var second = new LoadedCell { CellId = 0xBB01u, BuildingId = 0x10u };
|
|
var firstB = new LoadedCell { CellId = 0xAA02u, BuildingId = 0x20u };
|
|
var unstamped = new LoadedCell { CellId = 0xCC01u };
|
|
scratch.Rebuild([firstA, second, firstB, unstamped]);
|
|
|
|
Assert.Equal(3, scratch.ActiveGroupCount);
|
|
Assert.Equal(
|
|
new uint[] { 0x20u, 0x10u, unstamped.CellId },
|
|
scratch.Groups.Keys.ToArray());
|
|
Assert.Equal(new[] { firstA, firstB }, scratch.Groups[0x20u]);
|
|
Assert.Equal(new[] { second }, scratch.Groups[0x10u]);
|
|
Assert.Equal(new[] { unstamped }, scratch.Groups[unstamped.CellId]);
|
|
Assert.DoesNotContain(
|
|
scratch.Groups.Keys,
|
|
key => key >= 0x1000_0000u);
|
|
Assert.InRange(
|
|
scratch.RetainedListCount,
|
|
0,
|
|
BuildingGroupScratch.MaxRetainedGroups);
|
|
Assert.InRange(
|
|
scratch.MapCapacity,
|
|
0,
|
|
BuildingGroupScratch.MaxRetainedGroups);
|
|
|
|
scratch.Reset();
|
|
|
|
Assert.Equal(0, scratch.ActiveGroupCount);
|
|
Assert.Empty(scratch.Groups);
|
|
Assert.InRange(
|
|
scratch.RetainedListCount,
|
|
0,
|
|
BuildingGroupScratch.MaxRetainedGroups);
|
|
Assert.InRange(
|
|
scratch.MapCapacity,
|
|
0,
|
|
BuildingGroupScratch.MaxRetainedGroups);
|
|
}
|
|
|
|
[Fact]
|
|
public void Reset_DoesNotRetainPathologicalGroupBackingArray()
|
|
{
|
|
var scratch = new BuildingGroupScratch();
|
|
var oversizedGroup = new List<LoadedCell>(
|
|
BuildingGroupScratch.MaxRetainedCellsPerGroup * 2);
|
|
for (int i = 0;
|
|
i < BuildingGroupScratch.MaxRetainedCellsPerGroup * 2;
|
|
i++)
|
|
{
|
|
oversizedGroup.Add(new LoadedCell
|
|
{
|
|
CellId = (uint)i + 1u,
|
|
BuildingId = 0x42u,
|
|
});
|
|
}
|
|
|
|
scratch.Rebuild(oversizedGroup);
|
|
Assert.Single(scratch.Groups);
|
|
Assert.True(
|
|
scratch.Groups[0x42u].Capacity
|
|
> BuildingGroupScratch.MaxRetainedCellsPerGroup);
|
|
|
|
scratch.Reset();
|
|
|
|
Assert.Equal(0, scratch.RetainedListCount);
|
|
Assert.Empty(scratch.Groups);
|
|
}
|
|
}
|
|
|
|
public sealed class RetailPViewScratchRetentionTests
|
|
{
|
|
[Fact]
|
|
public void ClearFrameBuffers_DropsPathologicalHighWater_AfterIdleHysteresis()
|
|
{
|
|
var retention = new RetailPViewScratchRetention();
|
|
int pathologicalCellCount =
|
|
RetailPViewScratchRetention.MaxRetainedCellItems * 4;
|
|
int pathologicalFrameCount =
|
|
RetailPViewScratchRetention.MaxRetainedLookInFrames * 4;
|
|
var lookInFrames = new List<PortalVisibilityFrame>(pathologicalFrameCount);
|
|
var lookInPrepare = new HashSet<uint>();
|
|
var drawableCells = new HashSet<uint>();
|
|
var shellBatch = new HashSet<uint>();
|
|
var orderedTransparent = new List<uint>(pathologicalCellCount);
|
|
|
|
for (int i = 0; i < pathologicalFrameCount; i++)
|
|
lookInFrames.Add(new PortalVisibilityFrame());
|
|
for (int i = 0; i < pathologicalCellCount; i++)
|
|
{
|
|
uint id = (uint)i;
|
|
lookInPrepare.Add(id);
|
|
drawableCells.Add(id);
|
|
shellBatch.Add(id);
|
|
orderedTransparent.Add(id);
|
|
}
|
|
|
|
Assert.True(
|
|
lookInFrames.Capacity
|
|
> RetailPViewScratchRetention.MaxRetainedLookInFrames);
|
|
Assert.True(
|
|
drawableCells.EnsureCapacity(0)
|
|
> RetailPViewScratchRetention.MaxRetainedCellItems);
|
|
|
|
retention.ClearFrameBuffers(
|
|
lookInFrames,
|
|
lookInPrepare,
|
|
drawableCells,
|
|
shellBatch,
|
|
orderedTransparent);
|
|
|
|
Assert.Empty(lookInFrames);
|
|
Assert.Empty(lookInPrepare);
|
|
Assert.Empty(drawableCells);
|
|
Assert.Empty(shellBatch);
|
|
Assert.Empty(orderedTransparent);
|
|
Assert.True(
|
|
lookInFrames.Capacity
|
|
> RetailPViewScratchRetention.MaxRetainedLookInFrames);
|
|
|
|
for (int i = 0; i < RetailPViewScratchRetention.CapacityTrimIdleFrames; i++)
|
|
{
|
|
retention.ClearFrameBuffers(
|
|
lookInFrames,
|
|
lookInPrepare,
|
|
drawableCells,
|
|
shellBatch,
|
|
orderedTransparent);
|
|
}
|
|
|
|
Assert.InRange(
|
|
lookInFrames.Capacity,
|
|
0,
|
|
RetailPViewScratchRetention.MaxRetainedLookInFrames);
|
|
Assert.InRange(
|
|
lookInPrepare.EnsureCapacity(0),
|
|
0,
|
|
RetailPViewScratchRetention.MaxRetainedCellItems);
|
|
Assert.InRange(
|
|
drawableCells.EnsureCapacity(0),
|
|
0,
|
|
RetailPViewScratchRetention.MaxRetainedCellItems);
|
|
Assert.InRange(
|
|
shellBatch.EnsureCapacity(0),
|
|
0,
|
|
RetailPViewScratchRetention.MaxRetainedCellItems);
|
|
Assert.InRange(
|
|
orderedTransparent.Capacity,
|
|
0,
|
|
RetailPViewScratchRetention.MaxRetainedCellItems);
|
|
}
|
|
|
|
[Fact]
|
|
public void ClearFrameBuffers_PreservesNormalWarmCapacity()
|
|
{
|
|
var retention = new RetailPViewScratchRetention();
|
|
var lookInFrames = new List<PortalVisibilityFrame>(8);
|
|
var lookInPrepare = new HashSet<uint>();
|
|
var drawableCells = new HashSet<uint>();
|
|
var shellBatch = new HashSet<uint>();
|
|
var orderedTransparent = new List<uint>(64);
|
|
for (uint id = 0; id < 64; id++)
|
|
{
|
|
lookInPrepare.Add(id);
|
|
drawableCells.Add(id);
|
|
shellBatch.Add(id);
|
|
orderedTransparent.Add(id);
|
|
}
|
|
int lookInCapacity = lookInFrames.Capacity;
|
|
int prepareCapacity = lookInPrepare.EnsureCapacity(0);
|
|
int drawableCapacity = drawableCells.EnsureCapacity(0);
|
|
int shellCapacity = shellBatch.EnsureCapacity(0);
|
|
int transparentCapacity = orderedTransparent.Capacity;
|
|
|
|
retention.ClearFrameBuffers(
|
|
lookInFrames,
|
|
lookInPrepare,
|
|
drawableCells,
|
|
shellBatch,
|
|
orderedTransparent);
|
|
|
|
Assert.Equal(lookInCapacity, lookInFrames.Capacity);
|
|
Assert.Equal(prepareCapacity, lookInPrepare.EnsureCapacity(0));
|
|
Assert.Equal(drawableCapacity, drawableCells.EnsureCapacity(0));
|
|
Assert.Equal(shellCapacity, shellBatch.EnsureCapacity(0));
|
|
Assert.Equal(transparentCapacity, orderedTransparent.Capacity);
|
|
}
|
|
|
|
[Fact]
|
|
public void ClearFrameBuffers_RecurringLargeWorkingSet_PreservesWarmCapacity()
|
|
{
|
|
const int recurringCount =
|
|
RetailPViewScratchRetention.MaxRetainedCellItems + 163;
|
|
var retention = new RetailPViewScratchRetention();
|
|
var lookInFrames = new List<PortalVisibilityFrame>();
|
|
var lookInPrepare = new HashSet<uint>();
|
|
var drawableCells = new HashSet<uint>();
|
|
var shellBatch = new HashSet<uint>();
|
|
var orderedTransparent = new List<uint>();
|
|
|
|
for (int iteration = 0;
|
|
iteration < RetailPViewScratchRetention.CapacityTrimIdleFrames + 5;
|
|
iteration++)
|
|
{
|
|
for (int i = 0; i < recurringCount; i++)
|
|
{
|
|
uint id = (uint)i;
|
|
drawableCells.Add(id);
|
|
orderedTransparent.Add(id);
|
|
}
|
|
|
|
int drawableCapacity = drawableCells.EnsureCapacity(0);
|
|
int transparentCapacity = orderedTransparent.Capacity;
|
|
retention.ClearFrameBuffers(
|
|
lookInFrames,
|
|
lookInPrepare,
|
|
drawableCells,
|
|
shellBatch,
|
|
orderedTransparent);
|
|
|
|
Assert.Equal(drawableCapacity, drawableCells.EnsureCapacity(0));
|
|
Assert.Equal(transparentCapacity, orderedTransparent.Capacity);
|
|
}
|
|
}
|
|
}
|