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
83
src/AcDream.App/Rendering/RestoredTextureBindingMutation.cs
Normal file
83
src/AcDream.App/Rendering/RestoredTextureBindingMutation.cs
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
using System.Runtime.ExceptionServices;
|
||||
|
||||
namespace AcDream.App.Rendering;
|
||||
|
||||
/// <summary>
|
||||
/// Runs a texture mutation with the caller's prior binding restored on every
|
||||
/// exit path. The concrete GL adapter supplies checked commands; tests can
|
||||
/// fault each edge without requiring a graphics context.
|
||||
/// </summary>
|
||||
internal sealed class RestoredTextureBindingMutation
|
||||
{
|
||||
private uint? _pendingRestore;
|
||||
private bool _operationActive;
|
||||
|
||||
internal bool HasPendingRestore => _pendingRestore.HasValue;
|
||||
|
||||
public void Execute(
|
||||
Func<uint> readBinding,
|
||||
Action<uint> bind,
|
||||
uint mutationBinding,
|
||||
Action mutation)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(readBinding);
|
||||
ArgumentNullException.ThrowIfNull(bind);
|
||||
ArgumentNullException.ThrowIfNull(mutation);
|
||||
if (_operationActive)
|
||||
throw new InvalidOperationException("A texture-binding mutation is already active.");
|
||||
|
||||
_operationActive = true;
|
||||
try
|
||||
{
|
||||
ExecuteCore(readBinding, bind, mutationBinding, mutation);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_operationActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void ExecuteCore(
|
||||
Func<uint> readBinding,
|
||||
Action<uint> bind,
|
||||
uint mutationBinding,
|
||||
Action mutation)
|
||||
{
|
||||
if (_pendingRestore is uint pending)
|
||||
{
|
||||
bind(pending);
|
||||
_pendingRestore = null;
|
||||
}
|
||||
|
||||
uint previousBinding = readBinding();
|
||||
_pendingRestore = previousBinding;
|
||||
Exception? mutationFailure = null;
|
||||
try
|
||||
{
|
||||
bind(mutationBinding);
|
||||
mutation();
|
||||
}
|
||||
catch (Exception failure)
|
||||
{
|
||||
mutationFailure = failure;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
bind(previousBinding);
|
||||
_pendingRestore = null;
|
||||
}
|
||||
catch (Exception restoreFailure)
|
||||
{
|
||||
if (mutationFailure is not null)
|
||||
throw new AggregateException(
|
||||
"Texture mutation and binding restoration both failed.",
|
||||
mutationFailure,
|
||||
restoreFailure);
|
||||
throw;
|
||||
}
|
||||
|
||||
if (mutationFailure is not null)
|
||||
ExceptionDispatchInfo.Capture(mutationFailure).Throw();
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue