Phase 5 step 2
This commit is contained in:
@@ -100,13 +100,13 @@ std::vector<RuntimeRenderState> RenderFrameStateResolver::ComposeLayerStates(
|
||||
double smoothing,
|
||||
std::vector<RuntimeLiveOscCommitRequest>* commitRequests) const
|
||||
{
|
||||
RenderStateCompositionInput input;
|
||||
input.baseLayerStates = &baseStates;
|
||||
input.liveState = &liveState;
|
||||
input.allowLiveCommits = allowCommit;
|
||||
input.collectLiveCommitRequests = commitRequests != nullptr;
|
||||
input.liveSmoothing = smoothing;
|
||||
input.liveCommitDelay = kOscOverlayCommitDelay;
|
||||
LayeredRenderStateInput input;
|
||||
input.committedLiveLayerStates = &baseStates;
|
||||
input.transientAutomationOverlay = &liveState;
|
||||
input.allowTransientAutomationCommits = allowCommit;
|
||||
input.collectTransientAutomationCommitRequests = commitRequests != nullptr;
|
||||
input.transientAutomationSmoothing = smoothing;
|
||||
input.transientAutomationCommitDelay = kOscOverlayCommitDelay;
|
||||
input.now = std::chrono::steady_clock::now();
|
||||
const RenderStateCompositionResult result = mRenderStateComposer.BuildFrameState(input);
|
||||
|
||||
|
||||
@@ -1,24 +1,26 @@
|
||||
#include "RenderStateComposer.h"
|
||||
|
||||
RenderStateCompositionResult RenderStateComposer::BuildFrameState(const RenderStateCompositionInput& input) const
|
||||
RenderStateCompositionResult RenderStateComposer::BuildFrameState(const LayeredRenderStateInput& input) const
|
||||
{
|
||||
RenderStateCompositionResult result;
|
||||
if (!input.baseLayerStates)
|
||||
const std::vector<RuntimeRenderState>* layerStates =
|
||||
input.committedLiveLayerStates ? input.committedLiveLayerStates : input.basePersistedLayerStates;
|
||||
if (!layerStates)
|
||||
return result;
|
||||
|
||||
result.layerStates = *input.baseLayerStates;
|
||||
result.layerStates = *layerStates;
|
||||
result.hasLayerStates = !result.layerStates.empty();
|
||||
if (input.liveState)
|
||||
if (input.transientAutomationOverlay)
|
||||
{
|
||||
RuntimeLiveStateApplyOptions options;
|
||||
options.allowCommit = input.allowLiveCommits;
|
||||
options.smoothing = input.liveSmoothing;
|
||||
options.commitDelay = input.liveCommitDelay;
|
||||
options.allowCommit = input.allowTransientAutomationCommits;
|
||||
options.smoothing = input.transientAutomationSmoothing;
|
||||
options.commitDelay = input.transientAutomationCommitDelay;
|
||||
options.now = input.now;
|
||||
input.liveState->ApplyToLayerStates(
|
||||
input.transientAutomationOverlay->ApplyToLayerStates(
|
||||
result.layerStates,
|
||||
options,
|
||||
input.collectLiveCommitRequests ? &result.commitRequests : nullptr);
|
||||
input.collectTransientAutomationCommitRequests ? &result.commitRequests : nullptr);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -5,14 +5,15 @@
|
||||
#include <chrono>
|
||||
#include <vector>
|
||||
|
||||
struct RenderStateCompositionInput
|
||||
struct LayeredRenderStateInput
|
||||
{
|
||||
const std::vector<RuntimeRenderState>* baseLayerStates = nullptr;
|
||||
RuntimeLiveState* liveState = nullptr;
|
||||
bool allowLiveCommits = false;
|
||||
bool collectLiveCommitRequests = true;
|
||||
double liveSmoothing = 0.0;
|
||||
std::chrono::milliseconds liveCommitDelay = std::chrono::milliseconds(150);
|
||||
const std::vector<RuntimeRenderState>* basePersistedLayerStates = nullptr;
|
||||
const std::vector<RuntimeRenderState>* committedLiveLayerStates = nullptr;
|
||||
RuntimeLiveState* transientAutomationOverlay = nullptr;
|
||||
bool allowTransientAutomationCommits = false;
|
||||
bool collectTransientAutomationCommitRequests = true;
|
||||
double transientAutomationSmoothing = 0.0;
|
||||
std::chrono::milliseconds transientAutomationCommitDelay = std::chrono::milliseconds(150);
|
||||
std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
|
||||
};
|
||||
|
||||
@@ -26,5 +27,5 @@ struct RenderStateCompositionResult
|
||||
class RenderStateComposer
|
||||
{
|
||||
public:
|
||||
RenderStateCompositionResult BuildFrameState(const RenderStateCompositionInput& input) const;
|
||||
RenderStateCompositionResult BuildFrameState(const LayeredRenderStateInput& input) const;
|
||||
};
|
||||
|
||||
@@ -7,8 +7,8 @@ Phase 1 named the subsystems. Phase 2 added the typed event substrate. Phase 3 m
|
||||
## Status
|
||||
|
||||
- Phase 5 design package: proposed.
|
||||
- Phase 5 implementation: Step 1 started.
|
||||
- Current alignment: Phase 3 introduced the first pure composition boundary and transient OSC overlay owner, and Phase 5 now has a small `RuntimeStateLayerModel` inventory that names the current state categories. Committed runtime values are still physically stored through `RuntimeStore`/`LayerStackStore`, and transient OSC overlay state is still applied through render-facing helpers rather than through the final layered composition contract.
|
||||
- Phase 5 implementation: Step 2 started.
|
||||
- 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, and `RenderStateComposer` consumes a `LayeredRenderStateInput` whose fields make base persisted, committed live, and transient automation inputs explicit. Committed runtime values are still physically stored through `RuntimeStore`/`LayerStackStore`, and transient OSC overlay state is still applied through `RuntimeLiveState`.
|
||||
|
||||
Current live-state footholds:
|
||||
|
||||
@@ -16,7 +16,7 @@ Current live-state footholds:
|
||||
- `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.
|
||||
- `RuntimeLiveState` owns transient OSC overlay bookkeeping, smoothing, generation tracking, and commit-settlement policy.
|
||||
- `RenderStateComposer` combines base render states with live overlay state and returns final per-frame layer states plus settled commit requests.
|
||||
- `RenderStateComposer` consumes `LayeredRenderStateInput`, chooses committed-live layer states over base-persisted layer states when both are supplied, applies transient automation on top, and returns final per-frame layer states plus settled commit requests.
|
||||
- `RuntimeServiceLiveBridge` drains OSC ingress/completion queues and applies them to render live state during frame preparation.
|
||||
- `RuntimeStateLayerModel` names the Phase 5 state categories and classifies current fields as base persisted, committed live, transient automation, render-local, or health/config state.
|
||||
|
||||
@@ -246,19 +246,18 @@ Initial target:
|
||||
|
||||
### Step 2. Name The Layered Composition Input
|
||||
|
||||
Introduce a named composition input model around the current `RenderStateCompositionInput`.
|
||||
Introduce a named composition input model around the previous `RenderStateCompositionInput`.
|
||||
|
||||
Initial target:
|
||||
|
||||
- make base/committed/transient inputs visible in type names or field names
|
||||
- keep `RenderStateComposer` behavior unchanged at first
|
||||
- add tests that assert precedence with no GL
|
||||
- [x] make base/committed/transient inputs visible in type names or field names
|
||||
- [x] keep `RenderStateComposer` behavior unchanged at first
|
||||
- [x] add tests that assert precedence with no GL
|
||||
|
||||
Possible outcomes:
|
||||
|
||||
- evolve `RenderStateCompositionInput`
|
||||
- add a new `LayeredRenderStateInput`
|
||||
- add a thin adapter that feeds existing `RenderStateComposer`
|
||||
- [x] add a new `LayeredRenderStateInput`
|
||||
- [ ] add a thin adapter if a later migration needs compatibility with the previous input shape
|
||||
|
||||
### Step 3. Make Reset And Reload Policy Explicit
|
||||
|
||||
@@ -366,9 +365,9 @@ Render-local resources such as temporal history, feedback buffers, readback cach
|
||||
|
||||
Phase 5 can be considered complete once the project can say:
|
||||
|
||||
- [ ] persisted, committed-live, and transient automation layers are named in code or clear read models
|
||||
- [ ] final render-value precedence is explicit and covered by tests
|
||||
- [ ] `RenderStateComposer` or its replacement consumes a layered input contract
|
||||
- [x] persisted, committed-live, and transient automation layers are named in code or clear read models
|
||||
- [x] final render-value precedence is explicit and covered by tests
|
||||
- [x] `RenderStateComposer` or its replacement consumes a layered input contract
|
||||
- [ ] reset/reload/preset behavior for transient overlays is centralized or clearly delegated
|
||||
- [ ] OSC overlay settle/commit behavior is explicit, including persistence policy
|
||||
- [ ] `RuntimeStore` remains durable-state focused and does not absorb transient automation policy
|
||||
|
||||
@@ -359,12 +359,12 @@ void TestRenderStateComposerBuildsFrameState()
|
||||
update.targetValue = JsonValue(0.6);
|
||||
liveState.ApplyOscUpdates({ update });
|
||||
|
||||
RenderStateCompositionInput input;
|
||||
LayeredRenderStateInput input;
|
||||
std::vector<RuntimeRenderState> baseLayerStates = { MakeLayerState() };
|
||||
input.baseLayerStates = &baseLayerStates;
|
||||
input.liveState = &liveState;
|
||||
input.allowLiveCommits = false;
|
||||
input.liveSmoothing = 0.0;
|
||||
input.committedLiveLayerStates = &baseLayerStates;
|
||||
input.transientAutomationOverlay = &liveState;
|
||||
input.allowTransientAutomationCommits = false;
|
||||
input.transientAutomationSmoothing = 0.0;
|
||||
|
||||
RenderStateComposer composer;
|
||||
RenderStateCompositionResult result = composer.BuildFrameState(input);
|
||||
@@ -382,6 +382,49 @@ void TestRenderStateComposerBuildsFrameState()
|
||||
"composer leaves base layer states unchanged");
|
||||
}
|
||||
|
||||
void TestRenderStateComposerUsesCommittedLayerOverBaseLayer()
|
||||
{
|
||||
std::vector<RuntimeRenderState> basePersistedLayerStates = { MakeLayerState() };
|
||||
std::vector<RuntimeRenderState> committedLiveLayerStates = { MakeLayerState() };
|
||||
committedLiveLayerStates[0].parameterValues["amount"].numberValues = { 0.4 };
|
||||
|
||||
LayeredRenderStateInput input;
|
||||
input.basePersistedLayerStates = &basePersistedLayerStates;
|
||||
input.committedLiveLayerStates = &committedLiveLayerStates;
|
||||
|
||||
RenderStateComposer composer;
|
||||
RenderStateCompositionResult result = composer.BuildFrameState(input);
|
||||
|
||||
const auto valueIt = result.layerStates[0].parameterValues.find("amount");
|
||||
Expect(valueIt != result.layerStates[0].parameterValues.end() &&
|
||||
!valueIt->second.numberValues.empty() &&
|
||||
std::fabs(valueIt->second.numberValues[0] - 0.4) < 0.0001,
|
||||
"committed live layer overrides base persisted layer");
|
||||
const auto baseValueIt = basePersistedLayerStates[0].parameterValues.find("amount");
|
||||
Expect(baseValueIt != basePersistedLayerStates[0].parameterValues.end() &&
|
||||
!baseValueIt->second.numberValues.empty() &&
|
||||
std::fabs(baseValueIt->second.numberValues[0] - 0.25) < 0.0001,
|
||||
"committed override leaves base persisted layer unchanged");
|
||||
}
|
||||
|
||||
void TestRenderStateComposerUsesBaseLayerWhenCommittedLayerMissing()
|
||||
{
|
||||
std::vector<RuntimeRenderState> basePersistedLayerStates = { MakeLayerState() };
|
||||
|
||||
LayeredRenderStateInput input;
|
||||
input.basePersistedLayerStates = &basePersistedLayerStates;
|
||||
|
||||
RenderStateComposer composer;
|
||||
RenderStateCompositionResult result = composer.BuildFrameState(input);
|
||||
|
||||
Expect(result.hasLayerStates, "composer can use base persisted layer states without committed layer states");
|
||||
const auto valueIt = result.layerStates[0].parameterValues.find("amount");
|
||||
Expect(valueIt != result.layerStates[0].parameterValues.end() &&
|
||||
!valueIt->second.numberValues.empty() &&
|
||||
std::fabs(valueIt->second.numberValues[0] - 0.25) < 0.0001,
|
||||
"base persisted value is used when no committed live value exists");
|
||||
}
|
||||
|
||||
void TestRenderStateComposerQueuesCommitRequestsWhenEnabled()
|
||||
{
|
||||
RuntimeLiveState liveState;
|
||||
@@ -393,13 +436,13 @@ void TestRenderStateComposerQueuesCommitRequestsWhenEnabled()
|
||||
liveState.ApplyOscUpdates({ update });
|
||||
|
||||
std::vector<RuntimeRenderState> baseLayerStates = { MakeLayerState() };
|
||||
RenderStateCompositionInput input;
|
||||
input.baseLayerStates = &baseLayerStates;
|
||||
input.liveState = &liveState;
|
||||
input.allowLiveCommits = true;
|
||||
input.collectLiveCommitRequests = true;
|
||||
input.liveSmoothing = 0.0;
|
||||
input.liveCommitDelay = std::chrono::milliseconds(0);
|
||||
LayeredRenderStateInput input;
|
||||
input.committedLiveLayerStates = &baseLayerStates;
|
||||
input.transientAutomationOverlay = &liveState;
|
||||
input.allowTransientAutomationCommits = true;
|
||||
input.collectTransientAutomationCommitRequests = true;
|
||||
input.transientAutomationSmoothing = 0.0;
|
||||
input.transientAutomationCommitDelay = std::chrono::milliseconds(0);
|
||||
input.now = std::chrono::steady_clock::now() + std::chrono::milliseconds(1);
|
||||
|
||||
RenderStateComposer composer;
|
||||
@@ -421,13 +464,13 @@ void TestRenderStateComposerSuppressesCommitCollection()
|
||||
liveState.ApplyOscUpdates({ update });
|
||||
|
||||
std::vector<RuntimeRenderState> baseLayerStates = { MakeLayerState() };
|
||||
RenderStateCompositionInput input;
|
||||
input.baseLayerStates = &baseLayerStates;
|
||||
input.liveState = &liveState;
|
||||
input.allowLiveCommits = true;
|
||||
input.collectLiveCommitRequests = false;
|
||||
input.liveSmoothing = 0.0;
|
||||
input.liveCommitDelay = std::chrono::milliseconds(0);
|
||||
LayeredRenderStateInput input;
|
||||
input.committedLiveLayerStates = &baseLayerStates;
|
||||
input.transientAutomationOverlay = &liveState;
|
||||
input.allowTransientAutomationCommits = true;
|
||||
input.collectTransientAutomationCommitRequests = false;
|
||||
input.transientAutomationSmoothing = 0.0;
|
||||
input.transientAutomationCommitDelay = std::chrono::milliseconds(0);
|
||||
input.now = std::chrono::steady_clock::now() + std::chrono::milliseconds(1);
|
||||
|
||||
RenderStateComposer composer;
|
||||
@@ -454,6 +497,8 @@ int main()
|
||||
TestRuntimeLiveStateSmoothingVectorSizeMismatchUsesTargetShape();
|
||||
TestRuntimeLiveStateTriggerOverlayIncrementsAndClears();
|
||||
TestRenderStateComposerBuildsFrameState();
|
||||
TestRenderStateComposerUsesCommittedLayerOverBaseLayer();
|
||||
TestRenderStateComposerUsesBaseLayerWhenCommittedLayerMissing();
|
||||
TestRenderStateComposerQueuesCommitRequestsWhenEnabled();
|
||||
TestRenderStateComposerSuppressesCommitCollection();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user