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:
Erik 2026-07-18 21:35:16 +02:00
parent 3971997689
commit 749e8ceeb1
225 changed files with 29107 additions and 3914 deletions

View file

@ -1,22 +1,23 @@
namespace AcDream.App.World;
/// <summary>
/// Strongly typed, storage-free view over animation components owned by a
/// <see cref="LiveEntityRuntime"/>. This keeps feature loops type-safe without
/// introducing a second component dictionary.
/// Strongly typed view over animation components owned by a
/// <see cref="LiveEntityRuntime"/>. It owns only reusable traversal scratch;
/// canonical component identity remains in the runtime.
/// </summary>
public sealed class LiveEntityAnimationRuntimeView<TAnimation>
: IEnumerable<KeyValuePair<uint, TAnimation>>
where TAnimation : class, ILiveEntityAnimationRuntime
{
private readonly Func<LiveEntityRuntime?> _runtime;
private readonly List<KeyValuePair<uint, TAnimation>> _iterationSnapshot = new();
public LiveEntityAnimationRuntimeView(Func<LiveEntityRuntime?> runtime) =>
_runtime = runtime ?? throw new ArgumentNullException(nameof(runtime));
public int Count => _runtime()?.AnimationRuntimes.Count ?? 0;
public int Count => _runtime()?.SpatialAnimationRuntimes.Count ?? 0;
public IEnumerable<uint> Keys =>
_runtime()?.AnimationRuntimes.Keys ?? Array.Empty<uint>();
_runtime()?.SpatialAnimationRuntimes.Keys ?? Array.Empty<uint>();
public TAnimation this[uint localEntityId]
{
@ -51,16 +52,79 @@ public sealed class LiveEntityAnimationRuntimeView<TAnimation>
&& runtime.ClearAnimationRuntime(guid);
}
public IEnumerator<KeyValuePair<uint, TAnimation>> GetEnumerator()
public Enumerator GetEnumerator()
{
if (_runtime() is not { } runtime)
yield break;
foreach (var pair in runtime.AnimationRuntimes)
if (pair.Value is TAnimation typed)
yield return new KeyValuePair<uint, TAnimation>(pair.Key, typed);
_iterationSnapshot.Clear();
LiveEntityRuntime? runtime = _runtime();
if (runtime is not null)
{
foreach (var pair in runtime.SpatialAnimationRuntimes)
{
if (pair.Value is TAnimation typed)
{
_iterationSnapshot.Add(
new KeyValuePair<uint, TAnimation>(pair.Key, typed));
}
}
}
return new Enumerator(runtime, _iterationSnapshot);
}
IEnumerator<KeyValuePair<uint, TAnimation>> IEnumerable<KeyValuePair<uint, TAnimation>>.GetEnumerator() =>
GetEnumerator();
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator();
/// <summary>
/// Struct enumerator over a reusable frame snapshot. A runtime can rebucket
/// or delete another entity from inside animation/physics callbacks without
/// invalidating this traversal. Each entry is identity-checked immediately
/// before it is yielded, so GUID reuse cannot advance the displaced owner.
/// </summary>
public struct Enumerator : IEnumerator<KeyValuePair<uint, TAnimation>>
{
private readonly LiveEntityRuntime? _runtime;
private readonly List<KeyValuePair<uint, TAnimation>> _snapshot;
private int _index;
internal Enumerator(
LiveEntityRuntime? runtime,
List<KeyValuePair<uint, TAnimation>> snapshot)
{
_runtime = runtime;
_snapshot = snapshot;
_index = -1;
Current = default;
}
public KeyValuePair<uint, TAnimation> Current { get; private set; }
object System.Collections.IEnumerator.Current => Current;
public bool MoveNext()
{
while (++_index < _snapshot.Count)
{
KeyValuePair<uint, TAnimation> pair = _snapshot[_index];
if (_runtime?.SpatialAnimationRuntimes.TryGetValue(
pair.Key,
out ILiveEntityAnimationRuntime? indexed) == true
&& ReferenceEquals(indexed, pair.Value))
{
Current = pair;
return true;
}
}
Current = default;
return false;
}
public void Dispose() { }
void System.Collections.IEnumerator.Reset() =>
throw new NotSupportedException();
}
}
/// <summary>Storage-free typed view over remote-motion components.</summary>