28 KiB
GameWindow Slice 7 — render-frame orchestration
Status: Active 2026-07-22.
Parent program: docs/architecture/code-structure.md, Slice 7.
Baseline: 9512404e; GameWindow.cs is 7,026 raw lines, 241 fields, and
108 methods. The Release suite passes 7,182 tests / 5 fixture or environment
skips. The 314-second lifecycle/reconnect gate and 394-second synchronized
nine-stop resource soak pass.
Behavior rule: This is an ownership extraction. Preserve every accepted
world/PView/alpha/private-viewport/UI draw edge, render-thread publication
edge, GL-state boundary, and GPU-flight failure contract. Do not combine the
extraction with a render-quality change, visibility correction, frame-order
port, or resource-lifetime redesign.
Progress ledger
- A — freeze the complete render graph, correct the architecture SSOT, and introduce data-only frame contracts plus deterministic order/failure tests.
- B — extract paperdoll, panel-layout/devtools, and render-diagnostics leaf
owners while
GameWindowstill orders the frame. - C — extract frame-resource begin/upload/publication and live display, and weather/display foundations that do not depend on camera/root classification.
- D — extract frame-data classification and reusable world scratch without duplicating live identity, spatial, visibility, or resource ownership; then run the dependent audio, sky, lighting, and listener preparation.
- E — replace
RetailPViewDrawContext's callback bag with a typedRetailPViewPassExecutorand data-only inputs. - F — extract
WorldSceneRenderer, including both shared-alpha scopes, PView/fallback world branches, particles, debug world draw, and completion. - G — compose
RenderFrameOrchestrator, cutGameWindow.OnRenderto one handoff, and delete obsolete frame bodies, fields, helpers, and callbacks. - H — corrected-diff reviews, full Release suite, connected lifecycle and soak gates, framebuffer comparison, documentation, memory, and metrics.
Every checked checkpoint is one bisectable architectural commit. A checkpoint
does not complete while a new owner merely delegates a substantial body back to
GameWindow.
1. Outcome and non-goals
At slice exit, GameWindow.OnRender supplies one immutable delta/viewport input
to RenderFrameOrchestrator. The orchestrator owns the GPU-flight transaction
and composes focused frame-resource, world-scene, private-presentation, and
diagnostic phases. GameWindow remains the construction and shutdown shell; it
does not keep the draw graph, PView pass callbacks, frame scratch, paperdoll
assembly, or performance-title body.
The target ownership graph is:
RenderFrameOrchestrator
├── RenderFrameResourceController GPU slot + resource BeginFrame/upload
├── WorldRenderFrameBuilder camera/root/light/classification facts
├── WorldSceneRenderer accepted world draw graph
│ ├── RetailPViewRenderer visibility/order owner
│ ├── RetailPViewPassExecutor concrete GL pass implementation
│ └── WorldRenderDiagnostics probes/debug counters/signatures
├── PrivatePresentationRenderer portal + paperdoll + retained UI + ImGui
│ ├── PaperdollFramePresenter
│ └── DevToolsFramePresenter
└── RenderFrameDiagnosticsController title/resource/frame snapshots
Names may narrow as code lands, but the ownership boundaries do not collapse
into one replacement god object. No new owner may receive GameWindow, a broad
service locator, or an anonymous list of callbacks into the window.
This slice does not change:
- the viewer-cell render root or player-cell lighting root;
- synthetic outdoor-cell behavior or the null-root safety path;
- portal flood, building pre-gates, clip-plane/scissor limits, punch/seal depth behavior, shell lift, viewcone culling, or draw distances;
- shared-alpha sort keys, scope boundaries, blend/cull behavior, or immediate EnvCell/private alpha;
- weather, fog, point-light selection, particle visibility/range, terrain quality, FOV, frame pacing, or audio-listener formulas;
- portal-space, paperdoll, retained gameplay UI, ImGui, or screenshot visuals;
- resource ownership, shutdown/disposal order, or three-frame GPU retirement;
- TS-53's retained-UI time placement on the render seam.
Issue #225's translucent lifestone/particle comparison remains a separate user visual gate. Passing this structural slice must not mark it resolved.
2. Retail oracle and accepted adaptations
This extraction reuses the existing named-retail research rather than reinterpreting the draw algorithms:
SceneTool::BeginScene @ 0x0043DAD0establishes the black scene-clear baseline used by portal CreatureMode replacement;SmartBox::DrawNoBlit @ 0x00454C20updates the viewer and invokes the normal world render before post-world selection work;SmartBox::RenderNormalMode @ 0x00453AA0owns landscape/inside dispatch and the final retail alpha flush;RenderDeviceD3D::DrawInside @ 0x0059F0D0,PView::DrawInside @ 0x005A5860, andPView::ConstructView @ 0x005A57B0own the portal traversal;PView::DrawCells @ 0x005A4840fixes the outside-landscape → alpha flush → conditional depth clear → exit masks → shells → object-list order;LScape::draw @ 0x00506330,GameSky::Draw @ 0x00506FF0,DrawBuilding @ 0x0059F2A0,DrawBlock @ 0x005A17C0, andDrawObjCellForDummies @ 0x005A0760constrain the landscape/building/cell phases;AddMeshToAlphaList @ 0x0059C230andFlushAlphaList @ 0x0059D2E0constrain alpha submission/flush boundaries;CPhysicsPart::UpdateViewerDistance @ 0x0050E030andCShadowPart::insertion_sort @ 0x006B5130constrain transformed DAT SortCenter/CYpt and stable far-to-near ordering;CreatureMode::Render @ 0x004529D0constrains portal and paperdoll private viewports;SceneTool::EndFrame @ 0x0043FB30proves retail gameplay UI precedes retail profiler/debug overlays; placing ImGui above gameplay UI is acdream's IA-12 modern coexistence adaptation, not literal Keystone parity.
The readable pseudocode oracle is
docs/research/2026-06-05-retail-pview-indoor-render-pseudocode.md,
with the current full reference in
docs/research/2026-06-02-retail-render-pipeline-full-reference.md.
Shared-alpha ordering is pinned separately by
docs/research/2026-07-18-retail-shared-alpha-list-pseudocode.md.
This slice preserves, rather than retires, the registered modern adaptations: IA-8/9/10/12/14/15; AD-16/17/19/24; AP-21/32/33/34/35/85/92/115/116/117; TS-6/7; and TS-53. Source pointers move with ownership in the same commit, but mechanism/risk language changes only if behavior actually changes.
3. Frozen production render order
The complete accepted order is:
- call
GpuFrameFlightController.BeginFrameoutside the rendertry; - begin the composite-texture frame and cache tick;
- begin, in order, dispatcher, EnvCell, portal depth, world text, retained-UI text, clip, terrain, lighting UBO, then profiler frame state for the current GPU slot;
- select the portal replacement viewport; reset particle visibility when it is active;
- choose portal black or normal fog clear color, force depth writes, clear color/depth/stencil, and establish CW/back-face frame-global state;
- run GL-state/surface diagnostics;
- advance render-thread publication in order:
WbMeshAdapter.Tick, destination reveal preparation/evaluation, thenParticleRenderer.BeginFrame; - begin ImGui, tick weather, and begin retail selection-scene accumulation;
- when a normal camera/world viewport is active:
- begin the one frame-scoped
RetailAlphaQueuecollection; its landscapeFlushdrains the first sub-scope andEndFramelater drains the final world sub-scope without a second begin; - resolve camera/projection/frustum and begin particle/terrain visibility;
- publish world-reveal visibility/completion;
- preview audio/display settings and publish the listener;
- resolve player lighting cell and collided viewer render cell;
- build prior-visible-cell point-light candidacy, sun/fog/lighting UBO, and animated/equipped classification;
- construct the synthetic outdoor root/building candidates when required;
- run the null-root safety world or the one
RetailPViewRenderer.DrawInsidegraph; - draw the post-world Scene particles/weather fallback and debug geometry;
- sample current-frame DebugVM visible-landblock and nearest-collision facts before the developer UI can consume them;
- close the final shared-alpha scope and publish terrain/cell particle visibility;
- begin the one frame-scoped
- complete retail selection-scene accumulation;
- draw the portal CreatureMode replacement viewport;
- render the private paperdoll FBO before its 2-D widget blit;
- tick/update-cursor/draw retained gameplay UI;
- render ImGui menus and developer panels above gameplay UI;
- capture a requested default-framebuffer screenshot;
- publish window-title, resource-dump, and frame-profile diagnostics;
- close the exact GPU frame once in
finally.
Within RetailPViewRenderer.DrawInside:
- construct the main PView; merge per-building exterior floods only for the synthetic outdoor root and build separate look-in frames for interior roots;
- assemble/upload the one clip arena, prepare EnvCell batches, partition statics/dynamics, and classify outside-stage dynamics;
- draw each outside slice early: sky, terrain, and outdoor statics;
- draw building look-ins: all far-Z punches, opaque shells, then transparent shells plus statics/dynamics/emitters;
- draw outside-stage dynamic meshes, Scene particles, and weather late;
- draw one interior-root unattached Scene-particle pass;
- flush the landscape shared-alpha scope;
- for an interior root, perform the full depth clear, then write true-depth exit seals; for an outdoor root, retain world depth and use far-Z entry punches;
- draw opaque EnvCell shells once, then transparent shell cells immediate far-to-near;
- draw cell statics as one cross-cell batch, then their particles;
- draw the surviving main-flood dynamics last, then their particles; look-in and outside-stage dynamics remain in their earlier landscape phases.
The landscape alpha flush must never move across the depth clear. The final world alpha close must never move after portal/paperdoll private viewports.
4. Architecture and interfaces
4.1 Frame transaction
Use immutable values equivalent to:
internal readonly record struct RenderFrameInput(
double DeltaSeconds,
int ViewportWidth,
int ViewportHeight);
internal readonly record struct WorldRenderFrameOutcome(
int VisibleLandblocks,
int TotalLandblocks,
bool NormalWorldDrawn);
Portal-viewport selection and drawing belong to PrivatePresentationRenderer,
which runs after the world phase. If a combined public outcome becomes useful,
the top-level orchestrator composes it only after private presentation; the
world owner never claims that a later viewport was drawn.
RenderFrameOrchestrator receives a small fixed set of typed phase owners. It
does not receive every renderer separately, a mutable frame-services bag, or
GameWindow.
BeginFrame remains outside the try: if it fails, no EndFrame is attempted.
After begin succeeds, every failure closes exactly once. Render failure plus
close failure becomes the current explicit AggregateException; close-only
failure propagates directly. Alpha, particle-visibility, and selection-scene
completion retain their current non-finally behavior; changing that recovery
contract requires separate approval and evidence.
4.2 Borrowed resources and shutdown
Slice 7 collaborators borrow the already-created GL/render owners. They do not
dispose them. The existing retryable shutdown transaction keeps its proven
dependency order: wait for submitted work; withdraw UI/render publications;
release textures and mesh owners; then dispose GL backing stores, with
GpuFrameFlightController last among render resources. Slice 8 may group
construction/disposal after the render cutover is stable.
DisplayFramePacingController is the focused shared owner for requested VSync,
live display preview, monitor/window callbacks, and the separate
OnFrameRendered pacing event. Render preparation and window lifecycle wiring
invoke that typed owner directly; neither calls back into a substantial
GameWindow method. Its existing disposal remains in the Slice 7 shutdown
transaction.
4.3 World frame data
WorldRenderFrameBuilder owns reusable classification scratch:
- animated/equipped entity IDs;
- synthetic outdoor node and candidate building cells;
- previous-frame drawable cells used by point-light candidacy;
- camera/root/classification facts with one-frame borrowed lifetime.
The builder owns only facts available before PView execution. Slice-local
visible/outdoor/unattached particle-owner IDs belong to
RetailPViewPassExecutor. The current interior partition is produced by
RetailPViewRenderer.DrawInside and remains in its borrowed result/diagnostic
snapshot; it is never stored as stale pre-draw builder state.
It queries canonical LiveEntityRuntime, GpuWorldState, player-mode/camera,
physics cell graph, cell visibility, and landblock presentation sources. It
does not copy their dictionaries or create a second visibility computation.
Returned collections are borrowed until the next build; tests pin this
lifetime and consumers cannot retain them.
4.4 PView pass execution
Replace the current RetailPViewDrawContext callback bag with a data-only
RetailPViewFrameInput, a typed cell-visibility source, and one explicit
IRetailPViewPassExecutor/RetailPViewPassExecutor. The executor owns the GL
resources needed for these named operations:
SetTerrainClip
DrawLandscapeSlice
DrawLandscapeSliceLate
ClearInteriorDepth
DrawExitPortalMask
DrawLookInPortalPunch
DrawUnattachedSceneParticles
FlushLandscapeAlpha
DrawCellParticles
DrawDynamicsParticles
EmitDiagnostics
RetailPViewRenderer remains the retail ordering owner and calls these typed
operations. The executor may not call GameWindow or make independent
visibility/order decisions. Existing borrowed RetailPViewFrameResult scratch
semantics remain explicit.
4.5 Presentation and diagnostics
PaperdollFramePresenter owns dirty state, DAT-backed clone/re-dress, pose
selection/application, and FBO rendering. Inventory/session paths call
MarkDirty; they do not mutate its internals.
PrivatePresentationRenderer owns portal viewport, paperdoll, retained UI,
ImGui, and screenshot order. A focused panel-layout/devtools owner handles menu
actions and is also reused by framebuffer resize; it cannot call a substantial
window method.
WorldRenderDiagnostics owns pass-local PView/GL/scissor state, render
signatures, and world-pass timings. RenderFrameDiagnosticsController owns
FPS/frame-time accumulation, final visible-landblock counters, performance
title/resource publication, and the public render-frame snapshot. Only
render-derived DebugVM providers move in Slice 7. Update/session/streaming
providers and the cross-domain world-lifecycle resource sampler stay at the
composition boundary until Slice 8 rather than turning either diagnostics
owner into a replacement service locator. Diagnostics observe the frame; they
never choose a draw branch or mutate canonical world ownership.
5. Implementation checkpoints
A — contracts, architecture, and oracles
- correct the stale render-pipeline and per-frame architecture sections;
- add
RenderFrameInput, phase interfaces, and a recording orchestrator; - pin the outer resource/world/private/diagnostic order across normal, portal-replacement, login-wait, and screenshot outcome shapes; defer the concrete indoor/outdoor/null-root branch tests to the world builder and scene owner in D/F; camera is an initialized runtime invariant, so the slice does not invent a new graceful missing-camera path;
- pin the exact GPU begin/end exception matrix;
- add source guards against
GameWindowback-references, mega contexts, and a new PView delegate bag; - capture the current connected framebuffer/resource baseline.
Completed 2026-07-22. RenderFrameOrchestrator now owns the inert five-owner
outer transaction contract; GpuFrameFlightController implements its narrow
lifetime seam. Twenty-six focused render/GPU tests pin value-only contracts,
required-owner construction, exact phase prefixes, per-phase input propagation,
and every begin/render/close failure combination. Release build and the full
suite pass (7,199 passed / 5 skipped after adding 17 tests). All three
corrected-diff reviews are clean; production GameWindow.OnRender is unchanged.
B — leaf presentation and diagnostics
- extract paperdoll refresh/pose/dirty/FBO ownership;
- extract panel-layout reuse and devtools menu/panel rendering;
- extract pass-local render signature, PView/GL/scissor probes, and timing state
into
WorldRenderDiagnostics; extract FPS, final counts, title/resource publication, and the public render snapshot intoRenderFrameDiagnosticsController; - preserve the pre-presentation render-derived DebugVM sampling site separately from the post-screenshot title/resource publication site; leave non-render DebugVM providers and cross-domain world-lifecycle sampling at composition;
- keep call sites in their current
GameWindow.OnRenderpositions.
Completed 2026-07-22. Paperdoll clone/re-dress/pose/FBO work now belongs to
PaperdollFramePresenter; retained surfaces are narrow and optional, while
live identity and DAT pose application resolve through focused adapters.
DevToolsFramePresenter owns the ImGui frame, menus, panels, layout, and input
actions without taking shutdown ownership of the borrowed bootstrap.
WorldRenderDiagnostics, DebugVmRenderFactsPublisher, and
RenderFrameDiagnosticsController own the former render probes, debug facts,
title/resource cadence, and public snapshot. The production handoff now reports
the observed login/world and screenshot outcomes, preserves the original shared
TERRAIN→FRAME diagnostic transaction, and keeps the devtools-off scan path
allocation-free. GameWindow.cs is 6,270 raw lines, 60.1% below the 15,723-line
campaign baseline. Sixty-two focused tests, the Release build, and the complete
suite pass (7,255 passed / 5 skipped). Retail, architecture, and adversarial
corrected-diff reviews are clean.
C — frame resources and live preparation
- extract ordered per-resource
BeginFramecalls, clear/state establishment, histogram probe, mesh upload, reveal evaluation, and particle begin; - extract weather accumulation and display foundations that do not consume the camera/root classification, preserving their current render-time positions;
- consolidate requested-VSync/live-preview, monitor callbacks, and
OnFrameRenderedpacing throughDisplayFramePacingController, while leaving its disposal in the existing shutdown transaction; - prove
WbMeshAdapter.Tickremains before reveal evaluation and drawing; - prove dispatcher begin occurs once for the whole world/paperdoll frame.
Completed 2026-07-22. RenderFrameResourceController now owns the exact
resource-begin → atmosphere/GL-clear → live-upload/reveal/particle transaction,
with a single captured GPU slot shared by every phase. Focused sources own the
login reveal cell, teleport render state, upload timing, and render-time weather
clock. DisplayFramePacingController owns requested VSync, the event-refreshed
monitor-rate cache, software pacing, and the post-render callback without adding
a monitor query to the frame hot path. Borrowed frame owners are withdrawn before
render teardown; portal fallback ownership transfers before the throwable sink
bind; pacing releases its borrowed surface/profiler before their owners close.
GameWindow.cs is 6,181 raw lines, 60.7% below the 15,723-line campaign
baseline. Twenty-one focused tests, the Release build, and the complete suite
pass (7,269 passed / 5 skipped). Retail, architecture, and adversarial
corrected-diff reviews are clean.
D — world frame builder
- move animated/equipped classification, camera/root selection, outdoor-node building gather, and prior-visible-cell light scratch out of the window;
- after those facts exist, run focused audio/listener, live preview, sky PES,
sun/fog/point-light, and lighting-UBO preparation; do not build an interim
GameWindowmega-context; - keep PView-generated particle-owner sets in
RetailPViewPassExecutorand the post-draw partition in the borrowed PView result/diagnostic snapshot; - pin viewer-cell versus player-cell roles, portal replacement, login wait, fallback/null-root, sealed/SeenOutside, and borrowed scratch reset;
- preserve allocation-free warmed frames and hysteretic scratch retention.
Completed 2026-07-22. WorldRenderFrameBuilder now owns the ordered camera,
visibility, live settings/listener, player-lighting versus collided-viewer root,
sky/lighting/fog, animated-ID, and building-candidate preparation. Reusable
animated/building/light-cell collections retain their explicit one-frame
borrowed lifetime; PView drawable-cell feedback returns through the builder and
is copied before the renderer reuses its own scratch. The diagnostic sky-PES
experiment moved to SkyPesFrameController, and fog startup overrides now enter
through typed RuntimeOptions. The frame graph is withdrawn before its borrowed
equipped/effect/audio owners during shutdown. GameWindow.cs is 5,715 raw
lines, 63.6% below the 15,723-line campaign baseline. Twenty-nine focused tests,
the Release build, and the complete suite pass (7,281 passed / 5 skipped).
Retail, architecture, and adversarial corrected-diff reviews are clean.
E — typed PView pass executor
- replace
Action/Funcdraw callbacks inRetailPViewDrawContext; - move landscape early/late, scissor/clip, depth seal/punch, particle passes, landscape alpha flush, and PView diagnostics to the executor;
- add a recording executor test for the complete
DrawInsidecall sequence; - verify no executor operation rebuilds portal visibility or retains a borrowed frame result across calls.
Completed 2026-07-22. RetailPViewRenderer is now the retail visibility and
ordering owner only; RetailPViewPassExecutor owns the concrete clip upload,
EnvCell/entity, landscape, portal depth, particle, alpha, and diagnostic pass
implementations. The old callback bag and broad window closures are gone.
WorldRenderDiagnostics now owns every PView print-on-change signature and
probe sink, while a focused terrain-diagnostics controller preserves the
shared five-second terrain/frame publication transaction across fallback and
PView draws. Real DrawInside fixtures cover outdoor, interior-exit,
no-outside, entity/static/dynamic particle, transparent-shell, look-in, and
second-call scratch-reset behavior; structural tests pin concrete forwarding,
no delegate/back-reference leakage, no borrowed frame/result retention, and
early shutdown withdrawal. GameWindow.cs is 5,303 raw lines, 66.3% below the
15,723-line campaign baseline. Release build and the complete suite pass
(7,295 passed / 5 skipped). Retail, architecture, and adversarial
corrected-diff reviews are clean.
F — world scene owner
- extract alpha/selection/particle-visibility begin/end and the normal-world conditional;
- extract sky/terrain/null-root fallback and unified PView branches;
- extract post-world particles/weather and debug collision drawing;
- return a small
WorldRenderFrameOutcomefor diagnostics/presentation; - delete the world draw body and helper closure from
GameWindow.
G — final orchestration cutover
- compose concrete resource, world, private-presentation, and diagnostic owners;
- replace
OnRenderwith oneRenderFrameOrchestrator.Renderhandoff; - remove obsolete fields/helpers/callbacks and prove the transitive render graph
has no substantial path back to
GameWindow; - preserve the existing shutdown resource list without transferring disposal;
- measure line/field/method counts. Ownership decides completion; the expected signal is roughly 5,000–5,500 lines before Slice 8 composition cleanup.
H — release and connected gates
After three clean corrected-diff reviews:
- run focused App/Core render, PView, alpha, portal, screenshot, and resource tests;
- run
dotnet build AcDream.slnx -c Release; - run the complete Release suite;
- run
tools/run-connected-world-lifecycle-gate.ps1 -SkipBuild; - run
tools/run-connected-r6-soak.ps1 -SkipBuild; - require code-zero graceful exits, exact lifecycle checkpoints/PNGs, no fatal/invariant/reveal/pending-resource failures, and unchanged same-location resource tolerances;
- compare the six existing lifecycle/reconnect PNGs (
capped_login,aerlinthe_first,facility_hub,holtburg_after_dungeon,aerlinthe_revisit, anduncapped_reconnect) with the Slice 6 baseline; - audit architecture, divergence pointers, roadmap, milestones, issues,
AGENTS.md,CLAUDE.md, and durable memory.
The accepted baseline at docs-only commit 9512404e is behavior-equivalent to
production cutover e91f3102: 7,182 passed / 5 skipped, 314.195-second
lifecycle/reconnect, and 393.581-second soak. Exact counters are recorded in
memory/project_gamewindow_decomposition.md and the Slice 6 closeout ledger.
Building/doorway poses, an open paperdoll, transient portal-exit visuals, and
#225 remain user visual gates; the stable post-materialization PNGs do not
overclaim them.
6. Mandatory review gate
After every implementation checkpoint, three read-only reviews run:
- Retail conformance: named anchors, PView/alpha/depth/private-viewport/UI order, and registered adaptation boundaries.
- Architecture/integration: focused owner scope, no replacement god object, no service locator/back-callback, render-thread mutation, borrowed lifetime, GL-state symmetry, and shutdown dependency direction.
- Adversarial: begin/end failures, missing resources, portal/login branches, stale borrowed scratch, callback reentrancy, frame spikes, mid-frame resource churn, and GUID/session replacement.
The primary agent fixes confirmed findings at their root, then requests corrected-diff re-review until clean. Each checkpoint then runs focused tests, Release build/full suite, divergence/doc audit, and lands as one commit.
7. Final acceptance matrix
Automated
- exact orchestrator order for normal, login, portal, indoor, outdoor, and fallback frames, plus construction-time rejection of missing required phase owners;
- exact GPU begin/end/aggregate failure behavior;
- PView landscape/look-in/flush/clear/seal/shell/static/dynamics ordering;
- screenshot after retained UI/ImGui, before title/resource/frame-profile
diagnostics, and before GPU
EndFrame; - dispatcher frame begin once across world and paperdoll scopes;
- frame scratch reset/reuse after skipped, portal, normal, and failed frames;
- no
GameWindowreference or anonymous draw delegate bag in extracted owners; - existing PView replay, shared-alpha, particle visibility, portal, paperdoll, GPU-fence, screenshot, resource, and structural suites remain green;
- Release build and all tests green;
- connected lifecycle/reconnect and synchronized soak reports pass.
In-client campaign gate
- outdoor dense scenes, terrain, sky, weather, particles, and selection match;
- buildings, doorway look-in/out, depth seals/punches, and dynamics stay stable;
- sealed dungeons keep correct visibility and lighting;
- portal replacement and destination reveal preserve the accepted flow;
- paperdoll, retained gameplay UI, cursor, and ImGui layering are unchanged;
- no resource growth, GPU reset, render exception, or shutdown regression.
8. Fixed assumptions
- all render/GL mutation remains on the existing render thread;
DatCollectionremains the only DAT reader;LiveEntityRuntime,GpuWorldState, cell visibility, session, and resource owners remain canonical and are not copied;- existing render resources are borrowed through Slice 7 and disposed by the current shutdown transaction;
- frame-local results and scratch collections are borrowed until the next frame/call unless explicitly copied;
- no quality/range/performance tradeoff is introduced to make the extraction easier;
- missing optional diagnostic/UI owners skip only their own presentation and never suppress world drawing or GPU frame closure.