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
|
|
@ -8,6 +8,7 @@ using AcDream.Core.Physics;
|
|||
using AcDream.Core.Physics.Motion;
|
||||
using AcDream.Core.World;
|
||||
using DatReaderWriter;
|
||||
using AcDream.Content;
|
||||
using DatReaderWriter.DBObjs;
|
||||
using DatReaderWriter.Types;
|
||||
using Silk.NET.OpenGL;
|
||||
|
|
@ -44,7 +45,6 @@ public sealed class PortalTunnelPresentation : IDisposable
|
|||
private readonly GL _gl;
|
||||
private readonly WbDrawDispatcher _dispatcher;
|
||||
private readonly SceneLightingUboBinding _lightUbo;
|
||||
private readonly IWbMeshAdapter _meshAdapter;
|
||||
private readonly Setup _setup;
|
||||
private readonly uint _setupDid;
|
||||
private readonly uint _animationDid;
|
||||
|
|
@ -54,7 +54,7 @@ public sealed class PortalTunnelPresentation : IDisposable
|
|||
private readonly PortalTunnelCamera _camera = new();
|
||||
private readonly Random _random;
|
||||
private readonly Action<string>? _displayNotice;
|
||||
private readonly uint[] _registeredGfxObjects;
|
||||
private readonly PortalMeshReferenceOwner _meshReferences;
|
||||
|
||||
private bool _visible;
|
||||
private double _rotationElapsed;
|
||||
|
|
@ -62,6 +62,8 @@ public sealed class PortalTunnelPresentation : IDisposable
|
|||
private float _rotationStartAngle;
|
||||
private float _rotationEndAngle;
|
||||
private float _rotationCurrentAngle;
|
||||
private bool _disposeRequested;
|
||||
private bool _disposing;
|
||||
private bool _disposed;
|
||||
|
||||
private PortalTunnelPresentation(
|
||||
|
|
@ -80,7 +82,6 @@ public sealed class PortalTunnelPresentation : IDisposable
|
|||
_gl = gl;
|
||||
_dispatcher = dispatcher;
|
||||
_lightUbo = lightUbo;
|
||||
_meshAdapter = meshAdapter;
|
||||
_setup = setup;
|
||||
_setupDid = setupDid;
|
||||
_animationDid = animationDid;
|
||||
|
|
@ -99,13 +100,9 @@ public sealed class PortalTunnelPresentation : IDisposable
|
|||
MeshRefs = SetupMesh.Flatten(setup),
|
||||
};
|
||||
|
||||
_registeredGfxObjects = setup.Parts
|
||||
.Select(part => (uint)part)
|
||||
.Where(id => id != 0u)
|
||||
.Distinct()
|
||||
.ToArray();
|
||||
foreach (uint gfxObjId in _registeredGfxObjects)
|
||||
_meshAdapter.IncrementRefCount(gfxObjId);
|
||||
_meshReferences = new PortalMeshReferenceOwner(
|
||||
meshAdapter,
|
||||
setup.Parts.Select(part => (ulong)(uint)part));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -116,7 +113,7 @@ public sealed class PortalTunnelPresentation : IDisposable
|
|||
/// </summary>
|
||||
public static PortalTunnelPresentation CreateRequired(
|
||||
GL gl,
|
||||
DatCollection dats,
|
||||
IDatReaderWriter dats,
|
||||
IAnimationLoader animationLoader,
|
||||
IAnimationHookSink hookSink,
|
||||
WbDrawDispatcher dispatcher,
|
||||
|
|
@ -180,6 +177,17 @@ public sealed class PortalTunnelPresentation : IDisposable
|
|||
public uint SetupDid => _setupDid;
|
||||
public uint AnimationDid => _animationDid;
|
||||
|
||||
/// <summary>
|
||||
/// Publishes the synthetic scene's mesh ownership after the presentation
|
||||
/// itself has been stored by <c>GameWindow</c>. A partial acquisition stays
|
||||
/// reachable and is resumed or released by the same lifetime owner.
|
||||
/// </summary>
|
||||
internal void PrepareResources()
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
_meshReferences.Acquire();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retail <c>set_sequence_animation(anim, clear=1, low=1, fps=40)</c>
|
||||
/// on the edge where portal space becomes visible.
|
||||
|
|
@ -332,7 +340,8 @@ public sealed class PortalTunnelPresentation : IDisposable
|
|||
});
|
||||
}
|
||||
|
||||
private void ThrowIfDisposed() => ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
private void ThrowIfDisposed() =>
|
||||
ObjectDisposedException.ThrowIf(_disposeRequested || _disposed, this);
|
||||
|
||||
/// <summary>
|
||||
/// Retail stages animation hooks while advancing the sequence, then drains
|
||||
|
|
@ -372,12 +381,23 @@ public sealed class PortalTunnelPresentation : IDisposable
|
|||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed)
|
||||
if (_disposed || _disposing)
|
||||
return;
|
||||
Exit();
|
||||
_animationHooks.Clear();
|
||||
foreach (uint gfxObjId in _registeredGfxObjects)
|
||||
_meshAdapter.DecrementRefCount(gfxObjId);
|
||||
_disposed = true;
|
||||
|
||||
_disposeRequested = true;
|
||||
_disposing = true;
|
||||
try
|
||||
{
|
||||
_visible = false;
|
||||
_animationHooks.Clear();
|
||||
_sequence.ClearAnimations();
|
||||
_meshReferences.Dispose();
|
||||
if (_meshReferences.IsDisposed)
|
||||
_disposed = true;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_disposing = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue