refactor(app): extract focused window lifetime

Move the exact retryable shutdown manifest, typed root snapshot, terminal reporting, and native-window-last release out of GameWindow. Keep session and GPU convergence as hard barriers while reporting persistent physical callback cleanup without stranding dependent owners.

Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-22 19:43:52 +02:00
parent 5a55d08106
commit 31e6e192b3
21 changed files with 1297 additions and 572 deletions

View file

@ -133,33 +133,37 @@ public sealed class GameWindowRenderLeafCompositionTests
[Fact]
public void Shutdown_PreservesBorrowedDevtoolsLifetimeAndDrainsGpuBeforeFrontends()
{
string source = GameWindowSource();
string source = GameWindowLifetimeSource();
AssertAppearsInOrder(
source,
"new ResourceShutdownStage(\"submitted GPU work\"",
"new ResourceShutdownStage(\"render frontends\"",
"new(\"developer tools\"",
"owner.DisposeFrontend()",
"new(\"portal tunnel\"",
"new(\"paperdoll viewport\"",
"Hard(\"developer tools\", () => DisposeDevToolsFrontend(render.DevTools))",
"Hard(\"portal tunnel\"",
"Hard(\"paperdoll viewport\"",
"new ResourceShutdownStage(\"OpenGL context\"");
AssertAppearsInOrder(
source,
"private static void DisposeDevToolsFrontend(DevToolsCompositionOwner? owner)",
"owner.DisposeFrontend()",
"if (!owner.IsFrontendDisposalComplete)");
AssertAppearsInOrder(
source,
"new ResourceShutdownStage(\"frame borrowers\"",
"publication.Dispose();",
"bindings.Dispose();",
"frame.FrameGraphPublication?.Dispose()",
"frame.FrameBindings?.Dispose()",
"new ResourceShutdownStage(\"session dependents\"");
AssertAppearsInOrder(
source,
"new(\"frame pacing\", _displayFramePacing.Dispose)",
"new(\"frame profiler\", _frameProfiler.Dispose)");
"Hard(\"frame pacing\", render.FramePacing.Dispose)",
"Hard(\"frame profiler\", render.FrameProfiler.Dispose)");
AssertAppearsInOrder(
source,
"publication.Dispose();",
"owner.DisposeFrontend()",
"new ResourceShutdownStage(\"input\"",
"_input?.Dispose();",
"frame.FrameGraphPublication?.Dispose()",
"Hard(\"developer tools\", () => DisposeDevToolsFrontend(render.DevTools))",
"new ResourceShutdownStage(\"input context\"",
"platform.Input?.Dispose()",
"new ResourceShutdownStage(\"OpenGL context\"");
}
@ -239,6 +243,13 @@ public sealed class GameWindowRenderLeafCompositionTests
"Rendering",
"GameWindow.cs"));
private static string GameWindowLifetimeSource() => File.ReadAllText(Path.Combine(
FindRepoRoot(),
"src",
"AcDream.App",
"Rendering",
"GameWindowLifetime.cs"));
private static string LivePresentationSource() => File.ReadAllText(Path.Combine(
FindRepoRoot(),
"src",