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
148
src/AcDream.App/Rendering/PrivatePresentationRenderer.cs
Normal file
148
src/AcDream.App/Rendering/PrivatePresentationRenderer.cs
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
using System.Numerics;
|
||||
using AcDream.App.Diagnostics;
|
||||
using AcDream.App.Streaming;
|
||||
using AcDream.App.UI;
|
||||
using Silk.NET.Input;
|
||||
|
||||
namespace AcDream.App.Rendering;
|
||||
|
||||
internal interface IPrivatePortalViewport
|
||||
{
|
||||
void Draw(int width, int height);
|
||||
}
|
||||
|
||||
internal interface IPrivatePaperdollFrame
|
||||
{
|
||||
void Render();
|
||||
}
|
||||
|
||||
internal interface IRetainedGameplayUiFrame
|
||||
{
|
||||
void Render(double deltaSeconds, int width, int height);
|
||||
}
|
||||
|
||||
internal interface IPrivateFrameScreenshot
|
||||
{
|
||||
bool CapturePending(int width, int height);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws the private and 2-D presentation layers after the world alpha scope
|
||||
/// has closed: portal CreatureMode, paperdoll FBO, retained gameplay UI,
|
||||
/// developer UI, then the complete-frame screenshot.
|
||||
/// </summary>
|
||||
internal sealed class PrivatePresentationRenderer : IPrivatePresentationFramePhase
|
||||
{
|
||||
private readonly IPrivatePortalViewport _portal;
|
||||
private readonly IRenderFrameFoundationSource _foundation;
|
||||
private readonly IPrivatePaperdollFrame? _paperdoll;
|
||||
private readonly IRetainedGameplayUiFrame? _gameplayUi;
|
||||
private readonly IDevToolsFrameLifecycle? _devTools;
|
||||
private readonly IPrivateFrameScreenshot? _screenshots;
|
||||
|
||||
public PrivatePresentationRenderer(
|
||||
IPrivatePortalViewport portal,
|
||||
IRenderFrameFoundationSource foundation,
|
||||
IPrivatePaperdollFrame? paperdoll,
|
||||
IRetainedGameplayUiFrame? gameplayUi,
|
||||
IDevToolsFrameLifecycle? devTools,
|
||||
IPrivateFrameScreenshot? screenshots)
|
||||
{
|
||||
_portal = portal ?? throw new ArgumentNullException(nameof(portal));
|
||||
_foundation = foundation
|
||||
?? throw new ArgumentNullException(nameof(foundation));
|
||||
_paperdoll = paperdoll;
|
||||
_gameplayUi = gameplayUi;
|
||||
_devTools = devTools;
|
||||
_screenshots = screenshots;
|
||||
}
|
||||
|
||||
public PrivatePresentationFrameOutcome Render(
|
||||
RenderFrameInput input,
|
||||
WorldRenderFrameOutcome world)
|
||||
{
|
||||
_ = world;
|
||||
// Foundation is the immutable result of this frame's clear phase.
|
||||
// Snapshot it before drawing so a portal transition raised by a
|
||||
// private layer cannot relabel the viewport that was just presented.
|
||||
bool portalViewportVisible =
|
||||
_foundation.Foundation.PortalViewportVisible;
|
||||
_portal.Draw(input.ViewportWidth, input.ViewportHeight);
|
||||
_paperdoll?.Render();
|
||||
_gameplayUi?.Render(
|
||||
input.DeltaSeconds,
|
||||
input.ViewportWidth,
|
||||
input.ViewportHeight);
|
||||
_devTools?.Render(
|
||||
input.DeltaSeconds,
|
||||
input.ViewportWidth,
|
||||
input.ViewportHeight);
|
||||
bool screenshotCaptured = _screenshots?.CapturePending(
|
||||
input.ViewportWidth,
|
||||
input.ViewportHeight) == true;
|
||||
return new PrivatePresentationFrameOutcome(
|
||||
portalViewportVisible,
|
||||
screenshotCaptured);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Typed portal viewport adapter over the canonical teleport owner.</summary>
|
||||
internal sealed class LocalPlayerPortalViewport : IPrivatePortalViewport
|
||||
{
|
||||
private readonly LocalPlayerTeleportController _teleport;
|
||||
private readonly CameraController _camera;
|
||||
|
||||
public LocalPlayerPortalViewport(
|
||||
LocalPlayerTeleportController teleport,
|
||||
CameraController camera)
|
||||
{
|
||||
_teleport = teleport ?? throw new ArgumentNullException(nameof(teleport));
|
||||
_camera = camera ?? throw new ArgumentNullException(nameof(camera));
|
||||
}
|
||||
|
||||
public void Draw(int width, int height) =>
|
||||
_teleport.DrawPortalViewport(width, height, _camera.Active.Projection);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// One retained-gameplay-UI tick/cursor/draw transaction. This is the explicit
|
||||
/// boundary where the render graph reaches the retained UI composition owner;
|
||||
/// <see cref="RetailUiRuntime"/> intentionally retains its documented state and
|
||||
/// command bindings. The distinction between direct frame ownership and
|
||||
/// recursive shared-owner reachability is recorded in
|
||||
/// docs/architecture/code-structure.md.
|
||||
/// </summary>
|
||||
internal sealed class RetainedGameplayUiFrame : IRetainedGameplayUiFrame
|
||||
{
|
||||
private readonly RetailUiRuntime _runtime;
|
||||
private readonly IInputContext? _input;
|
||||
|
||||
public RetainedGameplayUiFrame(
|
||||
RetailUiRuntime runtime,
|
||||
IInputContext? input)
|
||||
{
|
||||
_runtime = runtime ?? throw new ArgumentNullException(nameof(runtime));
|
||||
_input = input;
|
||||
}
|
||||
|
||||
public void Render(double deltaSeconds, int width, int height)
|
||||
{
|
||||
_runtime.Tick(deltaSeconds);
|
||||
if (_input is not null)
|
||||
_runtime.UpdateCursor(_input.Mice);
|
||||
_runtime.Draw(new Vector2(width, height));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Optional complete-frame capture adapter.</summary>
|
||||
internal sealed class PrivateFrameScreenshot : IPrivateFrameScreenshot
|
||||
{
|
||||
private readonly FrameScreenshotController _screenshots;
|
||||
|
||||
public PrivateFrameScreenshot(FrameScreenshotController screenshots) =>
|
||||
_screenshots = screenshots
|
||||
?? throw new ArgumentNullException(nameof(screenshots));
|
||||
|
||||
public bool CapturePending(int width, int height) =>
|
||||
_screenshots.CapturePending(width, height);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue