refactor(render): compose render frame orchestrator
Move the accepted draw transaction and failure recovery behind typed frame-phase owners so GameWindow only supplies immutable frame input. Preserve retail draw order, make ImGui/bootstrap shutdown ownership explicit, and restore exact text-render GL state on failures.\n\nCo-authored-by: Codex <codex@openai.com>
This commit is contained in:
parent
28e1cf8029
commit
9d7df1bfc5
25 changed files with 1675 additions and 279 deletions
|
|
@ -60,6 +60,29 @@ internal interface IRenderFrameDiagnosticsPhase
|
|||
void Publish(RenderFrameInput input, RenderFrameOutcome outcome);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Closes presentation transactions which may have opened before a later
|
||||
/// render phase failed. Recovery is idempotent so failures before the
|
||||
/// transaction opens and failures after it closes are both safe.
|
||||
/// </summary>
|
||||
internal interface IRenderFrameFailureRecovery
|
||||
{
|
||||
void AbortFrame();
|
||||
}
|
||||
|
||||
internal sealed class NullRenderFrameFailureRecovery : IRenderFrameFailureRecovery
|
||||
{
|
||||
public static NullRenderFrameFailureRecovery Instance { get; } = new();
|
||||
|
||||
private NullRenderFrameFailureRecovery()
|
||||
{
|
||||
}
|
||||
|
||||
public void AbortFrame()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Owns the accepted outer render transaction. Focused phase owners retain the
|
||||
/// detailed PView, private-viewport, UI, and diagnostic order inside their
|
||||
|
|
@ -79,19 +102,22 @@ internal sealed class RenderFrameOrchestrator
|
|||
private readonly IWorldSceneFramePhase _world;
|
||||
private readonly IPrivatePresentationFramePhase _presentation;
|
||||
private readonly IRenderFrameDiagnosticsPhase _diagnostics;
|
||||
private readonly IRenderFrameFailureRecovery _recovery;
|
||||
|
||||
public RenderFrameOrchestrator(
|
||||
IRenderFrameLifetime lifetime,
|
||||
IRenderFrameResourcePhase resources,
|
||||
IWorldSceneFramePhase world,
|
||||
IPrivatePresentationFramePhase presentation,
|
||||
IRenderFrameDiagnosticsPhase diagnostics)
|
||||
IRenderFrameDiagnosticsPhase diagnostics,
|
||||
IRenderFrameFailureRecovery recovery)
|
||||
{
|
||||
_lifetime = lifetime ?? throw new ArgumentNullException(nameof(lifetime));
|
||||
_resources = resources ?? throw new ArgumentNullException(nameof(resources));
|
||||
_world = world ?? throw new ArgumentNullException(nameof(world));
|
||||
_presentation = presentation ?? throw new ArgumentNullException(nameof(presentation));
|
||||
_diagnostics = diagnostics ?? throw new ArgumentNullException(nameof(diagnostics));
|
||||
_recovery = recovery ?? throw new ArgumentNullException(nameof(recovery));
|
||||
}
|
||||
|
||||
public RenderFrameOutcome Render(RenderFrameInput input)
|
||||
|
|
@ -115,17 +141,50 @@ internal sealed class RenderFrameOrchestrator
|
|||
}
|
||||
finally
|
||||
{
|
||||
Exception? recoveryFailure = null;
|
||||
if (renderFailure is not null)
|
||||
{
|
||||
try
|
||||
{
|
||||
// ImGui NewFrame is opened during preparation but normally
|
||||
// closed during private presentation. Abort it before the
|
||||
// GPU flight closes when any intervening phase fails.
|
||||
_recovery.AbortFrame();
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
recoveryFailure = error;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_lifetime.EndFrame();
|
||||
}
|
||||
catch (Exception closeFailure) when (renderFailure is not null)
|
||||
{
|
||||
if (recoveryFailure is not null)
|
||||
{
|
||||
throw new AggregateException(
|
||||
"Rendering failed and neither presentation recovery nor the in-flight GPU frame could be closed.",
|
||||
renderFailure,
|
||||
recoveryFailure,
|
||||
closeFailure);
|
||||
}
|
||||
|
||||
throw new AggregateException(
|
||||
"Rendering failed and the in-flight GPU frame could not be closed.",
|
||||
renderFailure,
|
||||
closeFailure);
|
||||
}
|
||||
|
||||
if (renderFailure is not null && recoveryFailure is not null)
|
||||
{
|
||||
throw new AggregateException(
|
||||
"Rendering failed and the presentation frame could not be aborted.",
|
||||
renderFailure,
|
||||
recoveryFailure);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue