render engine updates
Some checks failed
CI / React UI Build (push) Successful in 11s
CI / Windows Release Package (push) Has been cancelled
CI / Native Windows Build And Tests (push) Has been cancelled

This commit is contained in:
Aiden
2026-05-11 17:06:42 +10:00
parent e459155d51
commit e00e2574ed
10 changed files with 265 additions and 166 deletions

View File

@@ -7,8 +7,8 @@ Phase 1 split runtime responsibilities into named subsystems. Phase 2 added the
## Status
- Phase 3 design package: proposed.
- Phase 3 implementation: initial parallel implementation batch integrated.
- Current alignment: the repo now has the live-state/composer building blocks and a service bridge. `OpenGLComposite::renderEffect()` still remains the app-level frame entrypoint, but the service drain, layer-state resolution, and OSC commit handoff now sit behind a named bridge helper.
- Phase 3 implementation: exit criteria satisfied for the current architecture.
- Current alignment: the repo now has the live-state/composer building blocks, a service bridge, and a named frame-state handoff. `OpenGLComposite::renderEffect()` still remains the app-level frame entrypoint, but the service drain, layer-state resolution, and OSC commit handoff now sit behind named helpers and frame-state data.
Current footholds:
@@ -17,7 +17,9 @@ Current footholds:
- `RuntimeSnapshotProvider` publishes render snapshots from `RenderSnapshotBuilder`.
- `RuntimeLiveState` owns transient OSC overlay bookkeeping and commit-settlement policy.
- `RenderStateComposer` exists as the first pure composition boundary for combining base layer state with live overlays.
- `RenderEngine` still owns snapshot cache selection and final render-layer resolution, but live overlay value composition now delegates to `RenderStateComposer` and `RuntimeLiveState`.
- `RenderFrameInput` / `RenderFrameState` now provide a named frame-facing handoff model for preparing layer state and render inputs before drawing.
- `RenderFrameStateResolver` now owns snapshot cache selection, parameter refresh decisions, and final frame-state resolution before drawing.
- `RenderEngine` owns GL/render resources and delegates frame-state preparation to the resolver.
- `ControlServices` owns OSC ingress, pending OSC updates, completed OSC commit notifications, and service start/stop.
- `RuntimeServiceLiveBridge` translates service OSC queues into render live-state updates and queues settled overlay commit requests.
- `RuntimeEventDispatcher` now routes accepted mutations, reloads, snapshots, shader build events, backend observations, and health observations.
@@ -68,7 +70,7 @@ Those are later phases. Phase 3 is about making state and service coordination c
2. asks `RuntimeServiceLiveBridge` to prepare live render layer states
3. asks `RenderEngine` to draw the layer stack
The bridge now owns service queue draining, live automation settlement, committed/live state selection, and OSC commit handoff. `RenderEngine` still owns snapshot cache selection and dynamic render-field refresh, which is the remaining boundary to clarify before Phase 4.
The bridge now owns service queue draining, live automation settlement, committed/live state selection, and OSC commit handoff. `RenderFrameStateResolver` owns snapshot cache selection, parameter refresh decisions, and dynamic render-field refresh before handing a prepared frame state to `RenderEngine`.
## Target State Model
@@ -150,7 +152,7 @@ Non-responsibilities:
| pending OSC updates drained by `OpenGLComposite` | `OscValueReceived` -> live-state overlay update handler | Phase 2 already has the event type; Phase 3 decides whether transient overlay updates enter the app dispatcher or a source-local bridge. |
| render asks for overlay commit requests | `OscOverlaySettled` or direct coordinator command plus event publication | Commit request creation should leave `renderEffect()` and live near the live-state owner. |
| completed OSC commits drained by `OpenGLComposite` | `RuntimeMutationAccepted` / completion event -> live-state commit completion | Completed commit routing should be event-driven or owned by live-state service bridge. |
| `RenderEngine::ResolveRenderLayerStates(...)` | `RenderStateComposer::BuildFrameState(...)` | Keep final state composition testable without GL. |
| `RenderFrameStateResolver::Resolve(...)` | `RenderStateComposer::BuildFrameState(...)` | Keep final state composition testable without GL. |
| direct persistence writes from store mutations | `RuntimePersistenceRequested` as the durable write trigger | Background writer lands later; Phase 3 should make request boundaries clear. |
| runtime-state broadcast side effects | `RuntimeStateBroadcastRequested` plus optional completed/failed observations | Keep broadcast delivery in services and presentation ownership in runtime presentation. |
@@ -246,7 +248,7 @@ This keeps Phase 6 smaller: the background snapshot writer can subscribe to pers
Introduce `RuntimeLiveState`, `RenderStateComposer`, or an equivalent pair of classes.
Start by moving pure data operations out of `RenderEngine::ResolveRenderLayerStates(...)` without changing behavior.
Start by moving pure data operations out of frame rendering without changing behavior.
Status: started. `runtime/live/RuntimeLiveState` and `runtime/live/RenderStateComposer` now exist, are included in the build, and have a focused `RuntimeLiveStateTests` target.
@@ -291,7 +293,7 @@ void OpenGLComposite::renderEffect()
The exact names can change. The goal is that render effect no longer manually drains services, settles overlay commits, and resolves layer values.
Status: started. `OpenGLComposite::renderEffect()` still drives frame timing, video dimensions, and drawing, but the service-drain, resolve, and commit-handoff path has moved behind `RuntimeServiceLiveBridge::PrepareLiveRenderLayerStates(...)`.
Status: started. `OpenGLComposite::renderEffect()` still drives frame timing, video dimensions, and drawing, but the service-drain, resolve, and commit-handoff path has moved behind `RuntimeServiceLiveBridge::PrepareLiveRenderFrameState(...)` and a named `RenderFrameInput` / `RenderFrameState` handoff.
### Step 5. Add Persistence Boundary Tests
@@ -339,7 +341,7 @@ The current groundwork is intended to let these lanes proceed in parallel with l
| Lane | Primary files | Goal |
| --- | --- | --- |
| A. Live-state behavior | `runtime/live/RuntimeLiveState.*`, `tests/RuntimeLiveStateTests.cpp` | Finish stale completion tests, smoothing edge cases, trigger behavior, and overlay settle policy. |
| B. Render-state composition | `runtime/live/RenderStateComposer.*`, `gl/RenderEngine.*` | Move more of `RenderEngine::ResolveRenderLayerStates(...)` value composition behind the pure composer while keeping GL calls in `RenderEngine`. |
| B. Render-state composition | `runtime/live/RenderStateComposer.*`, `gl/RenderFrameStateResolver.*`, `gl/RenderEngine.*` | Keep value composition and frame-state selection outside GL drawing while keeping GL calls in `RenderEngine`. |
| C. Service bridge | `control/RuntimeServices.*`, `control/ControlServices.*`, possible new bridge class | Stop `OpenGLComposite::renderEffect()` from draining OSC update/completion queues directly. |
| D. App-frame orchestration | `gl/OpenGLComposite.*`, `gl/RuntimeUpdateController.*` | Replace render-effect glue with a narrow frame-state preparation call and commit-request handoff. |
| E. Persistence boundary | `runtime/coordination/RuntimeCoordinator.*`, `runtime/store/*`, event tests | Keep persistence request publication explicit and prepare for a later background writer without changing storage behavior yet. |
@@ -348,13 +350,13 @@ The current groundwork is intended to let these lanes proceed in parallel with l
Phase 3 can be considered complete once the project can say:
- [x] final render-state composition has a named, testable owner outside `OpenGLComposite` (live value composition is covered by `RenderStateComposer`; full snapshot/cache selection still remains in `RenderEngine`)
- [x] final render-state composition has named owners outside `OpenGLComposite` (`RenderStateComposer` covers live value composition; `RenderFrameStateResolver` covers snapshot/cache selection and frame-state resolution)
- [x] transient OSC overlay state has a named owner and tests
- [x] overlay commit requests and completions no longer require `OpenGLComposite` to drain service queues directly
- [x] `RenderEngine` is closer to GL/render resource ownership and less responsible for value composition
- [x] `RuntimeStore` remains durable-state focused and does not gain live overlay responsibilities
- [x] persistence requests are explicit event outcomes for persisted mutations
- [ ] Phase 4 can define a render-thread input contract around immutable or near-immutable frame state
- [x] Phase 4 can define a render-thread input contract around immutable or near-immutable frame state
## Open Questions