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>
68 lines
2 KiB
C#
68 lines
2 KiB
C#
using System.Runtime.ExceptionServices;
|
|
|
|
namespace AcDream.App.Rendering;
|
|
|
|
/// <summary>
|
|
/// Temporarily removes bindless residency around texture-state mutation while
|
|
/// retaining the obligation to restore the pair across failed mutation or
|
|
/// failed reacquisition attempts.
|
|
/// </summary>
|
|
internal sealed class BindlessTextureMutationGuard(BindlessTexturePair pair)
|
|
{
|
|
private bool _restoreRequired;
|
|
private bool _operationActive;
|
|
|
|
internal bool RestoreRequired => _restoreRequired;
|
|
|
|
public void Execute(Action mutation)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(mutation);
|
|
if (_operationActive)
|
|
throw new InvalidOperationException("A bindless texture mutation is already active.");
|
|
|
|
_operationActive = true;
|
|
Exception? mutationFailure = null;
|
|
Exception? restoreFailure = null;
|
|
try
|
|
{
|
|
_restoreRequired |= pair.HasAnyResident;
|
|
if (pair.HasAnyResident)
|
|
pair.Release();
|
|
|
|
mutation();
|
|
}
|
|
catch (Exception failure)
|
|
{
|
|
mutationFailure = failure;
|
|
}
|
|
finally
|
|
{
|
|
if (_restoreRequired)
|
|
{
|
|
try
|
|
{
|
|
_ = pair.Acquire();
|
|
_restoreRequired = false;
|
|
}
|
|
catch (Exception failure)
|
|
{
|
|
restoreFailure = failure;
|
|
}
|
|
}
|
|
|
|
_operationActive = false;
|
|
}
|
|
|
|
if (mutationFailure is not null && restoreFailure is not null)
|
|
{
|
|
throw new AggregateException(
|
|
"Texture-state mutation failed and bindless residency could not be restored.",
|
|
mutationFailure,
|
|
restoreFailure);
|
|
}
|
|
if (mutationFailure is not null)
|
|
ExceptionDispatchInfo.Capture(mutationFailure).Throw();
|
|
if (restoreFailure is not null)
|
|
ExceptionDispatchInfo.Capture(restoreFailure).Throw();
|
|
}
|
|
}
|