refactor(lifetime): own render resource prefixes
Give terrain, sky, retained UI, portal preparation, and the update/render frame pair explicit single owners. Make shader, texture, text, bindless, and GL construction prefixes checked and retryable so partial failure cannot lose or replay resource ownership. Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
parent
fec0d94148
commit
c87b15303d
41 changed files with 3768 additions and 355 deletions
94
src/AcDream.App/Rendering/BindlessTexturePair.cs
Normal file
94
src/AcDream.App/Rendering/BindlessTexturePair.cs
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
namespace AcDream.App.Rendering;
|
||||
|
||||
/// <summary>
|
||||
/// Owns the two independent residency edges used by TerrainAtlas. Acquisition
|
||||
/// and release publish each successful edge immediately, so a partial failure
|
||||
/// retries only work that is still pending.
|
||||
/// </summary>
|
||||
internal sealed class BindlessTexturePair(
|
||||
uint firstTexture,
|
||||
uint secondTexture,
|
||||
Func<uint, ulong> acquire,
|
||||
Action<ulong> release)
|
||||
{
|
||||
private ulong _firstHandle;
|
||||
private ulong _secondHandle;
|
||||
private bool _firstResident;
|
||||
private bool _secondResident;
|
||||
|
||||
public bool IsFullyResident => _firstResident && _secondResident;
|
||||
public bool HasAnyResident => _firstResident || _secondResident;
|
||||
|
||||
public (ulong First, ulong Second) Acquire()
|
||||
{
|
||||
if (!_firstResident)
|
||||
{
|
||||
_firstHandle = acquire(firstTexture);
|
||||
_firstResident = true;
|
||||
}
|
||||
|
||||
if (!_secondResident)
|
||||
{
|
||||
try
|
||||
{
|
||||
_secondHandle = acquire(secondTexture);
|
||||
_secondResident = true;
|
||||
}
|
||||
catch (Exception acquisitionFailure)
|
||||
{
|
||||
try
|
||||
{
|
||||
Release();
|
||||
}
|
||||
catch (Exception cleanupFailure)
|
||||
{
|
||||
throw new AggregateException(
|
||||
"Second bindless texture acquisition failed and the resident prefix did not cleanly roll back.",
|
||||
acquisitionFailure,
|
||||
cleanupFailure);
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
return (_firstHandle, _secondHandle);
|
||||
}
|
||||
|
||||
public void Release()
|
||||
{
|
||||
List<Exception>? failures = null;
|
||||
if (_firstResident)
|
||||
{
|
||||
try
|
||||
{
|
||||
release(_firstHandle);
|
||||
_firstResident = false;
|
||||
_firstHandle = 0;
|
||||
}
|
||||
catch (Exception failure)
|
||||
{
|
||||
(failures ??= []).Add(failure);
|
||||
}
|
||||
}
|
||||
|
||||
if (_secondResident)
|
||||
{
|
||||
try
|
||||
{
|
||||
release(_secondHandle);
|
||||
_secondResident = false;
|
||||
_secondHandle = 0;
|
||||
}
|
||||
catch (Exception failure)
|
||||
{
|
||||
(failures ??= []).Add(failure);
|
||||
}
|
||||
}
|
||||
|
||||
if (failures is not null)
|
||||
throw new AggregateException(
|
||||
"One or more bindless texture handles could not be made non-resident.",
|
||||
failures);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue