step 3
All checks were successful
CI / React UI Build (push) Successful in 11s
CI / Native Windows Build And Tests (push) Successful in 2m40s
CI / Windows Release Package (push) Successful in 2m44s

This commit is contained in:
Aiden
2026-05-11 19:05:29 +10:00
parent 7740fe209c
commit 718e4dcadd
16 changed files with 282 additions and 13 deletions

View File

@@ -155,6 +155,40 @@ void ControlServices::ClearOscState()
}
}
void ControlServices::ClearOscStateForLayerKey(const std::string& layerKey)
{
{
std::lock_guard<std::mutex> lock(mPendingOscMutex);
for (auto it = mPendingOscUpdates.begin(); it != mPendingOscUpdates.end();)
{
if (it->second.layerKey == layerKey)
it = mPendingOscUpdates.erase(it);
else
++it;
}
}
{
std::lock_guard<std::mutex> lock(mPendingOscCommitMutex);
for (auto it = mPendingOscCommits.begin(); it != mPendingOscCommits.end();)
{
if (it->second.layerKey == layerKey)
it = mPendingOscCommits.erase(it);
else
++it;
}
}
{
std::lock_guard<std::mutex> lock(mCompletedOscCommitMutex);
for (auto it = mCompletedOscCommits.begin(); it != mCompletedOscCommits.end();)
{
if (it->routeKey.rfind(layerKey + "\n", 0) == 0)
it = mCompletedOscCommits.erase(it);
else
++it;
}
}
}
void ControlServices::ConsumeCompletedOscCommits(std::vector<CompletedOscCommit>& completedCommits)
{
completedCommits.clear();

View File

@@ -49,6 +49,7 @@ public:
bool ApplyPendingOscUpdates(std::vector<AppliedOscUpdate>& appliedUpdates, std::string& error);
bool QueueOscCommit(const std::string& routeKey, const std::string& layerKey, const std::string& parameterKey, const JsonValue& value, uint64_t generation, std::string& error);
void ClearOscState();
void ClearOscStateForLayerKey(const std::string& layerKey);
void ConsumeCompletedOscCommits(std::vector<CompletedOscCommit>& completedCommits);
private:

View File

@@ -68,6 +68,12 @@ void RuntimeServices::ClearOscState()
mControlServices->ClearOscState();
}
void RuntimeServices::ClearOscStateForLayerKey(const std::string& layerKey)
{
if (mControlServices)
mControlServices->ClearOscStateForLayerKey(layerKey);
}
void RuntimeServices::ConsumeCompletedOscCommits(std::vector<CompletedOscCommit>& completedCommits)
{
if (!mControlServices)

View File

@@ -27,6 +27,7 @@ public:
bool ApplyPendingOscUpdates(std::vector<AppliedOscUpdate>& appliedUpdates, std::string& error);
bool QueueOscCommit(const std::string& routeKey, const std::string& layerKey, const std::string& parameterKey, const JsonValue& value, uint64_t generation, std::string& error);
void ClearOscState();
void ClearOscStateForLayerKey(const std::string& layerKey);
void ConsumeCompletedOscCommits(std::vector<CompletedOscCommit>& completedCommits);
private:

View File

@@ -415,7 +415,16 @@ void RenderEngine::ProcessScreenshotCaptureCommandsOnRenderThread()
void RenderEngine::ClearOscOverlayState()
{
mRuntimeLiveState.Clear();
InvokeOnRenderThread([this]() {
mRuntimeLiveState.Clear();
});
}
void RenderEngine::ClearOscOverlayStateForLayerKey(const std::string& layerKey)
{
InvokeOnRenderThread([this, layerKey]() {
mRuntimeLiveState.ClearForLayerKey(layerKey);
});
}
void RenderEngine::UpdateOscOverlayState(

View File

@@ -95,6 +95,7 @@ public:
void ResetShaderFeedbackState();
void ApplyRuntimeCoordinatorRenderReset(RuntimeCoordinatorRenderResetScope resetScope);
void ClearOscOverlayState();
void ClearOscOverlayStateForLayerKey(const std::string& layerKey);
void UpdateOscOverlayState(
const std::vector<OscOverlayUpdate>& updates,
const std::vector<OscOverlayCommitCompletion>& completedCommits);

View File

@@ -85,10 +85,19 @@ bool RuntimeUpdateController::ApplyRuntimeCoordinatorResult(const RuntimeCoordin
mRuntimeCoordinator.ApplyCommittedStateMode(result.committedStateMode);
if (result.clearTransientOscState)
switch (result.transientOscInvalidation)
{
case RuntimeCoordinatorTransientOscInvalidation::All:
mRenderEngine.ClearOscOverlayState();
mRuntimeServices.ClearOscState();
break;
case RuntimeCoordinatorTransientOscInvalidation::Layer:
mRenderEngine.ClearOscOverlayStateForLayerKey(result.transientOscLayerKey);
mRuntimeServices.ClearOscStateForLayerKey(result.transientOscLayerKey);
break;
case RuntimeCoordinatorTransientOscInvalidation::None:
default:
break;
}
mRenderEngine.ApplyRuntimeCoordinatorRenderReset(result.renderResetScope);

View File

@@ -56,6 +56,11 @@ RuntimeCoordinatorResult RuntimeCoordinator::RemoveLayer(const std::string& laye
}
RuntimeCoordinatorResult result = ApplyStoreMutation(mRuntimeStore.DeleteStoredLayer(layerId, error), error, true, true, true);
if (result.accepted)
{
result.transientOscInvalidation = RuntimeCoordinatorTransientOscInvalidation::Layer;
result.transientOscLayerKey = layerId;
}
PublishCoordinatorResult("RemoveLayer", result);
return result;
}
@@ -205,7 +210,8 @@ RuntimeCoordinatorResult RuntimeCoordinator::ResetLayerParameters(const std::str
return result;
}
result.clearTransientOscState = true;
result.transientOscInvalidation = RuntimeCoordinatorTransientOscInvalidation::Layer;
result.transientOscLayerKey = layerId;
result.renderResetScope = RuntimeCoordinatorRenderResetScope::TemporalHistoryAndFeedback;
PublishCoordinatorResult("ResetLayerParameters", result);
return result;
@@ -538,7 +544,7 @@ void RuntimeCoordinator::PublishCoordinatorResult(const std::string& action, con
mutation.runtimeStateBroadcastRequired = result.runtimeStateBroadcastRequired;
mutation.shaderBuildRequested = result.shaderBuildRequested;
mutation.persistenceRequested = result.persistenceRequested;
mutation.clearTransientOscState = result.clearTransientOscState;
mutation.clearTransientOscState = result.transientOscInvalidation != RuntimeCoordinatorTransientOscInvalidation::None;
mutation.renderResetScope = ToRuntimeEventRenderResetScope(result.renderResetScope);
mutation.errorMessage = result.errorMessage;
mRuntimeEventDispatcher.PublishPayload(mutation, "RuntimeCoordinator");

View File

@@ -25,18 +25,26 @@ enum class RuntimeCoordinatorRenderResetScope
TemporalHistoryAndFeedback
};
enum class RuntimeCoordinatorTransientOscInvalidation
{
None,
Layer,
All
};
struct RuntimeCoordinatorResult
{
bool accepted = false;
bool runtimeStateBroadcastRequired = false;
bool shaderBuildRequested = false;
bool persistenceRequested = false;
bool clearTransientOscState = false;
bool compileStatusChanged = false;
bool compileStatusSucceeded = false;
bool clearReloadRequest = false;
RuntimeCoordinatorCommittedStateMode committedStateMode = RuntimeCoordinatorCommittedStateMode::Unchanged;
RuntimeCoordinatorRenderResetScope renderResetScope = RuntimeCoordinatorRenderResetScope::None;
RuntimeCoordinatorTransientOscInvalidation transientOscInvalidation = RuntimeCoordinatorTransientOscInvalidation::None;
std::string transientOscLayerKey;
std::string compileStatusMessage;
std::string errorMessage;
};

View File

@@ -74,6 +74,7 @@ JsonValue BuildOscCommitValue(const ShaderParameterDefinition& definition, const
return JsonValue();
}
}
void RuntimeLiveState::Clear()
@@ -81,6 +82,47 @@ void RuntimeLiveState::Clear()
mOscOverlayStates.clear();
}
void RuntimeLiveState::ClearForLayerKey(const std::string& layerKey)
{
for (auto it = mOscOverlayStates.begin(); it != mOscOverlayStates.end();)
{
if (OverlayMatchesLayerKey(it->second, layerKey))
it = mOscOverlayStates.erase(it);
else
++it;
}
}
bool RuntimeLiveState::OverlayMatchesLayerKey(const OscOverlayState& overlay, const std::string& layerKey)
{
return MatchesOscControlKey(overlay.layerKey, layerKey);
}
bool RuntimeLiveState::TryResolveOverlayTarget(
const OscOverlayState& overlay,
const std::vector<RuntimeRenderState>& states,
std::vector<RuntimeRenderState>::const_iterator& stateIt,
std::vector<ShaderParameterDefinition>::const_iterator& definitionIt)
{
stateIt = std::find_if(states.begin(), states.end(),
[&overlay](const RuntimeRenderState& state)
{
return MatchesOscControlKey(state.layerId, overlay.layerKey) ||
MatchesOscControlKey(state.shaderId, overlay.layerKey) ||
MatchesOscControlKey(state.shaderName, overlay.layerKey);
});
if (stateIt == states.end())
return false;
definitionIt = std::find_if(stateIt->parameterDefinitions.begin(), stateIt->parameterDefinitions.end(),
[&overlay](const ShaderParameterDefinition& definition)
{
return MatchesOscControlKey(definition.id, overlay.parameterKey) ||
MatchesOscControlKey(definition.label, overlay.parameterKey);
});
return definitionIt != stateIt->parameterDefinitions.end();
}
std::size_t RuntimeLiveState::OverlayCount() const
{
return mOscOverlayStates.size();
@@ -131,6 +173,27 @@ void RuntimeLiveState::ApplyOscCommitCompletions(const std::vector<RuntimeLiveOs
}
}
void RuntimeLiveState::PruneIncompatibleOverlays(const std::vector<RuntimeRenderState>& states)
{
for (auto it = mOscOverlayStates.begin(); it != mOscOverlayStates.end();)
{
std::vector<RuntimeRenderState>::const_iterator stateIt;
std::vector<ShaderParameterDefinition>::const_iterator definitionIt;
if (TryResolveOverlayTarget(it->second, states, stateIt, definitionIt))
{
ShaderParameterValue targetValue;
std::string normalizeError;
if (NormalizeAndValidateParameterValue(*definitionIt, it->second.targetValue, targetValue, normalizeError))
{
++it;
continue;
}
}
it = mOscOverlayStates.erase(it);
}
}
void RuntimeLiveState::ApplyToLayerStates(
std::vector<RuntimeRenderState>& states,
const RuntimeLiveStateApplyOptions& options,
@@ -139,6 +202,10 @@ void RuntimeLiveState::ApplyToLayerStates(
if (states.empty() || mOscOverlayStates.empty())
return;
PruneIncompatibleOverlays(states);
if (mOscOverlayStates.empty())
return;
const auto now = options.now;
const double clampedSmoothing = ClampOscAlpha(options.smoothing);
std::vector<std::string> overlayKeysToRemove;

View File

@@ -44,9 +44,11 @@ class RuntimeLiveState
{
public:
void Clear();
void ClearForLayerKey(const std::string& layerKey);
std::size_t OverlayCount() const;
void ApplyOscUpdates(const std::vector<RuntimeLiveOscUpdate>& updates);
void ApplyOscCommitCompletions(const std::vector<RuntimeLiveOscCommitCompletion>& completedCommits);
void PruneIncompatibleOverlays(const std::vector<RuntimeRenderState>& states);
void ApplyToLayerStates(
std::vector<RuntimeRenderState>& states,
const RuntimeLiveStateApplyOptions& options,
@@ -67,5 +69,12 @@ private:
bool commitQueued = false;
};
static bool OverlayMatchesLayerKey(const OscOverlayState& overlay, const std::string& layerKey);
static bool TryResolveOverlayTarget(
const OscOverlayState& overlay,
const std::vector<RuntimeRenderState>& states,
std::vector<RuntimeRenderState>::const_iterator& stateIt,
std::vector<ShaderParameterDefinition>::const_iterator& definitionIt);
std::map<std::string, OscOverlayState> mOscOverlayStates;
};