feat(render): unify physical residency accounting

This commit is contained in:
Erik 2026-07-24 16:20:48 +02:00
parent 1866ea0c6d
commit 3e18fc2730
25 changed files with 642 additions and 48 deletions

View file

@ -39,6 +39,8 @@ internal sealed class StandaloneBindlessTextureCache : IDisposable
private readonly Dictionary<uint, StandaloneBindlessTextureResource> _entries = new();
private readonly HashSet<uint> _disposeResidencyReleased = [];
private readonly HashSet<uint> _disposeDeleted = [];
private long _allocatedBytes;
private long _retiringBytes;
private bool _disposeRequested;
private bool _disposing;
private bool _disposed;
@ -62,6 +64,9 @@ internal sealed class StandaloneBindlessTextureCache : IDisposable
internal int OwnerCount => _owners.OwnerCount;
internal int UnownedEntryCount => _unowned.Count;
internal long UnownedBytes => _unowned.ResidentBytes;
internal long AllocatedBytes => _allocatedBytes;
internal long RetiringBytes => _retiringBytes;
internal long BudgetBytes => _unowned.BudgetBytes;
internal int AwaitingRetirementPublicationCount =>
_retirementLedger.AwaitingPublicationCount;
@ -96,6 +101,7 @@ internal sealed class StandaloneBindlessTextureCache : IDisposable
$"Standalone particle surface 0x{resource.SurfaceId:X8} is already cached.");
_owners.Acquire(ownerId, resource.SurfaceId);
_allocatedBytes = checked(_allocatedBytes + resource.Bytes);
}
public void ReleaseOwner(uint ownerId)
@ -143,9 +149,14 @@ internal sealed class StandaloneBindlessTextureCache : IDisposable
// The publication ledger owns this release from this point even
// when queue admission or an immediate callback throws. Never
// republish a texture after residency release has started.
_retiringBytes = checked(_retiringBytes + resource.Bytes);
_retirementLedger.Retire(new RetryableGpuResourceRelease(
() => _backend.MakeNonResident(resource),
() => _backend.Delete(resource)));
() => _backend.Delete(resource),
() => _retiringBytes = checked(
_retiringBytes - resource.Bytes),
() => _allocatedBytes = checked(
_allocatedBytes - resource.Bytes)));
}
}
@ -204,6 +215,8 @@ internal sealed class StandaloneBindlessTextureCache : IDisposable
{
_backend.Delete(resource);
_disposeDeleted.Add(resource.SurfaceId);
_allocatedBytes = checked(
_allocatedBytes - resource.Bytes);
}
catch (Exception ex)
{