Phase 5 step 5
This commit is contained in:
@@ -89,7 +89,7 @@ bool RenderSnapshotBuilder::TryBuildLayerRenderStates(unsigned outputWidth, unsi
|
|||||||
|
|
||||||
bool RenderSnapshotBuilder::TryRefreshLayerParameters(std::vector<RuntimeRenderState>& states) const
|
bool RenderSnapshotBuilder::TryRefreshLayerParameters(std::vector<RuntimeRenderState>& states) const
|
||||||
{
|
{
|
||||||
RefreshLayerParameters(mRuntimeStore.CopyLayerStates(), states);
|
RefreshLayerParameters(mRuntimeStore.CopyCommittedLiveLayerStates(), states);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,10 +113,10 @@ void RenderSnapshotBuilder::BuildLayerRenderStates(unsigned outputWidth, unsigne
|
|||||||
{
|
{
|
||||||
states.clear();
|
states.clear();
|
||||||
|
|
||||||
for (const LayerStackStore::LayerPersistentState& layer : readModel.layers)
|
for (const LayerStackStore::LayerPersistentState& layer : readModel.committedLiveState.layers)
|
||||||
{
|
{
|
||||||
auto shaderIt = readModel.packagesById.find(layer.shaderId);
|
auto shaderIt = readModel.committedLiveState.packagesById.find(layer.shaderId);
|
||||||
if (shaderIt == readModel.packagesById.end())
|
if (shaderIt == readModel.committedLiveState.packagesById.end())
|
||||||
continue;
|
continue;
|
||||||
const ShaderPackage& shaderPackage = shaderIt->second;
|
const ShaderPackage& shaderPackage = shaderIt->second;
|
||||||
|
|
||||||
|
|||||||
@@ -576,24 +576,37 @@ ShaderCompilerInputs RuntimeStore::GetShaderCompilerInputs() const
|
|||||||
return inputs;
|
return inputs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CommittedLiveStateReadModel RuntimeStore::BuildCommittedLiveStateReadModel() const
|
||||||
|
{
|
||||||
|
CommittedLiveStateReadModel model;
|
||||||
|
std::lock_guard<std::mutex> lock(mMutex);
|
||||||
|
model.layers = mLayerStack.Layers();
|
||||||
|
model.packagesById = mShaderCatalog.CaptureSnapshot().packagesById;
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
RenderSnapshotReadModel RuntimeStore::BuildRenderSnapshotReadModel() const
|
RenderSnapshotReadModel RuntimeStore::BuildRenderSnapshotReadModel() const
|
||||||
{
|
{
|
||||||
RenderSnapshotReadModel model;
|
RenderSnapshotReadModel model;
|
||||||
model.signalStatus = mHealthTelemetry.GetSignalStatusSnapshot();
|
model.signalStatus = mHealthTelemetry.GetSignalStatusSnapshot();
|
||||||
|
model.committedLiveState = BuildCommittedLiveStateReadModel();
|
||||||
std::lock_guard<std::mutex> lock(mMutex);
|
std::lock_guard<std::mutex> lock(mMutex);
|
||||||
model.layers = mLayerStack.Layers();
|
|
||||||
model.packagesById = mShaderCatalog.CaptureSnapshot().packagesById;
|
|
||||||
model.timing.startTime = mStartTime;
|
model.timing.startTime = mStartTime;
|
||||||
model.timing.startupRandom = mStartupRandom;
|
model.timing.startupRandom = mStartupRandom;
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<RuntimeStore::LayerPersistentState> RuntimeStore::CopyLayerStates() const
|
std::vector<RuntimeStore::LayerPersistentState> RuntimeStore::CopyCommittedLiveLayerStates() const
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(mMutex);
|
std::lock_guard<std::mutex> lock(mMutex);
|
||||||
return mLayerStack.Layers();
|
return mLayerStack.Layers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<RuntimeStore::LayerPersistentState> RuntimeStore::CopyLayerStates() const
|
||||||
|
{
|
||||||
|
return CopyCommittedLiveLayerStates();
|
||||||
|
}
|
||||||
|
|
||||||
RenderTimingSnapshot RuntimeStore::GetRenderTimingSnapshot() const
|
RenderTimingSnapshot RuntimeStore::GetRenderTimingSnapshot() const
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(mMutex);
|
std::lock_guard<std::mutex> lock(mMutex);
|
||||||
|
|||||||
@@ -71,7 +71,9 @@ public:
|
|||||||
void ClearReloadRequest();
|
void ClearReloadRequest();
|
||||||
bool CopyShaderPackageForStoredLayer(const std::string& layerId, ShaderPackage& shaderPackage, std::string& error) const;
|
bool CopyShaderPackageForStoredLayer(const std::string& layerId, ShaderPackage& shaderPackage, std::string& error) const;
|
||||||
::ShaderCompilerInputs GetShaderCompilerInputs() const;
|
::ShaderCompilerInputs GetShaderCompilerInputs() const;
|
||||||
|
::CommittedLiveStateReadModel BuildCommittedLiveStateReadModel() const;
|
||||||
::RenderSnapshotReadModel BuildRenderSnapshotReadModel() const;
|
::RenderSnapshotReadModel BuildRenderSnapshotReadModel() const;
|
||||||
|
std::vector<LayerPersistentState> CopyCommittedLiveLayerStates() const;
|
||||||
std::vector<LayerPersistentState> CopyLayerStates() const;
|
std::vector<LayerPersistentState> CopyLayerStates() const;
|
||||||
::RenderTimingSnapshot GetRenderTimingSnapshot() const;
|
::RenderTimingSnapshot GetRenderTimingSnapshot() const;
|
||||||
::RuntimeStatePresentationReadModel BuildRuntimeStatePresentationReadModel() const;
|
::RuntimeStatePresentationReadModel BuildRuntimeStatePresentationReadModel() const;
|
||||||
|
|||||||
@@ -27,10 +27,15 @@ struct RenderTimingSnapshot
|
|||||||
double startupRandom = 0.0;
|
double startupRandom = 0.0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RenderSnapshotReadModel
|
struct CommittedLiveStateReadModel
|
||||||
{
|
{
|
||||||
std::vector<LayerStackStore::LayerPersistentState> layers;
|
std::vector<LayerStackStore::LayerPersistentState> layers;
|
||||||
std::map<std::string, ShaderPackage> packagesById;
|
std::map<std::string, ShaderPackage> packagesById;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RenderSnapshotReadModel
|
||||||
|
{
|
||||||
|
CommittedLiveStateReadModel committedLiveState;
|
||||||
HealthTelemetry::SignalStatusSnapshot signalStatus;
|
HealthTelemetry::SignalStatusSnapshot signalStatus;
|
||||||
RenderTimingSnapshot timing;
|
RenderTimingSnapshot timing;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ 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: proposed.
|
||||||
- Phase 5 implementation: Step 4 complete.
|
- Phase 5 implementation: Step 5 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, and settled OSC commits have an explicit session-only persistence policy. Committed runtime values are still physically stored through `RuntimeStore`/`LayerStackStore`.
|
- 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 snapshot publication consumes a named `CommittedLiveStateReadModel`. Committed runtime values are still physically backed by `RuntimeStore`/`LayerStackStore` during this conservative migration step.
|
||||||
|
|
||||||
Current live-state footholds:
|
Current live-state footholds:
|
||||||
|
|
||||||
@@ -21,6 +21,7 @@ Current live-state footholds:
|
|||||||
- `RuntimeStateLayerModel` names the Phase 5 state categories and classifies current fields as base persisted, committed live, transient automation, render-local, or health/config state.
|
- `RuntimeStateLayerModel` names the Phase 5 state categories and classifies current fields as base persisted, committed live, transient automation, render-local, or health/config state.
|
||||||
- `RuntimeCoordinator` can request layer-scoped transient OSC invalidation, while `RuntimeLiveState` prunes overlays that no longer map to the current render-facing layer/parameter definitions.
|
- `RuntimeCoordinator` can request layer-scoped transient OSC invalidation, while `RuntimeLiveState` prunes overlays that no longer map to the current render-facing layer/parameter definitions.
|
||||||
- `RuntimeCoordinator::CommitOscParameterByControlKey(...)` commits settled OSC values into session state without requesting persistence by default.
|
- `RuntimeCoordinator::CommitOscParameterByControlKey(...)` commits settled OSC values into session state without requesting persistence by default.
|
||||||
|
- `CommittedLiveStateReadModel` names the current committed/session read boundary that feeds render snapshot publication while remaining physically backed by `RuntimeStore`.
|
||||||
|
|
||||||
## Why Phase 5 Exists
|
## Why Phase 5 Exists
|
||||||
|
|
||||||
@@ -310,9 +311,9 @@ Decide whether to physically split committed-live state now or introduce a read/
|
|||||||
|
|
||||||
Conservative option:
|
Conservative option:
|
||||||
|
|
||||||
- leave storage physically in `RuntimeStore`
|
- [x] leave storage physically in `RuntimeStore`
|
||||||
- add a named committed-live read model
|
- [x] add a named committed-live read model
|
||||||
- keep persistence decisions in `RuntimeCoordinator`
|
- [x] keep persistence decisions in `RuntimeCoordinator`
|
||||||
|
|
||||||
Stronger option:
|
Stronger option:
|
||||||
|
|
||||||
@@ -322,6 +323,13 @@ Stronger option:
|
|||||||
|
|
||||||
Phase 5 does not need a flag-day split. It needs the concept to stop being implicit.
|
Phase 5 does not need a flag-day split. It needs the concept to stop being implicit.
|
||||||
|
|
||||||
|
Current implementation:
|
||||||
|
|
||||||
|
- `CommittedLiveStateReadModel` carries the current committed/session layer stack and shader package metadata used by snapshot publication.
|
||||||
|
- `RenderSnapshotReadModel` contains `committedLiveState` rather than exposing layer-stack fields directly.
|
||||||
|
- `RenderSnapshotBuilder` builds render snapshots and parameter refreshes from committed-live read APIs.
|
||||||
|
- `RuntimeStore` still provides the physical backing during this phase, but session-only committed changes can be observed through the committed-live read model without requiring durable persistence.
|
||||||
|
|
||||||
### Step 6. Update Docs And Exit Criteria
|
### Step 6. Update Docs And Exit Criteria
|
||||||
|
|
||||||
Before calling Phase 5 complete, update:
|
Before calling Phase 5 complete, update:
|
||||||
@@ -388,7 +396,7 @@ Phase 5 can be considered complete once the project can say:
|
|||||||
- [x] `RenderStateComposer` or its replacement consumes a layered input contract
|
- [x] `RenderStateComposer` or its replacement consumes a layered input contract
|
||||||
- [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
|
||||||
- [ ] `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
|
- [ ] render-local temporal/feedback state remains separate from live parameter layering
|
||||||
- [ ] subsystem docs and the architecture review reflect the final ownership model
|
- [ ] subsystem docs and the architecture review reflect the final ownership model
|
||||||
|
|
||||||
|
|||||||
@@ -113,6 +113,8 @@ Phase 5's `RuntimeStateLayerModel` explicitly keeps temporal history, feedback s
|
|||||||
|
|
||||||
`RuntimeLiveState` now owns transient automation invalidation for render-facing compatibility. It can clear overlays for a target layer/control key and prunes overlays that no longer resolve to the current layer and parameter definitions before applying them to a frame. This keeps shader reload, preset load, and layer removal behavior local to the live-state/composition boundary instead of scattering it through GL drawing code.
|
`RuntimeLiveState` now owns transient automation invalidation for render-facing compatibility. It can clear overlays for a target layer/control key and prunes overlays that no longer resolve to the current layer and parameter definitions before applying them to a frame. This keeps shader reload, preset load, and layer removal behavior local to the live-state/composition boundary instead of scattering it through GL drawing code.
|
||||||
|
|
||||||
|
Render snapshots now flow through a named `CommittedLiveStateReadModel`, so render-facing committed state is distinct from durable storage even while both are physically backed by the same store during migration.
|
||||||
|
|
||||||
### 5. Shader Build Application
|
### 5. Shader Build Application
|
||||||
|
|
||||||
Compilation itself may eventually move into a separate build service, but once shader build outputs exist, `RenderEngine` owns:
|
Compilation itself may eventually move into a separate build service, but once shader build outputs exist, `RenderEngine` owns:
|
||||||
|
|||||||
@@ -274,6 +274,8 @@ For OSC specifically, the coordinator should eventually decide:
|
|||||||
|
|
||||||
Phase 5 sets the default settled OSC policy to session-only. `CommitOscParameterByControlKey(...)` updates committed session state through the store with persistence disabled, publishes ordinary mutation/state-change observations, and does not request a persistence write unless a future explicit policy opts into durable OSC commits.
|
Phase 5 sets the default settled OSC policy to session-only. `CommitOscParameterByControlKey(...)` updates committed session state through the store with persistence disabled, publishes ordinary mutation/state-change observations, and does not request a persistence write unless a future explicit policy opts into durable OSC commits.
|
||||||
|
|
||||||
|
The committed-live concept now has a named read model, `CommittedLiveStateReadModel`. The coordinator remains the owner of whether a mutation should be durable or session-only, while `RuntimeStore` temporarily backs the read model until a physical `CommittedLiveState` collaborator is worth extracting.
|
||||||
|
|
||||||
### Health and timing state
|
### Health and timing state
|
||||||
|
|
||||||
The coordinator may emit events like:
|
The coordinator may emit events like:
|
||||||
|
|||||||
@@ -97,6 +97,8 @@ Those are coordinator concerns, not store concerns.
|
|||||||
|
|
||||||
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 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 also adds `CommittedLiveStateReadModel` as the named read boundary for current session/operator state. During the conservative migration, `RuntimeStore` still backs that model physically, but snapshot publication consumes the committed-live read model rather than treating render-facing state as raw durable storage.
|
||||||
|
|
||||||
### Runtime Configuration
|
### Runtime Configuration
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
@@ -323,6 +324,22 @@ void TestRuntimeCoordinatorPersistenceEvents()
|
|||||||
Expect(!oscCommitSnapshot.currentValue.numberValues.empty() &&
|
Expect(!oscCommitSnapshot.currentValue.numberValues.empty() &&
|
||||||
oscCommitSnapshot.currentValue.numberValues[0] == 0.2,
|
oscCommitSnapshot.currentValue.numberValues[0] == 0.2,
|
||||||
"settled OSC commit updates the committed session value");
|
"settled OSC commit updates the committed session value");
|
||||||
|
|
||||||
|
CommittedLiveStateReadModel committedLiveState = store.BuildCommittedLiveStateReadModel();
|
||||||
|
Expect(!committedLiveState.layers.empty(), "committed live read model exposes current session layers");
|
||||||
|
const auto committedLayerIt = std::find_if(committedLiveState.layers.begin(), committedLiveState.layers.end(),
|
||||||
|
[&oscCommitSnapshot](const RuntimeStore::LayerPersistentState& layer) { return layer.id == oscCommitSnapshot.layerId; });
|
||||||
|
Expect(committedLayerIt != committedLiveState.layers.end(), "committed live read model preserves layer identity");
|
||||||
|
if (committedLayerIt != committedLiveState.layers.end())
|
||||||
|
{
|
||||||
|
const auto committedValueIt = committedLayerIt->parameterValues.find("gain");
|
||||||
|
Expect(committedValueIt != committedLayerIt->parameterValues.end() &&
|
||||||
|
!committedValueIt->second.numberValues.empty() &&
|
||||||
|
committedValueIt->second.numberValues[0] == 0.2,
|
||||||
|
"committed live read model includes session-only OSC commit value");
|
||||||
|
}
|
||||||
|
Expect(committedLiveState.packagesById.find("alpha") != committedLiveState.packagesById.end(),
|
||||||
|
"committed live read model carries package definitions for snapshot publication");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::filesystem::remove_all(root);
|
std::filesystem::remove_all(root);
|
||||||
|
|||||||
Reference in New Issue
Block a user