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>
77 lines
2.3 KiB
C#
77 lines
2.3 KiB
C#
using AcDream.App.UI;
|
|
using DatReaderWriter;
|
|
using AcDream.Content;
|
|
using DatReaderWriter.DBObjs;
|
|
|
|
namespace AcDream.App.Rendering;
|
|
|
|
/// <summary>Resolves retail global cursor enum IDs through the portal EnumIDMap chain.</summary>
|
|
internal sealed class RetailCursorResolver
|
|
{
|
|
private readonly IDatReaderWriter _dats;
|
|
private readonly object _datLock;
|
|
private readonly Dictionary<uint, uint> _didByEnum = new();
|
|
private readonly HashSet<uint> _missingEnums = new();
|
|
|
|
public RetailCursorResolver(IDatReaderWriter dats, object datLock)
|
|
{
|
|
_dats = dats;
|
|
_datLock = datLock;
|
|
}
|
|
|
|
public bool TryResolve(RetailGlobalCursorKind kind, out UiCursorMedia cursor)
|
|
{
|
|
cursor = default;
|
|
if (!RetailCursorCatalog.TryGetGlobalCursor(kind, out var spec))
|
|
return false;
|
|
|
|
return TryResolve(spec, out cursor);
|
|
}
|
|
|
|
internal bool TryResolve(RetailCursorSpec spec, out UiCursorMedia cursor)
|
|
{
|
|
cursor = default;
|
|
if (!spec.IsValid)
|
|
return false;
|
|
|
|
if (_didByEnum.TryGetValue(spec.EnumId, out uint cachedDid))
|
|
{
|
|
cursor = new UiCursorMedia(cachedDid, spec.HotspotX, spec.HotspotY);
|
|
return true;
|
|
}
|
|
if (_missingEnums.Contains(spec.EnumId))
|
|
return false;
|
|
|
|
uint did = ResolveDidByEnum(spec.EnumId);
|
|
if (did == 0)
|
|
{
|
|
_missingEnums.Add(spec.EnumId);
|
|
return false;
|
|
}
|
|
|
|
cursor = new UiCursorMedia(did, spec.HotspotX, spec.HotspotY);
|
|
_didByEnum[spec.EnumId] = did;
|
|
return true;
|
|
}
|
|
|
|
private uint ResolveDidByEnum(uint cursorEnum)
|
|
{
|
|
lock (_datLock)
|
|
{
|
|
uint masterDid = (uint)_dats.Portal.Db.Header.MasterMapId;
|
|
if (masterDid == 0)
|
|
return 0;
|
|
|
|
if (!_dats.Portal.TryGet<EnumIDMap>(masterDid, out var master) || master is null)
|
|
return 0;
|
|
|
|
if (!master.ClientEnumToID.TryGetValue(RetailCursorCatalog.CursorEnumTable, out uint cursorMapDid))
|
|
return 0;
|
|
|
|
if (!_dats.Portal.TryGet<EnumIDMap>(cursorMapDid, out var cursorMap) || cursorMap is null)
|
|
return 0;
|
|
|
|
return cursorMap.ClientEnumToID.TryGetValue(cursorEnum, out uint did) ? did : 0;
|
|
}
|
|
}
|
|
}
|