Step 6
This commit is contained in:
@@ -9,7 +9,7 @@ Phase checklist:
|
|||||||
- [x] Split `RuntimeHost`
|
- [x] Split `RuntimeHost`
|
||||||
- [x] Finish live-state and service-facing coordination
|
- [x] Finish live-state and service-facing coordination
|
||||||
- [x] Make the render thread the sole GL owner
|
- [x] Make the render thread the sole GL owner
|
||||||
- [ ] Refactor live state layering into an explicit composition model
|
- [x] Refactor live state layering into an explicit composition model
|
||||||
- [ ] Move persistence onto a background snapshot writer
|
- [ ] Move persistence onto a background snapshot writer
|
||||||
- [ ] Make DeckLink/backend lifecycle explicit with a state machine
|
- [ ] Make DeckLink/backend lifecycle explicit with a state machine
|
||||||
- [ ] Add structured health, telemetry, and operational reporting
|
- [ ] Add structured health, telemetry, and operational reporting
|
||||||
@@ -20,7 +20,8 @@ Checklist note:
|
|||||||
- The checked Phase 2 item means the internal event model substrate is complete enough for later phases: the typed event vocabulary, app-owned dispatcher, coalesced event pump, reload bridge events, production bridges, and pure event tests are in place. Remaining items in [PHASE_2_INTERNAL_EVENT_MODEL_DESIGN.md](/c:/Users/Aiden/Documents/GitHub/video-shader-toys/docs/PHASE_2_INTERNAL_EVENT_MODEL_DESIGN.md) are narrow follow-ups, mainly completion/failure observations and later replacement of the runtime-store poll fallback with real file-watch events.
|
- The checked Phase 2 item means the internal event model substrate is complete enough for later phases: the typed event vocabulary, app-owned dispatcher, coalesced event pump, reload bridge events, production bridges, and pure event tests are in place. Remaining items in [PHASE_2_INTERNAL_EVENT_MODEL_DESIGN.md](/c:/Users/Aiden/Documents/GitHub/video-shader-toys/docs/PHASE_2_INTERNAL_EVENT_MODEL_DESIGN.md) are narrow follow-ups, mainly completion/failure observations and later replacement of the runtime-store poll fallback with real file-watch events.
|
||||||
- The checked Phase 3 item means the render-facing state path now has named live-state, composition, frame-state, resolver, and service-bridge boundaries. `OpenGLComposite::renderEffect()` is reduced to runtime work, frame input construction, and frame rendering.
|
- The checked Phase 3 item means the render-facing state path now has named live-state, composition, frame-state, resolver, and service-bridge boundaries. `OpenGLComposite::renderEffect()` is reduced to runtime work, frame input construction, and frame rendering.
|
||||||
- The checked Phase 4 item means normal runtime GL work is now owned by a dedicated `RenderEngine` render thread. Input upload, output render, preview, screenshot capture, render-local resets, and shader application enter through render-thread queue/request paths instead of caller-thread context borrowing. The remaining output timing risk is callback-coupled synchronous output production, which is intentionally tracked for the later DeckLink/backend lifecycle and playout-queue work.
|
- The checked Phase 4 item means normal runtime GL work is now owned by a dedicated `RenderEngine` render thread. Input upload, output render, preview, screenshot capture, render-local resets, and shader application enter through render-thread queue/request paths instead of caller-thread context borrowing. The remaining output timing risk is callback-coupled synchronous output production, which is intentionally tracked for the later DeckLink/backend lifecycle and playout-queue work.
|
||||||
- It does not mean the whole app is fully extracted. Deeper live-state layering, background persistence, backend lifecycle/playout queue policy, and richer telemetry continue through later phases.
|
- The checked Phase 5 item means persisted, committed/session, transient automation, and render-local state are explicitly named. `CommittedLiveState` physically owns current session layer state, `RuntimeLiveState` owns transient OSC overlays, `RenderStateComposer` consumes a layered input contract, and reset/reload/preset overlay invalidation is centralized and covered by non-GL tests.
|
||||||
|
- It does not mean the whole app is fully extracted. Background persistence, backend lifecycle/playout queue policy, and richer telemetry continue through later phases.
|
||||||
|
|
||||||
## Timing Review
|
## Timing Review
|
||||||
|
|
||||||
@@ -125,30 +126,31 @@ Recommended direction:
|
|||||||
- prefer degraded runtime states over modal failure handling where possible
|
- prefer degraded runtime states over modal failure handling where possible
|
||||||
- add a rolling log file for operational troubleshooting
|
- add a rolling log file for operational troubleshooting
|
||||||
|
|
||||||
### 5. Live OSC overlay and persisted state are still separate concepts without a formal model
|
### 5. Live OSC overlay and persisted state now have an explicit layering model
|
||||||
|
|
||||||
The current design works better now, but it still relies on hand-managed reconciliation between:
|
Phase 5 formalized the previous hand-managed reconciliation between:
|
||||||
|
|
||||||
- persisted/committed parameter state in `RuntimeStore`
|
- base persisted state owned by `RuntimeStore` serialization/preset IO
|
||||||
- transient OSC overlay state in `RenderEngine`
|
- committed session state owned by `CommittedLiveState`
|
||||||
|
- transient OSC overlay state owned by `RuntimeLiveState`
|
||||||
|
- render-local temporal, feedback, preview, screenshot, and playout state owned by `RenderEngine`
|
||||||
|
|
||||||
Relevant code:
|
Relevant code:
|
||||||
|
|
||||||
- [RenderEngine.h](/c:/Users/Aiden/Documents/GitHub/video-shader-toys/apps/LoopThroughWithOpenGLCompositing/gl/RenderEngine.h:18)
|
- [CommittedLiveState.h](/c:/Users/Aiden/Documents/GitHub/video-shader-toys/apps/LoopThroughWithOpenGLCompositing/runtime/live/CommittedLiveState.h:1)
|
||||||
|
- [RuntimeLiveState.h](/c:/Users/Aiden/Documents/GitHub/video-shader-toys/apps/LoopThroughWithOpenGLCompositing/runtime/live/RuntimeLiveState.h:1)
|
||||||
|
- [RenderStateComposer.h](/c:/Users/Aiden/Documents/GitHub/video-shader-toys/apps/LoopThroughWithOpenGLCompositing/runtime/live/RenderStateComposer.h:1)
|
||||||
|
- [RuntimeStateLayerModel.h](/c:/Users/Aiden/Documents/GitHub/video-shader-toys/apps/LoopThroughWithOpenGLCompositing/runtime/live/RuntimeStateLayerModel.h:1)
|
||||||
|
|
||||||
Recommended direction:
|
Current direction:
|
||||||
|
|
||||||
Formalize three layers of state:
|
- render resolves values with a named composition rule:
|
||||||
|
|
||||||
- base persisted state
|
- `final = base + committed + transient`
|
||||||
- operator/UI committed state
|
|
||||||
- transient live automation overlay
|
|
||||||
|
|
||||||
Then render can always resolve:
|
- settled OSC commits are session-only by default and do not request persistence unless policy explicitly opts in
|
||||||
|
- reset, reload, preset load, and shader compatibility changes prune or clear transient overlays at the live-state boundary
|
||||||
- `final = base + committed + transient`
|
- render-local temporal and feedback resources remain outside the parameter layering model
|
||||||
|
|
||||||
That avoids special-case sync behavior becoming scattered across the code.
|
|
||||||
|
|
||||||
### 6. DeckLink lifecycle could be modeled more explicitly
|
### 6. DeckLink lifecycle could be modeled more explicitly
|
||||||
|
|
||||||
@@ -542,11 +544,14 @@ Dedicated design note:
|
|||||||
|
|
||||||
- [PHASE_5_LIVE_STATE_LAYERING_DESIGN.md](/c:/Users/Aiden/Documents/GitHub/video-shader-toys/docs/PHASE_5_LIVE_STATE_LAYERING_DESIGN.md)
|
- [PHASE_5_LIVE_STATE_LAYERING_DESIGN.md](/c:/Users/Aiden/Documents/GitHub/video-shader-toys/docs/PHASE_5_LIVE_STATE_LAYERING_DESIGN.md)
|
||||||
|
|
||||||
Recommended layers:
|
Status:
|
||||||
|
|
||||||
- base persisted state
|
- complete for the current architecture
|
||||||
- operator-committed live state
|
- `RuntimeStateLayerModel` names the state categories
|
||||||
- transient automation overlay
|
- `CommittedLiveState` physically owns committed/session layer state
|
||||||
|
- `RenderStateComposer` consumes `LayeredRenderStateInput`
|
||||||
|
- `RuntimeLiveState` owns transient overlay smoothing, generation, commit settlement, and compatibility pruning
|
||||||
|
- settled OSC commits update session state without requesting persistence by default
|
||||||
|
|
||||||
Render should derive final values from a clear composition rule such as:
|
Render should derive final values from a clear composition rule such as:
|
||||||
|
|
||||||
|
|||||||
@@ -6,13 +6,14 @@ Phase 1 named the subsystems. Phase 2 added the typed event substrate. Phase 3 m
|
|||||||
|
|
||||||
## Status
|
## Status
|
||||||
|
|
||||||
- Phase 5 design package: proposed.
|
- Phase 5 design package: complete.
|
||||||
- Phase 5 implementation: Step 5 complete.
|
- Phase 5 implementation: complete.
|
||||||
- Current alignment: Phase 3 introduced the first pure composition boundary and transient OSC overlay owner. Phase 5 now has a small `RuntimeStateLayerModel` inventory that names the current state categories, `RenderStateComposer` consumes a `LayeredRenderStateInput` whose fields make base persisted, committed live, and transient automation inputs explicit, `RuntimeLiveState` owns transient-overlay invalidation against current layer/parameter compatibility, settled OSC commits have an explicit session-only persistence policy, and `CommittedLiveState` physically owns current session layer state. `RuntimeStore` still owns file IO, config, package metadata, preset persistence, and persistence requests.
|
- Current alignment: Phase 3 introduced the first pure composition boundary and transient OSC overlay owner. Phase 5 now has a small `RuntimeStateLayerModel` inventory that names the current state categories, `RenderStateComposer` consumes a `LayeredRenderStateInput` whose fields make base persisted, committed live, and transient automation inputs explicit, `RuntimeLiveState` owns transient-overlay invalidation against current layer/parameter compatibility, settled OSC commits have an explicit session-only persistence policy, and `CommittedLiveState` physically owns current session layer state. `RuntimeStore` still owns file IO, config, package metadata, preset persistence, and persistence requests.
|
||||||
|
|
||||||
Current live-state footholds:
|
Current live-state footholds:
|
||||||
|
|
||||||
- `RuntimeStore` owns persisted layer stack, parameter values, presets, config, and render snapshot read models.
|
- `RuntimeStore` owns file IO, config, package metadata, preset persistence, persistent-state serialization, and persistence requests.
|
||||||
|
- `CommittedLiveState` physically owns the current committed/session layer stack and parameter values.
|
||||||
- `RuntimeCoordinator` owns mutation validation, classification, accepted/rejected event publication, snapshot/reload follow-ups, and the policy switch between committed states and live snapshots.
|
- `RuntimeCoordinator` owns mutation validation, classification, accepted/rejected event publication, snapshot/reload follow-ups, and the policy switch between committed states and live snapshots.
|
||||||
- `RuntimeSnapshotProvider` publishes render-facing snapshots from committed runtime state.
|
- `RuntimeSnapshotProvider` publishes render-facing snapshots from committed runtime state.
|
||||||
- `RuntimeLiveState` owns transient OSC overlay bookkeeping, smoothing, generation tracking, and commit-settlement policy.
|
- `RuntimeLiveState` owns transient OSC overlay bookkeeping, smoothing, generation tracking, and commit-settlement policy.
|
||||||
@@ -66,8 +67,8 @@ Phase 5 should formalize three layers:
|
|||||||
|
|
||||||
| Layer | Owner | Lifetime | Persistence | Render role |
|
| Layer | Owner | Lifetime | Persistence | Render role |
|
||||||
| --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- |
|
||||||
| Base persisted state | `RuntimeStore` / `LayerStackStore` | survives restart | written to disk | default layer stack, shader selections, saved parameter values |
|
| Base persisted state | `RuntimeStore` plus durable serialization/preset IO | survives restart | written to disk | default saved layer stack, shader selections, saved parameter values |
|
||||||
| Committed live state | `RuntimeCoordinator` or a new live-session collaborator | current running session | may request persistence depending on mutation type | operator/UI/current truth until changed again |
|
| Committed live state | `CommittedLiveState` with policy owned by `RuntimeCoordinator` | current running session | may request persistence depending on mutation type | operator/UI/current truth until changed again |
|
||||||
| Transient automation overlay | `RuntimeLiveState` or a new automation overlay collaborator | high-rate/short-lived | not persisted directly | temporary OSC/automation target applied over committed truth |
|
| Transient automation overlay | `RuntimeLiveState` or a new automation overlay collaborator | high-rate/short-lived | not persisted directly | temporary OSC/automation target applied over committed truth |
|
||||||
|
|
||||||
The target composition rule is:
|
The target composition rule is:
|
||||||
@@ -190,7 +191,7 @@ Layering should use stable render-facing identity:
|
|||||||
- parameter id for shader-defined identity
|
- parameter id for shader-defined identity
|
||||||
- parameter control key for external-control identity
|
- parameter control key for external-control identity
|
||||||
|
|
||||||
Phase 5 should document which identity is authoritative when layer id and control key disagree or when a shader changes.
|
Current policy treats render-facing layer identity plus parameter/control-key compatibility as authoritative. Incompatible transient overlays are pruned before composition, so stale OSC routes do not migrate onto unrelated controls after layer removal, preset load, shader change, or incompatible reload.
|
||||||
|
|
||||||
### Invalidations
|
### Invalidations
|
||||||
|
|
||||||
@@ -307,7 +308,7 @@ Current policy:
|
|||||||
|
|
||||||
### Step 5. Separate Committed-Live Concept From Durable Storage
|
### Step 5. Separate Committed-Live Concept From Durable Storage
|
||||||
|
|
||||||
Decide whether to physically split committed-live state now or introduce a read/model boundary first.
|
Separate the committed-live concept from durable storage with both a physical owner and a read/model boundary.
|
||||||
|
|
||||||
Earlier conservative option:
|
Earlier conservative option:
|
||||||
|
|
||||||
@@ -320,7 +321,7 @@ Stronger option:
|
|||||||
- [x] make `RuntimeSnapshotProvider` consume committed live state through a read model
|
- [x] make `RuntimeSnapshotProvider` consume committed live state through a read model
|
||||||
- [x] leave durable writes in `RuntimeStore`
|
- [x] leave durable writes in `RuntimeStore`
|
||||||
|
|
||||||
Phase 5 does not need a flag-day split. It needs the concept to stop being implicit.
|
The implementation now has the stronger split while keeping `RuntimeStore` as the compatibility facade for existing callers.
|
||||||
|
|
||||||
Current implementation:
|
Current implementation:
|
||||||
|
|
||||||
@@ -334,10 +335,10 @@ Current implementation:
|
|||||||
|
|
||||||
Before calling Phase 5 complete, update:
|
Before calling Phase 5 complete, update:
|
||||||
|
|
||||||
- architecture review checklist
|
- [x] architecture review checklist
|
||||||
- `RuntimeCoordinator`, `RuntimeStore`, `RuntimeSnapshotProvider`, `RenderEngine`, and `ControlServices` subsystem docs
|
- [x] `RuntimeCoordinator`, `RuntimeStore`, `RuntimeSnapshotProvider`, `RenderEngine`, and `ControlServices` subsystem docs
|
||||||
- Phase 6 assumptions about persistence inputs
|
- [x] Phase 6 assumptions about persistence inputs
|
||||||
- Phase 7 assumptions about what render/backend state is not part of live parameter layering
|
- [x] Phase 7 assumptions about what render/backend state is not part of live parameter layering
|
||||||
|
|
||||||
## Testing Strategy
|
## Testing Strategy
|
||||||
|
|
||||||
@@ -397,12 +398,11 @@ Phase 5 can be considered complete once the project can say:
|
|||||||
- [x] reset/reload/preset behavior for transient overlays is centralized or clearly delegated
|
- [x] reset/reload/preset behavior for transient overlays is centralized or clearly delegated
|
||||||
- [x] OSC overlay settle/commit behavior is explicit, including persistence policy
|
- [x] OSC overlay settle/commit behavior is explicit, including persistence policy
|
||||||
- [x] `RuntimeStore` remains durable-state focused and does not absorb transient automation policy
|
- [x] `RuntimeStore` remains durable-state focused and does not absorb transient automation policy
|
||||||
- [ ] render-local temporal/feedback state remains separate from live parameter layering
|
- [x] render-local temporal/feedback state remains separate from live parameter layering
|
||||||
- [ ] subsystem docs and the architecture review reflect the final ownership model
|
- [x] subsystem docs and the architecture review reflect the final ownership model
|
||||||
|
|
||||||
## Open Questions
|
## Open Questions
|
||||||
|
|
||||||
- Should committed live state remain physically in `RuntimeStore` for now, or move to a `CommittedLiveState` collaborator?
|
|
||||||
- Should transient OSC overlay updates become app-level typed events, or stay source-local through `RuntimeServiceLiveBridge`?
|
- Should transient OSC overlay updates become app-level typed events, or stay source-local through `RuntimeServiceLiveBridge`?
|
||||||
- Should overlay commit persistence be global, ingress-specific, or parameter-definition-driven?
|
- Should overlay commit persistence be global, ingress-specific, or parameter-definition-driven?
|
||||||
- What compatibility rule should apply when shader reload preserves a control key but changes parameter shape?
|
- What compatibility rule should apply when shader reload preserves a control key but changes parameter shape?
|
||||||
|
|||||||
@@ -8,15 +8,15 @@ Phases 1-5 separate durable state, coordination policy, render-facing snapshots,
|
|||||||
|
|
||||||
- Phase 6 design package: proposed.
|
- Phase 6 design package: proposed.
|
||||||
- Phase 6 implementation: not started.
|
- Phase 6 implementation: not started.
|
||||||
- Current alignment: `RuntimeStore` owns durable state and serialization, while `RuntimeCoordinator` already publishes explicit persistence-request outcomes for persisted mutations. The remaining issue is that actual disk writes are still synchronous store work rather than queued, debounced, atomic background writes.
|
- Current alignment: `RuntimeStore` owns durable serialization, config, package metadata, preset IO, and persistence requests; `CommittedLiveState` owns the current committed/session layer state; and `RuntimeCoordinator` already publishes explicit persistence-request outcomes for persisted mutations. The remaining issue is that actual disk writes are still synchronous store work rather than queued, debounced, atomic background writes.
|
||||||
|
|
||||||
Current persistence footholds:
|
Current persistence footholds:
|
||||||
|
|
||||||
- `RuntimeStore` owns persistent runtime-state serialization and stack preset serialization.
|
- `RuntimeStore` owns persistent runtime-state serialization, stack preset serialization, and durable file IO.
|
||||||
- `LayerStackStore` owns durable layer and parameter state.
|
- `CommittedLiveState` owns current committed/session layer and parameter state.
|
||||||
- `RuntimeCoordinatorResult::persistenceRequested` exists as an explicit mutation outcome.
|
- `RuntimeCoordinatorResult::persistenceRequested` exists as an explicit mutation outcome.
|
||||||
- `RuntimeEventType::RuntimePersistenceRequested` exists as the event-level persistence request.
|
- `RuntimeEventType::RuntimePersistenceRequested` exists as the event-level persistence request.
|
||||||
- Phase 5 is expected to clarify which live-state mutations are durable, committed-live, or transient.
|
- Phase 5 clarified which live-state mutations are durable, committed-live, transient automation, or render-local. Settled OSC commits are session-only by default and do not request persistence.
|
||||||
|
|
||||||
## Why Phase 6 Exists
|
## Why Phase 6 Exists
|
||||||
|
|
||||||
@@ -61,7 +61,7 @@ Phase 6 should make persistence a small pipeline:
|
|||||||
```text
|
```text
|
||||||
RuntimeCoordinator accepts mutation
|
RuntimeCoordinator accepts mutation
|
||||||
-> publishes/returns persistence request
|
-> publishes/returns persistence request
|
||||||
-> PersistenceWriter captures a durable snapshot
|
-> PersistenceWriter captures a durable snapshot from RuntimeStore serialization
|
||||||
-> background worker debounces/coalesces writes
|
-> background worker debounces/coalesces writes
|
||||||
-> atomic write commits file
|
-> atomic write commits file
|
||||||
-> HealthTelemetry/runtime event records success or failure
|
-> HealthTelemetry/runtime event records success or failure
|
||||||
@@ -70,6 +70,7 @@ RuntimeCoordinator accepts mutation
|
|||||||
The key rule is:
|
The key rule is:
|
||||||
|
|
||||||
- `RuntimeStore` owns durable state and serialization
|
- `RuntimeStore` owns durable state and serialization
|
||||||
|
- `CommittedLiveState` owns current session state; only coordinator-approved durable snapshots should be persisted
|
||||||
- `PersistenceWriter` owns when and how snapshots are written
|
- `PersistenceWriter` owns when and how snapshots are written
|
||||||
- `RuntimeCoordinator` owns whether a mutation requests persistence
|
- `RuntimeCoordinator` owns whether a mutation requests persistence
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ This document expands Phase 7 of [ARCHITECTURE_RESILIENCE_REVIEW.md](/c:/Users/A
|
|||||||
|
|
||||||
Phase 4 made the render thread the sole owner of normal runtime GL work, but output timing is still callback-coupled: DeckLink completion callbacks synchronously request render-thread output production before scheduling the next hardware frame. Phase 7 should make backend lifecycle, buffer policy, playout headroom, and recovery explicit.
|
Phase 4 made the render thread the sole owner of normal runtime GL work, but output timing is still callback-coupled: DeckLink completion callbacks synchronously request render-thread output production before scheduling the next hardware frame. Phase 7 should make backend lifecycle, buffer policy, playout headroom, and recovery explicit.
|
||||||
|
|
||||||
|
Phase 5 clarified that live parameter layering stops at final render-state composition. Phase 7 should keep backend lifecycle, output queue ownership, buffer reuse, temporal/feedback resources, and stale-frame/underrun policy outside the persisted/committed/transient parameter model.
|
||||||
|
|
||||||
## Status
|
## Status
|
||||||
|
|
||||||
- Phase 7 design package: proposed.
|
- Phase 7 design package: proposed.
|
||||||
@@ -49,6 +51,7 @@ Phase 7 should not require:
|
|||||||
|
|
||||||
- a new renderer
|
- a new renderer
|
||||||
- changing shader/state composition
|
- changing shader/state composition
|
||||||
|
- changing committed-live or transient automation layering
|
||||||
- replacing DeckLink support with multiple backends
|
- replacing DeckLink support with multiple backends
|
||||||
- full telemetry UI redesign
|
- full telemetry UI redesign
|
||||||
- removing every synchronous API immediately
|
- removing every synchronous API immediately
|
||||||
@@ -73,6 +76,8 @@ The callback should not wait for rendering. It should:
|
|||||||
- schedule the next frame
|
- schedule the next frame
|
||||||
- publish backend timing/health observations
|
- publish backend timing/health observations
|
||||||
|
|
||||||
|
The queue contains rendered output-frame ownership and scheduling metadata, not live parameter state. Parameter composition should already be resolved before an output frame enters this playout boundary.
|
||||||
|
|
||||||
## Target Lifecycle Model
|
## Target Lifecycle Model
|
||||||
|
|
||||||
Suggested backend states:
|
Suggested backend states:
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ The following must stay outside `ControlServices` in the target design.
|
|||||||
|
|
||||||
The subsystem may report that an input requested a state change, but it should not decide whether that change is persisted.
|
The subsystem may report that an input requested a state change, but it should not decide whether that change is persisted.
|
||||||
|
|
||||||
That belongs to `RuntimeCoordinator` and `RuntimeStore`.
|
That belongs to `RuntimeCoordinator`, with `RuntimeStore` and the later persistence writer carrying out durable writes when policy requests them.
|
||||||
|
|
||||||
### Render Snapshot Publication
|
### Render Snapshot Publication
|
||||||
|
|
||||||
@@ -161,9 +161,9 @@ That belongs to `RuntimeCoordinator` and `RuntimeStore`.
|
|||||||
|
|
||||||
### Render-Local Overlay Ownership
|
### Render-Local Overlay Ownership
|
||||||
|
|
||||||
Live OSC overlays, temporal state, shader feedback, and render-only transient state belong to `RenderEngine`.
|
Live OSC automation overlays belong to the live-state/render preparation boundary (`RuntimeLiveState` today). Temporal state, shader feedback, output staging, and other render-only transient state belong to `RenderEngine`.
|
||||||
|
|
||||||
`ControlServices` may ingest automation targets, but it should not own how those targets are applied inside the render domain.
|
`ControlServices` may ingest and coalesce automation targets, but it should not own how those targets are composed, committed, persisted, or applied inside the render domain.
|
||||||
|
|
||||||
### Hardware Timing or Playout Recovery
|
### Hardware Timing or Playout Recovery
|
||||||
|
|
||||||
|
|||||||
@@ -43,10 +43,9 @@ The current rendering path is split across several classes:
|
|||||||
|
|
||||||
That split is workable today, but it creates architectural pressure:
|
That split is workable today, but it creates architectural pressure:
|
||||||
|
|
||||||
- GL ownership is thread-shared instead of sole-owned.
|
|
||||||
- render and playout timing are still callback-coupled.
|
- render and playout timing are still callback-coupled.
|
||||||
- preview and playout are produced in the same immediate path.
|
- preview and playout are produced in the same immediate path.
|
||||||
- render-local transient state now has clearer Phase 3 boundaries, but GL ownership is still shared through callback and UI entrypoints.
|
- render-local transient state now has clearer Phase 3/5 boundaries, but output production is still synchronously requested by the backend completion path.
|
||||||
- it is difficult to test render behavior separately from app bootstrap and hardware integration.
|
- it is difficult to test render behavior separately from app bootstrap and hardware integration.
|
||||||
|
|
||||||
`RenderEngine` exists to absorb that responsibility into one subsystem with one direction of ownership. Phase 4 has completed the GL ownership part of this target: normal runtime GL work now enters through the `RenderEngine` render thread.
|
`RenderEngine` exists to absorb that responsibility into one subsystem with one direction of ownership. Phase 4 has completed the GL ownership part of this target: normal runtime GL work now enters through the `RenderEngine` render thread.
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ The coordinator decides which state category a mutation affects:
|
|||||||
|
|
||||||
The design rule is that classification belongs here, not in the ingress layer and not in render code.
|
The design rule is that classification belongs here, not in the ingress layer and not in render code.
|
||||||
|
|
||||||
Phase 5 has started codifying the shared vocabulary for this classification in `RuntimeStateLayerModel`. The current model records committed session parameter values, layer bypass state, and runtime compile/reload flags as committed-live/session coordination state, even though some of those values are still physically backed by `RuntimeStore` during migration.
|
Phase 5 codifies the shared vocabulary for this classification in `RuntimeStateLayerModel`. Current committed session parameter values and layer bypass state are committed-live/session state owned by `CommittedLiveState`; runtime compile/reload flags are coordination state rather than durable store truth.
|
||||||
|
|
||||||
### 4. Snapshot publication requests
|
### 4. Snapshot publication requests
|
||||||
|
|
||||||
@@ -248,13 +248,15 @@ Typical interaction:
|
|||||||
|
|
||||||
This is the coordinator's primary logical domain.
|
This is the coordinator's primary logical domain.
|
||||||
|
|
||||||
Even while committed live state is physically stored inside `RuntimeStore`, the coordinator should be considered the policy owner of:
|
The coordinator is the policy owner of:
|
||||||
|
|
||||||
- current layer stack composition
|
- current layer stack composition
|
||||||
- current selected shaders
|
- current selected shaders
|
||||||
- current bypass flags
|
- current bypass flags
|
||||||
- current operator-authored parameter values
|
- current operator-authored parameter values
|
||||||
|
|
||||||
|
`CommittedLiveState` is the physical owner for this current-session layer state. `RuntimeStore` persists or skips disk writes according to coordinator policy and remains the compatibility facade for existing mutation call shapes.
|
||||||
|
|
||||||
### Transient live overlay state
|
### Transient live overlay state
|
||||||
|
|
||||||
The coordinator defines the rules for transient state, but should not become the long-term storage owner for render-local transient data.
|
The coordinator defines the rules for transient state, but should not become the long-term storage owner for render-local transient data.
|
||||||
@@ -534,7 +536,6 @@ Mitigation:
|
|||||||
|
|
||||||
## Open Questions
|
## Open Questions
|
||||||
|
|
||||||
- Should committed live state remain physically stored in `RuntimeStore`, or should the coordinator gain a live-session companion object before Phase 3?
|
|
||||||
- Should preset load/save stay synchronous through early migration, or should the coordinator always treat them as policy requests whose persistence effects may complete later?
|
- Should preset load/save stay synchronous through early migration, or should the coordinator always treat them as policy requests whose persistence effects may complete later?
|
||||||
- Should reload requests be modeled as a dedicated mutation class distinct from ordinary control mutations from the start?
|
- Should reload requests be modeled as a dedicated mutation class distinct from ordinary control mutations from the start?
|
||||||
- How much normalization of parameter values should remain in store-side helpers versus moving into coordinator policy helpers?
|
- How much normalization of parameter values should remain in store-side helpers versus moving into coordinator policy helpers?
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ Before the Phase 1 runtime split, the closest behavior lived in:
|
|||||||
|
|
||||||
`RenderSnapshotBuilder` is responsible for:
|
`RenderSnapshotBuilder` is responsible for:
|
||||||
|
|
||||||
- building render-facing snapshots from durable store state plus whatever committed-live state view the Phase 3 split ultimately exposes
|
- building render-facing snapshots from the committed-live read model and package/runtime metadata supplied by `RuntimeStore`
|
||||||
- separating structural snapshot changes from dynamic frame fields
|
- separating structural snapshot changes from dynamic frame fields
|
||||||
- translating runtime layer state into render-ready layer descriptors
|
- translating runtime layer state into render-ready layer descriptors
|
||||||
- attaching immutable or near-immutable shader/package-derived data needed by render
|
- attaching immutable or near-immutable shader/package-derived data needed by render
|
||||||
@@ -81,13 +81,11 @@ The shape of render-facing layer state should remain consistent across phases ev
|
|||||||
|
|
||||||
`RenderSnapshotBuilder` should build from a read-oriented runtime view, not from direct mutation calls. `RuntimeSnapshotProvider` should consume the builder's output and own publication/cache behavior.
|
`RenderSnapshotBuilder` should build from a read-oriented runtime view, not from direct mutation calls. `RuntimeSnapshotProvider` should consume the builder's output and own publication/cache behavior.
|
||||||
|
|
||||||
That view will likely include:
|
That view now includes:
|
||||||
|
|
||||||
- durable configuration and layer-stack data from `RuntimeStore`
|
- committed live layer state from `CommittedLiveStateReadModel`
|
||||||
- committed live values from either:
|
- package and manifest metadata supplied through `RuntimeStore`
|
||||||
- `RuntimeStore`, while committed live state is still co-located there, or
|
- durable runtime configuration needed to describe render-facing dimensions and defaults
|
||||||
- a coordinator-owned live-state companion once Phase 3 finishes the split
|
|
||||||
- package and manifest metadata required to describe render-facing layer structure
|
|
||||||
|
|
||||||
The important Phase 1 rule is not "the provider always reads one specific object." It is:
|
The important Phase 1 rule is not "the provider always reads one specific object." It is:
|
||||||
|
|
||||||
@@ -297,9 +295,9 @@ Notes:
|
|||||||
|
|
||||||
### `RuntimeStore`
|
### `RuntimeStore`
|
||||||
|
|
||||||
`RenderSnapshotBuilder` depends on store-owned durable data and package metadata through a read-oriented interface or view. `RuntimeSnapshotProvider` depends on the builder rather than reaching into store internals directly.
|
`RenderSnapshotBuilder` depends on store-owned durable metadata and the committed-live read model exposed through store-facing read APIs. `RuntimeSnapshotProvider` depends on the builder rather than reaching into store internals directly.
|
||||||
|
|
||||||
If committed live state remains physically co-located with the store during early migration, the builder may read it through the same view. If committed live state moves behind a coordinator-owned live-session model later, the builder should consume that through a similarly read-oriented view.
|
Committed session layer state now lives in `CommittedLiveState`; `RuntimeStore` remains the facade that combines that read model with package metadata and persistence-owned data for snapshot publication.
|
||||||
|
|
||||||
Neither the builder nor provider should mutate the store directly.
|
Neither the builder nor provider should mutate the store directly.
|
||||||
|
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ Those are coordinator concerns, not store concerns.
|
|||||||
|
|
||||||
`RuntimeStore` should own the following state categories.
|
`RuntimeStore` should own the following state categories.
|
||||||
|
|
||||||
Phase 5 names this boundary in code through `RuntimeStateLayerModel`: persisted layer stack data, saved parameter values, and stack presets are classified as base persisted state. Operator/session values may still be backed by the store during migration, but their mutation policy is committed-live policy owned by the coordinator, not durable-store policy by default.
|
Phase 5 names this boundary in code through `RuntimeStateLayerModel`: persisted layer stack data, saved parameter values, and stack presets are classified as base persisted state. Operator/session values are owned by `CommittedLiveState`; their mutation policy is committed-live policy owned by the coordinator, not durable-store policy by default.
|
||||||
|
|
||||||
Phase 5 also adds `CommittedLiveState` as the physical owner of current session/operator layer state and `CommittedLiveStateReadModel` as the named read boundary for render snapshot publication. `RuntimeStore` still owns file IO, config, package metadata, preset persistence, and persistence requests, but it delegates current-session layer mutations to `CommittedLiveState`.
|
Phase 5 also adds `CommittedLiveState` as the physical owner of current session/operator layer state and `CommittedLiveStateReadModel` as the named read boundary for render snapshot publication. `RuntimeStore` still owns file IO, config, package metadata, preset persistence, and persistence requests, but it delegates current-session layer mutations to `CommittedLiveState`.
|
||||||
|
|
||||||
@@ -366,10 +366,14 @@ Those belong under other target subsystems.
|
|||||||
- runtime host config load and resolved paths
|
- runtime host config load and resolved paths
|
||||||
|
|
||||||
The current codebase has completed this part of the split: `RuntimeConfigStore` owns config parsing, path resolution, configured ports/formats, runtime roots, and shader compiler paths, while `RuntimeStore` exposes compatibility-shaped delegates for existing callers.
|
The current codebase has completed this part of the split: `RuntimeConfigStore` owns config parsing, path resolution, configured ports/formats, runtime roots, and shader compiler paths, while `RuntimeStore` exposes compatibility-shaped delegates for existing callers.
|
||||||
|
- `CommittedLiveState`
|
||||||
|
- current committed/session layer stack and parameter values
|
||||||
|
- layer CRUD/reorder and shader selection for the running session
|
||||||
|
- committed-live read model for snapshot publication
|
||||||
- `LayerStackStore`
|
- `LayerStackStore`
|
||||||
- durable layer stack and parameter values
|
- backing layer stack mechanics used by committed-live state
|
||||||
- layer CRUD/reorder and shader selection
|
- layer CRUD/reorder and shader selection helpers
|
||||||
- stack preset value serialization/load
|
- stack preset value serialization/load helpers
|
||||||
- `RuntimeStatePresenter` / `RuntimeStateJson`
|
- `RuntimeStatePresenter` / `RuntimeStateJson`
|
||||||
- runtime-state JSON assembly
|
- runtime-state JSON assembly
|
||||||
- layer-stack presentation serialization
|
- layer-stack presentation serialization
|
||||||
@@ -382,7 +386,7 @@ The current codebase has completed this part of the split: `RuntimeConfigStore`
|
|||||||
- `PersistenceWriter` helper
|
- `PersistenceWriter` helper
|
||||||
- synchronous at first, async/debounced later
|
- synchronous at first, async/debounced later
|
||||||
|
|
||||||
The current codebase has completed the layer split: `LayerStackStore` owns durable layer state, layer CRUD/reorder, parameter persistence, and stack preset value serialization/load. `RuntimeStore` keeps file IO and facade methods for existing callers.
|
The current codebase has completed the committed-live split: `CommittedLiveState` owns current committed/session layer state using `LayerStackStore` backing mechanics. `RuntimeStore` keeps file IO, package metadata, persistence serialization, persistence requests, preset file access, and facade methods for existing callers.
|
||||||
|
|
||||||
The current codebase has completed the render snapshot split: `RenderSnapshotBuilder` owns render-state assembly, cached parameter refresh, dynamic frame-field refresh, and render snapshot versions. `RuntimeSnapshotProvider` depends on this builder rather than on `RuntimeStore` friendship.
|
The current codebase has completed the render snapshot split: `RenderSnapshotBuilder` owns render-state assembly, cached parameter refresh, dynamic frame-field refresh, and render snapshot versions. `RuntimeSnapshotProvider` depends on this builder rather than on `RuntimeStore` friendship.
|
||||||
|
|
||||||
@@ -536,16 +540,7 @@ Current recommendation:
|
|||||||
|
|
||||||
- keep only durable reference/package metadata here
|
- keep only durable reference/package metadata here
|
||||||
|
|
||||||
### 2. Should Committed Live State Be Co-Located With Persisted State?
|
### 2. Should Preset Application Be A Store Operation Or A Coordinator Operation?
|
||||||
|
|
||||||
The Phase 1 parent doc leaves open whether committed live state stays in the store or is split with a live companion model owned by the coordinator.
|
|
||||||
|
|
||||||
For `RuntimeStore`, the important rule is:
|
|
||||||
|
|
||||||
- if a piece of state is part of the durable truth model, the store should own it
|
|
||||||
- if it is transient or session-only, it should not be forced into the store just for convenience
|
|
||||||
|
|
||||||
### 3. Should Preset Application Be A Store Operation Or A Coordinator Operation?
|
|
||||||
|
|
||||||
The file load and preset parse clearly belong here.
|
The file load and preset parse clearly belong here.
|
||||||
|
|
||||||
@@ -556,7 +551,7 @@ Current recommendation:
|
|||||||
- `RuntimeStore` loads preset content
|
- `RuntimeStore` loads preset content
|
||||||
- `RuntimeCoordinator` decides how to apply it
|
- `RuntimeCoordinator` decides how to apply it
|
||||||
|
|
||||||
### 4. How Early Should Async Persistence Land?
|
### 3. How Early Should Async Persistence Land?
|
||||||
|
|
||||||
Phase 1 does not require it, but the store design should not block it.
|
Phase 1 does not require it, but the store design should not block it.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user