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
|
|
@ -0,0 +1,85 @@
|
|||
namespace AcDream.App.Rendering;
|
||||
|
||||
internal interface IGlTextureNameApi
|
||||
{
|
||||
uint GenTexture();
|
||||
void DeleteTexture(uint texture);
|
||||
}
|
||||
|
||||
internal sealed class GlTextureNameApi(Silk.NET.OpenGL.GL gl) : IGlTextureNameApi
|
||||
{
|
||||
public uint GenTexture() =>
|
||||
GlResourceCommand.CreateTexture(gl, "terrain construction texture");
|
||||
|
||||
public void DeleteTexture(uint texture) =>
|
||||
GlResourceCommand.DeleteTexture(
|
||||
gl,
|
||||
texture,
|
||||
$"delete terrain construction texture {texture}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retains every texture name immediately after allocation until the complete
|
||||
/// aggregate owner has been constructed. A failed factory rolls names back in
|
||||
/// reverse acquisition order and attempts every deletion.
|
||||
/// </summary>
|
||||
internal sealed class GlTextureConstructionTransaction(IGlTextureNameApi api)
|
||||
: IRetryableResourceCleanup
|
||||
{
|
||||
private readonly List<uint> _ownedNames = [];
|
||||
private bool _finished;
|
||||
|
||||
public bool IsCleanupComplete => _finished;
|
||||
|
||||
public uint Allocate()
|
||||
{
|
||||
if (_finished)
|
||||
throw new InvalidOperationException("The texture construction transaction is finished.");
|
||||
|
||||
uint texture = api.GenTexture();
|
||||
if (texture == 0)
|
||||
throw new InvalidOperationException("OpenGL returned no texture name.");
|
||||
_ownedNames.Add(texture);
|
||||
return texture;
|
||||
}
|
||||
|
||||
public void Commit()
|
||||
{
|
||||
if (_finished)
|
||||
throw new InvalidOperationException("The texture construction transaction is finished.");
|
||||
_ownedNames.Clear();
|
||||
_finished = true;
|
||||
}
|
||||
|
||||
public void Rollback()
|
||||
{
|
||||
if (_finished)
|
||||
return;
|
||||
|
||||
List<Exception>? failures = null;
|
||||
for (int i = _ownedNames.Count - 1; i >= 0; i--)
|
||||
{
|
||||
uint texture = _ownedNames[i];
|
||||
try
|
||||
{
|
||||
api.DeleteTexture(texture);
|
||||
_ownedNames.RemoveAt(i);
|
||||
}
|
||||
catch (Exception failure)
|
||||
{
|
||||
(failures ??= []).Add(new InvalidOperationException(
|
||||
$"Texture construction rollback could not delete OpenGL name {texture}.",
|
||||
failure));
|
||||
}
|
||||
}
|
||||
|
||||
if (failures is not null)
|
||||
throw new AggregateException(
|
||||
"Texture construction rollback did not release every allocated OpenGL name.",
|
||||
failures);
|
||||
|
||||
_finished = true;
|
||||
}
|
||||
|
||||
public void RetryCleanup() => Rollback();
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue