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
|
|
@ -1,5 +1,6 @@
|
|||
using DatReaderWriter;
|
||||
using DatReaderWriter.DBObjs;
|
||||
using AcDream.Core.Content;
|
||||
using DatReaderWriter.Types;
|
||||
using AcDream.Core.Physics;
|
||||
|
||||
|
|
@ -15,7 +16,7 @@ public static class LandblockLoader
|
|||
/// Load a single landblock (heightmap + static objects) from the dats.
|
||||
/// </summary>
|
||||
/// <returns>Null if the landblock is missing from the cell dat.</returns>
|
||||
public static LoadedLandblock? Load(DatCollection dats, uint landblockId)
|
||||
public static LoadedLandblock? Load(IDatObjectSource dats, uint landblockId)
|
||||
{
|
||||
var block = dats.Get<LandBlock>(landblockId);
|
||||
if (block is null)
|
||||
|
|
@ -40,7 +41,7 @@ public static class LandblockLoader
|
|||
var result = new List<WorldEntity>(info.Objects.Count + info.Buildings.Count);
|
||||
|
||||
// When landblockId is non-zero, namespace stab Ids globally:
|
||||
// 0xC0XXYY00 + n, where XX = lbX byte, YY = lbY byte
|
||||
// 0xCXXYYIII, where XX = lbX, YY = lbY, III = 12-bit counter
|
||||
// distinct from the 0x8XXYYIII scenery and 0x4XXYYIII interior
|
||||
// namespaces in GameWindow.cs. The 0xC0 top byte distinguishes stabs.
|
||||
//
|
||||
|
|
@ -48,20 +49,21 @@ public static class LandblockLoader
|
|||
// legacy starting-from-1 monotonic Ids — compatible with their assertions
|
||||
// which check uniqueness within a single landblock.
|
||||
//
|
||||
// The low byte reserves 0 for the namespace base and 1..255 for
|
||||
// entities. Never wrap into the Y byte: a collision here would corrupt
|
||||
// every renderer/physics/effect table keyed by WorldEntity.Id.
|
||||
uint stabIdBase = landblockId == 0
|
||||
? 0u
|
||||
: 0xC0000000u | ((landblockId >> 24) & 0xFFu) << 16 | ((landblockId >> 16) & 0xFFu) << 8;
|
||||
uint nextId = stabIdBase == 0 ? 1u : stabIdBase + 1u;
|
||||
// The 12-bit allocator fails before crossing into the adjacent
|
||||
// landblock's Y range; no wrapped id can corrupt renderer, physics, or
|
||||
// effect tables keyed by WorldEntity.Id.
|
||||
uint landblockX = (landblockId >> 24) & 0xFFu;
|
||||
uint landblockY = (landblockId >> 16) & 0xFFu;
|
||||
uint nextId = landblockId == 0 ? 1u : 0u;
|
||||
|
||||
uint AllocateId()
|
||||
{
|
||||
if (stabIdBase != 0 && nextId > stabIdBase + 0xFFu)
|
||||
throw new InvalidDataException(
|
||||
$"Landblock 0x{landblockId:X8} exceeds the 255-entry static stab id namespace.");
|
||||
return nextId++;
|
||||
if (landblockId == 0)
|
||||
return nextId++;
|
||||
return LandblockStaticEntityIdAllocator.Allocate(
|
||||
landblockX,
|
||||
landblockY,
|
||||
ref nextId);
|
||||
}
|
||||
|
||||
foreach (var stab in info.Objects)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue