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
|
|
@ -1,9 +1,9 @@
|
|||
# acdream — code structure & extraction sequence
|
||||
|
||||
**Status:** Living document. Created 2026-05-16; implementation reconciliation
|
||||
completed 2026-07-21; Slices 1–6 landed by 2026-07-22. Slice 7 draw-frame
|
||||
orchestration is the active structural program before new M4 subsystems enter
|
||||
the App layer.
|
||||
completed 2026-07-21; Slices 1–6 and the Slice 7 draw-frame cutover landed by
|
||||
2026-07-22. Slice 7 connected closeout is active before the final Slice 8
|
||||
composition/shutdown cleanup and new M4 subsystems enter the App layer.
|
||||
**Purpose:** Describe the desired structural state of the App layer,
|
||||
explain the rules we've adopted, and lay out the safe extraction
|
||||
sequence from today's reality (one 15,723-line `GameWindow.cs` at the
|
||||
|
|
@ -30,6 +30,7 @@ after Slice 3 14,310 lines / 274 fields / 190 method
|
|||
after Slice 4 10,301 lines / 267 fields / 163 methods
|
||||
after Slice 5 closeout 8,811 lines / 247 fields / 153 methods
|
||||
after Slice 6 closeout 7,026 lines / 241 fields / 108 methods
|
||||
after Slice 7 draw-frame cutover 4,666 lines / 196 fields / 70 methods
|
||||
```
|
||||
|
||||
`GameWindow` is the single object that:
|
||||
|
|
@ -168,6 +169,45 @@ App currently wires it.
|
|||
|
||||
---
|
||||
|
||||
### Render-frame ownership versus recursive reachability
|
||||
|
||||
The typed `RenderFrameOrchestrator` graph owns frame sequencing and borrows
|
||||
long-lived runtime/presentation owners. The enforceable ownership invariant is
|
||||
that the orchestrator and its immediate phase owners retain neither
|
||||
`GameWindow`, an anonymous callback bag, nor direct window delegates. It is
|
||||
**not** an invariant that recursively walking every borrowed canonical owner
|
||||
can never reach an event subscriber or callback that was composed by
|
||||
`GameWindow`; that claim would be false and would confuse object-graph
|
||||
reachability with frame ownership.
|
||||
|
||||
Known recursive callback-bearing paths include (this is evidence and design
|
||||
documentation, not an exhaustive allowlist):
|
||||
|
||||
- `RetainedGameplayUiFrame -> RetailUiRuntime -> RetailUiRuntimeBindings` for
|
||||
retained gameplay UI state and commands.
|
||||
- `PrivatePresentationRenderer -> PaperdollFramePresenter ->
|
||||
RetailPaperdollFrameView/PaperdollInventoryVisibility -> UiElement tree` for
|
||||
private paperdoll visibility and texture publication. This is a second,
|
||||
independent retained-UI entry because `UiElement.Parent` links back to the
|
||||
shared root and sibling controls.
|
||||
- `DevToolsFramePresenter -> DevToolsPanelSet -> panel/ViewModel bindings` for
|
||||
the optional developer UI.
|
||||
- `WorldRenderFrameBuilder -> RuntimeWorldFrameSettingsPreview -> SettingsVM`
|
||||
for the live settings draft preview applied before world drawing.
|
||||
- `LocalPlayerPortalViewport -> LocalPlayerTeleportController ->
|
||||
GameplayInputFrameController -> InputDispatcher.Fired -> GameWindow` for the
|
||||
canonical portal/input lifetime and the host's input-action subscription.
|
||||
|
||||
These are presentation state/command seams, not alternative owners of the
|
||||
window or frame transaction. The screenshot path is deliberately not on this
|
||||
list: viewport width/height now travel in `RenderFrameInput`, so
|
||||
`FrameScreenshotController` no longer stores a window-size callback. New
|
||||
immediate phase owners must still satisfy the direct ownership invariant;
|
||||
recursive shared-owner paths are reviewed against their canonical subsystem
|
||||
lifetime rather than an impossible global no-callback assertion.
|
||||
|
||||
---
|
||||
|
||||
## 3. Target structure of the App layer
|
||||
|
||||
The end state — not what we're shipping in one pass, but the shape
|
||||
|
|
@ -608,7 +648,7 @@ registered; this behavior-preserving extraction introduced no new divergence.
|
|||
|
||||
Detailed execution ledger:
|
||||
[`docs/plans/2026-07-22-gamewindow-slice-7-render-frame-orchestration.md`](../plans/2026-07-22-gamewindow-slice-7-render-frame-orchestration.md)
|
||||
(active).
|
||||
(connected closeout active).
|
||||
|
||||
Move the complete draw graph and its reusable frame-local scratch state into a
|
||||
GL-owning App collaborator. Preserve the exact modern pipeline order, clip
|
||||
|
|
@ -622,6 +662,14 @@ Automated acceptance uses framebuffer artifacts and render/resource
|
|||
checkpoints. Visual acceptance compares outdoor, building, dungeon, portal
|
||||
exit, translucent lifestone/particles, and UI at the same camera positions.
|
||||
|
||||
The production draw cutover is complete. `GameWindow.OnRender` now performs one
|
||||
value-only handoff to `RenderFrameOrchestrator`; focused resource, world,
|
||||
private-presentation, and diagnostic owners contain the former frame body and
|
||||
failure recovery. The Release suite passes 7,341 tests with five intentional
|
||||
skips. `GameWindow` is 4,666 raw lines / 196 fields / 70 methods: 11,057 lines
|
||||
(70.3%) smaller than the campaign baseline. The connected lifecycle and
|
||||
resource-soak closeout remains before Slice 7 is final.
|
||||
|
||||
#### Slice 8 — composition and shutdown cleanup
|
||||
|
||||
Keep GL/window construction in `GameWindow.OnLoad`, but group creation into
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue