pass 1
All checks were successful
CI / React UI Build (push) Successful in 11s
CI / Native Windows Build And Tests (push) Successful in 2m39s
CI / Windows Release Package (push) Successful in 2m45s

This commit is contained in:
Aiden
2026-05-11 01:12:24 +10:00
parent 53e78890a8
commit c4883d3413
16 changed files with 618 additions and 303 deletions

View File

@@ -2,6 +2,9 @@
#include "RuntimeStore.h"
#include <algorithm>
#include <chrono>
RuntimeCoordinator::RuntimeCoordinator(RuntimeStore& runtimeStore) :
mRuntimeStore(runtimeStore)
{
@@ -9,55 +12,110 @@ RuntimeCoordinator::RuntimeCoordinator(RuntimeStore& runtimeStore) :
RuntimeCoordinatorResult RuntimeCoordinator::AddLayer(const std::string& shaderId)
{
std::lock_guard<std::mutex> lock(mMutex);
std::string error;
if (!ValidateShaderExists(shaderId, error))
return ApplyStoreMutation(false, error, false, false);
return ApplyStoreMutation(mRuntimeStore.CreateStoredLayer(shaderId, error), error, true, true);
}
RuntimeCoordinatorResult RuntimeCoordinator::RemoveLayer(const std::string& layerId)
{
std::lock_guard<std::mutex> lock(mMutex);
std::string error;
if (!ValidateLayerExists(layerId, error))
return ApplyStoreMutation(false, error, false, false);
return ApplyStoreMutation(mRuntimeStore.DeleteStoredLayer(layerId, error), error, true, true);
}
RuntimeCoordinatorResult RuntimeCoordinator::MoveLayer(const std::string& layerId, int direction)
{
std::lock_guard<std::mutex> lock(mMutex);
std::string error;
bool shouldMove = false;
if (!ResolveLayerMove(layerId, direction, shouldMove, error))
return ApplyStoreMutation(false, error, false, false);
if (!shouldMove)
return BuildAcceptedNoReloadResult();
return ApplyStoreMutation(mRuntimeStore.MoveStoredLayer(layerId, direction, error), error, true, true);
}
RuntimeCoordinatorResult RuntimeCoordinator::MoveLayerToIndex(const std::string& layerId, std::size_t targetIndex)
{
std::lock_guard<std::mutex> lock(mMutex);
std::string error;
bool shouldMove = false;
if (!ResolveLayerMoveToIndex(layerId, targetIndex, shouldMove, error))
return ApplyStoreMutation(false, error, false, false);
if (!shouldMove)
return BuildAcceptedNoReloadResult();
return ApplyStoreMutation(mRuntimeStore.MoveStoredLayerToIndex(layerId, targetIndex, error), error, true, true);
}
RuntimeCoordinatorResult RuntimeCoordinator::SetLayerBypass(const std::string& layerId, bool bypassed)
{
std::lock_guard<std::mutex> lock(mMutex);
std::string error;
if (!ValidateLayerExists(layerId, error))
return ApplyStoreMutation(false, error, false, false);
return ApplyStoreMutation(mRuntimeStore.SetStoredLayerBypassState(layerId, bypassed, error), error, true, false);
}
RuntimeCoordinatorResult RuntimeCoordinator::SetLayerShader(const std::string& layerId, const std::string& shaderId)
{
std::lock_guard<std::mutex> lock(mMutex);
std::string error;
if (!ValidateLayerExists(layerId, error) || !ValidateShaderExists(shaderId, error))
return ApplyStoreMutation(false, error, false, false);
return ApplyStoreMutation(mRuntimeStore.SetStoredLayerShaderSelection(layerId, shaderId, error), error, true, false);
}
RuntimeCoordinatorResult RuntimeCoordinator::UpdateLayerParameter(const std::string& layerId, const std::string& parameterId, const JsonValue& newValue)
{
std::lock_guard<std::mutex> lock(mMutex);
std::string error;
return ApplyStoreMutation(mRuntimeStore.SetStoredParameterValue(layerId, parameterId, newValue, error), error, false, false);
ResolvedParameterMutation mutation;
if (!BuildParameterMutationById(layerId, parameterId, newValue, true, mutation, error))
return ApplyStoreMutation(false, error, false, false);
return ApplyStoreMutation(mRuntimeStore.SetStoredParameterValue(mutation.layerId, mutation.parameterId, mutation.value, mutation.persistState, error), error, false, false);
}
RuntimeCoordinatorResult RuntimeCoordinator::UpdateLayerParameterByControlKey(const std::string& layerKey, const std::string& parameterKey, const JsonValue& newValue)
{
std::lock_guard<std::mutex> lock(mMutex);
std::string error;
return ApplyStoreMutation(mRuntimeStore.SetStoredParameterValueByControlKey(layerKey, parameterKey, newValue, error), error, false, false);
ResolvedParameterMutation mutation;
if (!BuildParameterMutationByControlKey(layerKey, parameterKey, newValue, true, mutation, error))
return ApplyStoreMutation(false, error, false, false);
return ApplyStoreMutation(mRuntimeStore.SetStoredParameterValue(mutation.layerId, mutation.parameterId, mutation.value, mutation.persistState, error), error, false, false);
}
RuntimeCoordinatorResult RuntimeCoordinator::CommitOscParameterByControlKey(const std::string& layerKey, const std::string& parameterKey, const JsonValue& newValue)
{
std::lock_guard<std::mutex> lock(mMutex);
std::string error;
ResolvedParameterMutation mutation;
if (!BuildParameterMutationByControlKey(layerKey, parameterKey, newValue, false, mutation, error))
return ApplyStoreMutation(false, error, false, false);
return ApplyStoreMutation(mRuntimeStore.SetStoredParameterValue(mutation.layerId, mutation.parameterId, mutation.value, mutation.persistState, error), error, false, false);
}
RuntimeCoordinatorResult RuntimeCoordinator::ResetLayerParameters(const std::string& layerId)
{
std::lock_guard<std::mutex> lock(mMutex);
std::string error;
if (!ValidateLayerExists(layerId, error))
return ApplyStoreMutation(false, error, false, false);
RuntimeCoordinatorResult result = ApplyStoreMutation(mRuntimeStore.ResetStoredLayerParameterValues(layerId, error), error, false, false);
if (!result.accepted)
return result;
@@ -69,21 +127,51 @@ RuntimeCoordinatorResult RuntimeCoordinator::ResetLayerParameters(const std::str
RuntimeCoordinatorResult RuntimeCoordinator::SaveStackPreset(const std::string& presetName)
{
std::lock_guard<std::mutex> lock(mMutex);
std::string error;
if (!ValidatePresetName(presetName, error))
return ApplyStoreMutation(false, error, false, false);
return ApplyStoreMutation(mRuntimeStore.SaveStackPresetSnapshot(presetName, error), error, false, false);
}
RuntimeCoordinatorResult RuntimeCoordinator::LoadStackPreset(const std::string& presetName)
{
std::lock_guard<std::mutex> lock(mMutex);
std::string error;
if (!ValidatePresetName(presetName, error))
return ApplyStoreMutation(false, error, false, false);
return ApplyStoreMutation(mRuntimeStore.LoadStackPresetSnapshot(presetName, error), error, true, false);
}
RuntimeCoordinatorResult RuntimeCoordinator::RequestShaderReload(bool preserveFeedbackState)
{
std::lock_guard<std::mutex> lock(mMutex);
return BuildQueuedReloadResult(preserveFeedbackState);
}
RuntimeCoordinatorResult RuntimeCoordinator::PollRuntimeStoreChanges(bool& registryChanged)
{
std::lock_guard<std::mutex> lock(mMutex);
registryChanged = false;
bool reloadRequested = false;
std::string error;
if (!mRuntimeStore.PollStoredFileChanges(registryChanged, reloadRequested, error))
return HandleRuntimePollFailure(error);
if (reloadRequested)
return BuildQueuedReloadResult(false);
if (registryChanged)
return BuildAcceptedNoReloadResult();
RuntimeCoordinatorResult result;
result.accepted = true;
return result;
}
RuntimeCoordinatorResult RuntimeCoordinator::HandleRuntimePollFailure(const std::string& error)
{
RuntimeCoordinatorResult result;
@@ -97,6 +185,7 @@ RuntimeCoordinatorResult RuntimeCoordinator::HandleRuntimePollFailure(const std:
RuntimeCoordinatorResult RuntimeCoordinator::HandlePreparedShaderBuildFailure(const std::string& error)
{
std::lock_guard<std::mutex> lock(mMutex);
mPreserveFeedbackOnNextShaderBuild = false;
mUseCommittedLayerStates = true;
@@ -112,6 +201,7 @@ RuntimeCoordinatorResult RuntimeCoordinator::HandlePreparedShaderBuildFailure(co
RuntimeCoordinatorResult RuntimeCoordinator::HandlePreparedShaderBuildSuccess()
{
std::lock_guard<std::mutex> lock(mMutex);
mUseCommittedLayerStates = false;
RuntimeCoordinatorResult result;
@@ -127,11 +217,13 @@ RuntimeCoordinatorResult RuntimeCoordinator::HandlePreparedShaderBuildSuccess()
RuntimeCoordinatorResult RuntimeCoordinator::HandleRuntimeReloadRequest()
{
std::lock_guard<std::mutex> lock(mMutex);
return BuildQueuedReloadResult(false);
}
void RuntimeCoordinator::ApplyCommittedStateMode(RuntimeCoordinatorCommittedStateMode mode)
{
std::lock_guard<std::mutex> lock(mMutex);
switch (mode)
{
case RuntimeCoordinatorCommittedStateMode::UseCommittedStates:
@@ -153,9 +245,158 @@ bool RuntimeCoordinator::UseCommittedLayerStates() const
bool RuntimeCoordinator::PreserveFeedbackOnNextShaderBuild() const
{
std::lock_guard<std::mutex> lock(mMutex);
return mPreserveFeedbackOnNextShaderBuild;
}
bool RuntimeCoordinator::BuildParameterMutationById(const std::string& layerId, const std::string& parameterId, const JsonValue& newValue,
bool persistState, ResolvedParameterMutation& mutation, std::string& error) const
{
std::lock_guard<std::mutex> lock(mRuntimeStore.mRuntimeHost.mMutex);
RuntimeHost::LayerPersistentState* layer = mRuntimeStore.mRuntimeHost.FindLayerById(layerId);
if (!layer)
{
error = "Unknown layer id: " + layerId;
return false;
}
auto shaderIt = mRuntimeStore.mRuntimeHost.mPackagesById.find(layer->shaderId);
if (shaderIt == mRuntimeStore.mRuntimeHost.mPackagesById.end())
{
error = "Unknown shader id: " + layer->shaderId;
return false;
}
auto parameterIt = std::find_if(shaderIt->second.parameters.begin(), shaderIt->second.parameters.end(),
[&parameterId](const ShaderParameterDefinition& definition) { return definition.id == parameterId; });
if (parameterIt == shaderIt->second.parameters.end())
{
error = "Unknown parameter id: " + parameterId;
return false;
}
return BuildParameterMutationLocked(*layer, *parameterIt, newValue, persistState, mutation, error);
}
bool RuntimeCoordinator::BuildParameterMutationByControlKey(const std::string& layerKey, const std::string& parameterKey, const JsonValue& newValue,
bool persistState, ResolvedParameterMutation& mutation, std::string& error) const
{
std::lock_guard<std::mutex> lock(mRuntimeStore.mRuntimeHost.mMutex);
RuntimeHost::LayerPersistentState* matchedLayer = nullptr;
const ShaderPackage* matchedPackage = nullptr;
std::vector<ShaderParameterDefinition>::const_iterator parameterIt;
if (!mRuntimeStore.TryResolveStoredLayerAndParameterByControlKeyLocked(layerKey, parameterKey, matchedLayer, matchedPackage, parameterIt, error))
return false;
return BuildParameterMutationLocked(*matchedLayer, *parameterIt, newValue, persistState, mutation, error);
}
bool RuntimeCoordinator::BuildParameterMutationLocked(RuntimeHost::LayerPersistentState& layer, const ShaderParameterDefinition& definition, const JsonValue& newValue,
bool persistState, ResolvedParameterMutation& mutation, std::string& error) const
{
mutation.layerId = layer.id;
mutation.parameterId = definition.id;
mutation.persistState = persistState;
if (definition.type == ShaderParameterType::Trigger)
{
const auto existingValue = layer.parameterValues.find(definition.id);
const double previousCount = existingValue == layer.parameterValues.end() || existingValue->second.numberValues.empty()
? 0.0
: existingValue->second.numberValues[0];
const double triggerTime = std::chrono::duration_cast<std::chrono::duration<double>>(
std::chrono::steady_clock::now() - mRuntimeStore.mRuntimeHost.mStartTime).count();
mutation.value.numberValues = { previousCount + 1.0, triggerTime };
mutation.persistState = false;
return true;
}
return mRuntimeStore.mRuntimeHost.NormalizeAndValidateValue(definition, newValue, mutation.value, error);
}
bool RuntimeCoordinator::HasLayerLocked(const std::string& layerId) const
{
return mRuntimeStore.mRuntimeHost.FindLayerById(layerId) != nullptr;
}
bool RuntimeCoordinator::HasShaderLocked(const std::string& shaderId) const
{
return mRuntimeStore.mRuntimeHost.mPackagesById.find(shaderId) != mRuntimeStore.mRuntimeHost.mPackagesById.end();
}
bool RuntimeCoordinator::ValidateLayerExists(const std::string& layerId, std::string& error) const
{
std::lock_guard<std::mutex> lock(mRuntimeStore.mRuntimeHost.mMutex);
if (HasLayerLocked(layerId))
return true;
error = "Unknown layer id: " + layerId;
return false;
}
bool RuntimeCoordinator::ValidateShaderExists(const std::string& shaderId, std::string& error) const
{
std::lock_guard<std::mutex> lock(mRuntimeStore.mRuntimeHost.mMutex);
if (HasShaderLocked(shaderId))
return true;
error = "Unknown shader id: " + shaderId;
return false;
}
bool RuntimeCoordinator::ResolveLayerMove(const std::string& layerId, int direction, bool& shouldMove, std::string& error) const
{
std::lock_guard<std::mutex> lock(mRuntimeStore.mRuntimeHost.mMutex);
const auto& layers = mRuntimeStore.mRuntimeHost.mPersistentState.layers;
auto it = std::find_if(layers.begin(), layers.end(),
[&layerId](const RuntimeHost::LayerPersistentState& layer) { return layer.id == layerId; });
if (it == layers.end())
{
error = "Unknown layer id: " + layerId;
return false;
}
const std::ptrdiff_t index = std::distance(layers.begin(), it);
const std::ptrdiff_t newIndex = index + direction;
shouldMove = newIndex >= 0 && newIndex < static_cast<std::ptrdiff_t>(layers.size()) && newIndex != index;
return true;
}
bool RuntimeCoordinator::ResolveLayerMoveToIndex(const std::string& layerId, std::size_t targetIndex, bool& shouldMove, std::string& error) const
{
std::lock_guard<std::mutex> lock(mRuntimeStore.mRuntimeHost.mMutex);
const auto& layers = mRuntimeStore.mRuntimeHost.mPersistentState.layers;
auto it = std::find_if(layers.begin(), layers.end(),
[&layerId](const RuntimeHost::LayerPersistentState& layer) { return layer.id == layerId; });
if (it == layers.end())
{
error = "Unknown layer id: " + layerId;
return false;
}
if (layers.empty())
{
shouldMove = false;
return true;
}
const std::size_t clampedTargetIndex = (std::min)(targetIndex, layers.size() - 1);
const std::size_t sourceIndex = static_cast<std::size_t>(std::distance(layers.begin(), it));
shouldMove = sourceIndex != clampedTargetIndex;
return true;
}
bool RuntimeCoordinator::ValidatePresetName(const std::string& presetName, std::string& error) const
{
if (!mRuntimeStore.MakeSafePresetFileStem(presetName).empty())
return true;
error = "Preset name must include at least one letter or number.";
return false;
}
RuntimeCoordinatorResult RuntimeCoordinator::ApplyStoreMutation(bool succeeded, const std::string& errorMessage, bool reloadRequired, bool preserveFeedbackState)
{
if (!succeeded)

View File

@@ -1,9 +1,11 @@
#pragma once
#include "RuntimeHost.h"
#include "RuntimeJson.h"
#include <atomic>
#include <cstddef>
#include <mutex>
#include <string>
class RuntimeStore;
@@ -50,11 +52,13 @@ public:
RuntimeCoordinatorResult SetLayerShader(const std::string& layerId, const std::string& shaderId);
RuntimeCoordinatorResult UpdateLayerParameter(const std::string& layerId, const std::string& parameterId, const JsonValue& newValue);
RuntimeCoordinatorResult UpdateLayerParameterByControlKey(const std::string& layerKey, const std::string& parameterKey, const JsonValue& newValue);
RuntimeCoordinatorResult CommitOscParameterByControlKey(const std::string& layerKey, const std::string& parameterKey, const JsonValue& newValue);
RuntimeCoordinatorResult ResetLayerParameters(const std::string& layerId);
RuntimeCoordinatorResult SaveStackPreset(const std::string& presetName);
RuntimeCoordinatorResult LoadStackPreset(const std::string& presetName);
RuntimeCoordinatorResult RequestShaderReload(bool preserveFeedbackState = false);
RuntimeCoordinatorResult PollRuntimeStoreChanges(bool& registryChanged);
RuntimeCoordinatorResult HandleRuntimePollFailure(const std::string& error);
RuntimeCoordinatorResult HandlePreparedShaderBuildFailure(const std::string& error);
RuntimeCoordinatorResult HandlePreparedShaderBuildSuccess();
@@ -64,11 +68,33 @@ public:
bool PreserveFeedbackOnNextShaderBuild() const;
private:
struct ResolvedParameterMutation
{
std::string layerId;
std::string parameterId;
ShaderParameterValue value;
bool persistState = true;
};
bool BuildParameterMutationById(const std::string& layerId, const std::string& parameterId, const JsonValue& newValue,
bool persistState, ResolvedParameterMutation& mutation, std::string& error) const;
bool BuildParameterMutationByControlKey(const std::string& layerKey, const std::string& parameterKey, const JsonValue& newValue,
bool persistState, ResolvedParameterMutation& mutation, std::string& error) const;
bool BuildParameterMutationLocked(RuntimeHost::LayerPersistentState& layer, const ShaderParameterDefinition& definition, const JsonValue& newValue,
bool persistState, ResolvedParameterMutation& mutation, std::string& error) const;
bool HasLayerLocked(const std::string& layerId) const;
bool HasShaderLocked(const std::string& shaderId) const;
bool ValidateLayerExists(const std::string& layerId, std::string& error) const;
bool ValidateShaderExists(const std::string& shaderId, std::string& error) const;
bool ResolveLayerMove(const std::string& layerId, int direction, bool& shouldMove, std::string& error) const;
bool ResolveLayerMoveToIndex(const std::string& layerId, std::size_t targetIndex, bool& shouldMove, std::string& error) const;
bool ValidatePresetName(const std::string& presetName, std::string& error) const;
RuntimeCoordinatorResult ApplyStoreMutation(bool succeeded, const std::string& errorMessage, bool reloadRequired, bool preserveFeedbackState);
RuntimeCoordinatorResult BuildQueuedReloadResult(bool preserveFeedbackState);
RuntimeCoordinatorResult BuildAcceptedNoReloadResult() const;
RuntimeStore& mRuntimeStore;
mutable std::mutex mMutex;
bool mPreserveFeedbackOnNextShaderBuild = false;
std::atomic<bool> mUseCommittedLayerStates{ false };
};

View File

@@ -14,8 +14,6 @@
#include <vector>
class RuntimeStore;
class RuntimeSnapshotProvider;
class RuntimeHost
{
public:
@@ -71,7 +69,7 @@ private:
private:
friend class RuntimeStore;
friend class RuntimeSnapshotProvider;
friend class RuntimeCoordinator;
HealthTelemetry mHealthTelemetry;
mutable std::mutex mMutex;
AppConfig mConfig;

View File

@@ -1,14 +1,12 @@
#include "RuntimeSnapshotProvider.h"
#include "RuntimeClock.h"
#include "ShaderCompiler.h"
#include <algorithm>
#include <mutex>
#include <filesystem>
#include <utility>
RuntimeSnapshotProvider::RuntimeSnapshotProvider(RuntimeHost& runtimeHost) :
mRuntimeHost(runtimeHost)
RuntimeSnapshotProvider::RuntimeSnapshotProvider(RuntimeStore& runtimeStore) :
mRuntimeStore(runtimeStore)
{
}
@@ -17,30 +15,22 @@ bool RuntimeSnapshotProvider::BuildLayerPassFragmentShaderSources(const std::str
try
{
ShaderPackage shaderPackage;
{
std::lock_guard<std::mutex> lock(mRuntimeHost.mMutex);
const RuntimeHost::LayerPersistentState* layer = mRuntimeHost.FindLayerById(layerId);
if (!layer)
{
error = "Unknown layer id: " + layerId;
return false;
}
if (!mRuntimeStore.CopyShaderPackageForStoredLayer(layerId, shaderPackage, error))
return false;
auto it = mRuntimeHost.mPackagesById.find(layer->shaderId);
if (it == mRuntimeHost.mPackagesById.end())
{
error = "Unknown shader id: " + layer->shaderId;
return false;
}
shaderPackage = it->second;
}
std::filesystem::path repoRoot;
std::filesystem::path wrapperPath;
std::filesystem::path generatedGlslPath;
std::filesystem::path patchedGlslPath;
unsigned maxTemporalHistoryFrames = 0;
mRuntimeStore.GetShaderCompilerInputs(repoRoot, wrapperPath, generatedGlslPath, patchedGlslPath, maxTemporalHistoryFrames);
ShaderCompiler compiler(
mRuntimeHost.mRepoRoot,
mRuntimeHost.mWrapperPath,
mRuntimeHost.mGeneratedGlslPath,
mRuntimeHost.mPatchedGlslPath,
mRuntimeHost.mConfig.maxTemporalHistoryFrames);
repoRoot,
wrapperPath,
generatedGlslPath,
patchedGlslPath,
maxTemporalHistoryFrames);
passSources.clear();
passSources.reserve(shaderPackage.passes.size());
for (const ShaderPassDefinition& pass : shaderPackage.passes)
@@ -69,20 +59,20 @@ bool RuntimeSnapshotProvider::BuildLayerPassFragmentShaderSources(const std::str
unsigned RuntimeSnapshotProvider::GetMaxTemporalHistoryFrames() const
{
return mRuntimeHost.mConfig.maxTemporalHistoryFrames;
return mRuntimeStore.GetConfiguredMaxTemporalHistoryFrames();
}
RuntimeSnapshotVersions RuntimeSnapshotProvider::GetVersions() const
{
RuntimeSnapshotVersions versions;
versions.renderStateVersion = mRuntimeHost.mRenderStateVersion.load(std::memory_order_relaxed);
versions.parameterStateVersion = mRuntimeHost.mParameterStateVersion.load(std::memory_order_relaxed);
versions.renderStateVersion = mRuntimeStore.GetRenderStateVersion();
versions.parameterStateVersion = mRuntimeStore.GetParameterStateVersion();
return versions;
}
void RuntimeSnapshotProvider::AdvanceFrame()
{
++mRuntimeHost.mFrameCounter;
mRuntimeStore.AdvanceFrameCounter();
}
RuntimeRenderStateSnapshot RuntimeSnapshotProvider::GetRenderStateSnapshot(unsigned outputWidth, unsigned outputHeight) const
@@ -94,10 +84,7 @@ RuntimeRenderStateSnapshot RuntimeSnapshotProvider::GetRenderStateSnapshot(unsig
RuntimeRenderStateSnapshot snapshot;
snapshot.outputWidth = outputWidth;
snapshot.outputHeight = outputHeight;
{
std::lock_guard<std::mutex> lock(mRuntimeHost.mMutex);
BuildLayerRenderStatesLocked(outputWidth, outputHeight, snapshot.states);
}
mRuntimeStore.BuildLayerRenderStates(outputWidth, outputHeight, snapshot.states);
const RuntimeSnapshotVersions versionsAfter = GetVersions();
if (versionsBefore.renderStateVersion == versionsAfter.renderStateVersion &&
@@ -114,13 +101,8 @@ bool RuntimeSnapshotProvider::TryGetRenderStateSnapshot(unsigned outputWidth, un
const RuntimeSnapshotVersions versionsBefore = GetVersions();
std::vector<RuntimeRenderState> states;
{
std::unique_lock<std::mutex> lock(mRuntimeHost.mMutex, std::try_to_lock);
if (!lock.owns_lock())
return false;
BuildLayerRenderStatesLocked(outputWidth, outputHeight, states);
}
if (!mRuntimeStore.TryBuildLayerRenderStates(outputWidth, outputHeight, states))
return false;
const RuntimeSnapshotVersions versionsAfter = GetVersions();
if (versionsBefore.renderStateVersion != versionsAfter.renderStateVersion ||
@@ -139,13 +121,8 @@ bool RuntimeSnapshotProvider::TryGetRenderStateSnapshot(unsigned outputWidth, un
bool RuntimeSnapshotProvider::TryRefreshSnapshotParameters(RuntimeRenderStateSnapshot& snapshot) const
{
const uint64_t expectedRenderStateVersion = snapshot.versions.renderStateVersion;
{
std::unique_lock<std::mutex> lock(mRuntimeHost.mMutex, std::try_to_lock);
if (!lock.owns_lock())
return false;
RefreshCachedLayerStatesLocked(snapshot.states);
}
if (!mRuntimeStore.TryRefreshLayerParameters(snapshot.states))
return false;
const RuntimeSnapshotVersions versions = GetVersions();
if (versions.renderStateVersion != expectedRenderStateVersion)
@@ -157,88 +134,5 @@ bool RuntimeSnapshotProvider::TryRefreshSnapshotParameters(RuntimeRenderStateSna
void RuntimeSnapshotProvider::RefreshDynamicRenderStateFields(std::vector<RuntimeRenderState>& states) const
{
std::lock_guard<std::mutex> lock(mRuntimeHost.mMutex);
RefreshDynamicRenderStateFieldsLocked(states);
}
void RuntimeSnapshotProvider::BuildLayerRenderStatesLocked(unsigned outputWidth, unsigned outputHeight, std::vector<RuntimeRenderState>& states) const
{
const HealthTelemetry::SignalStatusSnapshot signalStatus = mRuntimeHost.mHealthTelemetry.GetSignalStatusSnapshot();
for (const RuntimeHost::LayerPersistentState& layer : mRuntimeHost.mPersistentState.layers)
{
auto shaderIt = mRuntimeHost.mPackagesById.find(layer.shaderId);
if (shaderIt == mRuntimeHost.mPackagesById.end())
continue;
RuntimeRenderState state;
state.layerId = layer.id;
state.shaderId = layer.shaderId;
state.shaderName = shaderIt->second.displayName;
state.mixAmount = 1.0;
state.bypass = layer.bypass ? 1.0 : 0.0;
state.inputWidth = signalStatus.width;
state.inputHeight = signalStatus.height;
state.outputWidth = outputWidth;
state.outputHeight = outputHeight;
state.parameterDefinitions = shaderIt->second.parameters;
state.textureAssets = shaderIt->second.textureAssets;
state.fontAssets = shaderIt->second.fontAssets;
state.isTemporal = shaderIt->second.temporal.enabled;
state.temporalHistorySource = shaderIt->second.temporal.historySource;
state.requestedTemporalHistoryLength = shaderIt->second.temporal.requestedHistoryLength;
state.effectiveTemporalHistoryLength = shaderIt->second.temporal.effectiveHistoryLength;
state.feedback = shaderIt->second.feedback;
for (const ShaderParameterDefinition& definition : shaderIt->second.parameters)
{
ShaderParameterValue value = mRuntimeHost.DefaultValueForDefinition(definition);
auto valueIt = layer.parameterValues.find(definition.id);
if (valueIt != layer.parameterValues.end())
value = valueIt->second;
state.parameterValues[definition.id] = value;
}
states.push_back(state);
}
RefreshDynamicRenderStateFieldsLocked(states);
}
void RuntimeSnapshotProvider::RefreshCachedLayerStatesLocked(std::vector<RuntimeRenderState>& states) const
{
for (RuntimeRenderState& state : states)
{
const auto layerIt = std::find_if(mRuntimeHost.mPersistentState.layers.begin(), mRuntimeHost.mPersistentState.layers.end(),
[&state](const RuntimeHost::LayerPersistentState& layer) { return layer.id == state.layerId; });
if (layerIt == mRuntimeHost.mPersistentState.layers.end())
continue;
state.bypass = layerIt->bypass ? 1.0 : 0.0;
state.parameterValues.clear();
for (const ShaderParameterDefinition& definition : state.parameterDefinitions)
{
ShaderParameterValue value = mRuntimeHost.DefaultValueForDefinition(definition);
auto valueIt = layerIt->parameterValues.find(definition.id);
if (valueIt != layerIt->parameterValues.end())
value = valueIt->second;
state.parameterValues[definition.id] = value;
}
}
}
void RuntimeSnapshotProvider::RefreshDynamicRenderStateFieldsLocked(std::vector<RuntimeRenderState>& states) const
{
const RuntimeClockSnapshot clock = GetRuntimeClockSnapshot();
const double timeSeconds = std::chrono::duration_cast<std::chrono::duration<double>>(std::chrono::steady_clock::now() - mRuntimeHost.mStartTime).count();
const double frameCount = static_cast<double>(mRuntimeHost.mFrameCounter.load(std::memory_order_relaxed));
for (RuntimeRenderState& state : states)
{
state.timeSeconds = timeSeconds;
state.utcTimeSeconds = clock.utcTimeSeconds;
state.utcOffsetSeconds = clock.utcOffsetSeconds;
state.startupRandom = mRuntimeHost.mStartupRandom;
state.frameCount = frameCount;
}
mRuntimeStore.RefreshDynamicRenderStateFields(states);
}

View File

@@ -1,6 +1,6 @@
#pragma once
#include "RuntimeHost.h"
#include "RuntimeStore.h"
#include <cstdint>
#include <string>
@@ -23,7 +23,7 @@ struct RuntimeRenderStateSnapshot
class RuntimeSnapshotProvider
{
public:
explicit RuntimeSnapshotProvider(RuntimeHost& runtimeHost);
explicit RuntimeSnapshotProvider(RuntimeStore& runtimeStore);
bool BuildLayerPassFragmentShaderSources(const std::string& layerId, std::vector<ShaderPassBuildSource>& passSources, std::string& error) const;
unsigned GetMaxTemporalHistoryFrames() const;
@@ -35,9 +35,5 @@ public:
void RefreshDynamicRenderStateFields(std::vector<RuntimeRenderState>& states) const;
private:
void BuildLayerRenderStatesLocked(unsigned outputWidth, unsigned outputHeight, std::vector<RuntimeRenderState>& states) const;
void RefreshCachedLayerStatesLocked(std::vector<RuntimeRenderState>& states) const;
void RefreshDynamicRenderStateFieldsLocked(std::vector<RuntimeRenderState>& states) const;
RuntimeHost& mRuntimeHost;
RuntimeStore& mRuntimeStore;
};

View File

@@ -1,9 +1,11 @@
#include "RuntimeStore.h"
#include "RuntimeClock.h"
#include "ShaderPackageRegistry.h"
#include "RuntimeParameterUtils.h"
#include <fstream>
#include <mutex>
#include <random>
#include <sstream>
#include <windows.h>
@@ -129,11 +131,20 @@ bool FontAssetsEqual(const std::vector<ShaderFontAsset>& left, const std::vector
}
}
RuntimeStore::RuntimeStore(RuntimeHost& runtimeHost) :
mRuntimeHost(runtimeHost)
RuntimeStore::RuntimeStore()
{
}
HealthTelemetry& RuntimeStore::GetHealthTelemetry()
{
return mRuntimeHost.GetHealthTelemetry();
}
const HealthTelemetry& RuntimeStore::GetHealthTelemetry() const
{
return mRuntimeHost.GetHealthTelemetry();
}
bool RuntimeStore::InitializeStore(std::string& error)
{
try
@@ -422,7 +433,7 @@ bool RuntimeStore::SetStoredLayerShaderSelection(const std::string& layerId, con
return SavePersistentState(error);
}
bool RuntimeStore::SetStoredParameterValue(const std::string& layerId, const std::string& parameterId, const JsonValue& newValue, std::string& error)
bool RuntimeStore::SetStoredParameterValue(const std::string& layerId, const std::string& parameterId, const ShaderParameterValue& value, bool persistState, std::string& error)
{
std::lock_guard<std::mutex> lock(mRuntimeHost.mMutex);
@@ -433,71 +444,7 @@ bool RuntimeStore::SetStoredParameterValue(const std::string& layerId, const std
return false;
}
auto shaderIt = mRuntimeHost.mPackagesById.find(layer->shaderId);
if (shaderIt == mRuntimeHost.mPackagesById.end())
{
error = "Unknown shader id: " + layer->shaderId;
return false;
}
const ShaderPackage& shaderPackage = shaderIt->second;
auto parameterIt = std::find_if(shaderPackage.parameters.begin(), shaderPackage.parameters.end(),
[&parameterId](const ShaderParameterDefinition& definition) { return definition.id == parameterId; });
if (parameterIt == shaderPackage.parameters.end())
{
error = "Unknown parameter id: " + parameterId;
return false;
}
if (parameterIt->type == ShaderParameterType::Trigger)
{
ShaderParameterValue& value = layer->parameterValues[parameterId];
const double previousCount = value.numberValues.empty() ? 0.0 : value.numberValues[0];
const double triggerTime = std::chrono::duration_cast<std::chrono::duration<double>>(std::chrono::steady_clock::now() - mRuntimeHost.mStartTime).count();
value.numberValues = { previousCount + 1.0, triggerTime };
mRuntimeHost.MarkParameterStateDirtyLocked();
return true;
}
ShaderParameterValue normalized;
if (!mRuntimeHost.NormalizeAndValidateValue(*parameterIt, newValue, normalized, error))
return false;
layer->parameterValues[parameterId] = normalized;
mRuntimeHost.MarkParameterStateDirtyLocked();
return SavePersistentState(error);
}
bool RuntimeStore::SetStoredParameterValueByControlKey(const std::string& layerKey, const std::string& parameterKey, const JsonValue& newValue, std::string& error)
{
return SetStoredParameterValueByControlKey(layerKey, parameterKey, newValue, true, error);
}
bool RuntimeStore::SetStoredParameterValueByControlKey(const std::string& layerKey, const std::string& parameterKey, const JsonValue& newValue, bool persistState, std::string& error)
{
std::lock_guard<std::mutex> lock(mRuntimeHost.mMutex);
RuntimeHost::LayerPersistentState* matchedLayer = nullptr;
const ShaderPackage* matchedPackage = nullptr;
std::vector<ShaderParameterDefinition>::const_iterator parameterIt;
if (!TryResolveStoredLayerAndParameterByControlKeyLocked(layerKey, parameterKey, matchedLayer, matchedPackage, parameterIt, error))
return false;
if (parameterIt->type == ShaderParameterType::Trigger)
{
ShaderParameterValue& value = matchedLayer->parameterValues[parameterIt->id];
const double previousCount = value.numberValues.empty() ? 0.0 : value.numberValues[0];
const double triggerTime = std::chrono::duration_cast<std::chrono::duration<double>>(std::chrono::steady_clock::now() - mRuntimeHost.mStartTime).count();
value.numberValues = { previousCount + 1.0, triggerTime };
mRuntimeHost.MarkParameterStateDirtyLocked();
return true;
}
ShaderParameterValue normalized;
if (!mRuntimeHost.NormalizeAndValidateValue(*parameterIt, newValue, normalized, error))
return false;
matchedLayer->parameterValues[parameterIt->id] = normalized;
layer->parameterValues[parameterId] = value;
mRuntimeHost.MarkParameterStateDirtyLocked();
return !persistState || SavePersistentState(error);
}
@@ -1194,3 +1141,165 @@ bool RuntimeStore::TryResolveStoredLayerAndParameterByControlKeyLocked(const std
return true;
}
bool RuntimeStore::CopyShaderPackageForStoredLayer(const std::string& layerId, ShaderPackage& shaderPackage, std::string& error) const
{
std::lock_guard<std::mutex> lock(mRuntimeHost.mMutex);
const RuntimeHost::LayerPersistentState* layer = mRuntimeHost.FindLayerById(layerId);
if (!layer)
{
error = "Unknown layer id: " + layerId;
return false;
}
auto it = mRuntimeHost.mPackagesById.find(layer->shaderId);
if (it == mRuntimeHost.mPackagesById.end())
{
error = "Unknown shader id: " + layer->shaderId;
return false;
}
shaderPackage = it->second;
return true;
}
void RuntimeStore::GetShaderCompilerInputs(std::filesystem::path& repoRoot, std::filesystem::path& wrapperPath,
std::filesystem::path& generatedGlslPath, std::filesystem::path& patchedGlslPath, unsigned& maxTemporalHistoryFrames) const
{
std::lock_guard<std::mutex> lock(mRuntimeHost.mMutex);
repoRoot = mRuntimeHost.mRepoRoot;
wrapperPath = mRuntimeHost.mWrapperPath;
generatedGlslPath = mRuntimeHost.mGeneratedGlslPath;
patchedGlslPath = mRuntimeHost.mPatchedGlslPath;
maxTemporalHistoryFrames = mRuntimeHost.mConfig.maxTemporalHistoryFrames;
}
uint64_t RuntimeStore::GetRenderStateVersion() const
{
return mRuntimeHost.mRenderStateVersion.load(std::memory_order_relaxed);
}
uint64_t RuntimeStore::GetParameterStateVersion() const
{
return mRuntimeHost.mParameterStateVersion.load(std::memory_order_relaxed);
}
void RuntimeStore::AdvanceFrameCounter()
{
++mRuntimeHost.mFrameCounter;
}
void RuntimeStore::BuildLayerRenderStates(unsigned outputWidth, unsigned outputHeight, std::vector<RuntimeRenderState>& states) const
{
std::lock_guard<std::mutex> lock(mRuntimeHost.mMutex);
BuildLayerRenderStatesLocked(outputWidth, outputHeight, states);
}
bool RuntimeStore::TryBuildLayerRenderStates(unsigned outputWidth, unsigned outputHeight, std::vector<RuntimeRenderState>& states) const
{
std::unique_lock<std::mutex> lock(mRuntimeHost.mMutex, std::try_to_lock);
if (!lock.owns_lock())
return false;
BuildLayerRenderStatesLocked(outputWidth, outputHeight, states);
return true;
}
bool RuntimeStore::TryRefreshLayerParameters(std::vector<RuntimeRenderState>& states) const
{
std::unique_lock<std::mutex> lock(mRuntimeHost.mMutex, std::try_to_lock);
if (!lock.owns_lock())
return false;
RefreshLayerParametersLocked(states);
return true;
}
void RuntimeStore::RefreshDynamicRenderStateFields(std::vector<RuntimeRenderState>& states) const
{
std::lock_guard<std::mutex> lock(mRuntimeHost.mMutex);
RefreshDynamicRenderStateFieldsLocked(states);
}
void RuntimeStore::BuildLayerRenderStatesLocked(unsigned outputWidth, unsigned outputHeight, std::vector<RuntimeRenderState>& states) const
{
states.clear();
const HealthTelemetry::SignalStatusSnapshot signalStatus = mRuntimeHost.mHealthTelemetry.GetSignalStatusSnapshot();
for (const RuntimeHost::LayerPersistentState& layer : mRuntimeHost.mPersistentState.layers)
{
auto shaderIt = mRuntimeHost.mPackagesById.find(layer.shaderId);
if (shaderIt == mRuntimeHost.mPackagesById.end())
continue;
RuntimeRenderState state;
state.layerId = layer.id;
state.shaderId = layer.shaderId;
state.shaderName = shaderIt->second.displayName;
state.mixAmount = 1.0;
state.bypass = layer.bypass ? 1.0 : 0.0;
state.inputWidth = signalStatus.width;
state.inputHeight = signalStatus.height;
state.outputWidth = outputWidth;
state.outputHeight = outputHeight;
state.parameterDefinitions = shaderIt->second.parameters;
state.textureAssets = shaderIt->second.textureAssets;
state.fontAssets = shaderIt->second.fontAssets;
state.isTemporal = shaderIt->second.temporal.enabled;
state.temporalHistorySource = shaderIt->second.temporal.historySource;
state.requestedTemporalHistoryLength = shaderIt->second.temporal.requestedHistoryLength;
state.effectiveTemporalHistoryLength = shaderIt->second.temporal.effectiveHistoryLength;
state.feedback = shaderIt->second.feedback;
for (const ShaderParameterDefinition& definition : shaderIt->second.parameters)
{
ShaderParameterValue value = mRuntimeHost.DefaultValueForDefinition(definition);
auto valueIt = layer.parameterValues.find(definition.id);
if (valueIt != layer.parameterValues.end())
value = valueIt->second;
state.parameterValues[definition.id] = value;
}
states.push_back(state);
}
RefreshDynamicRenderStateFieldsLocked(states);
}
void RuntimeStore::RefreshLayerParametersLocked(std::vector<RuntimeRenderState>& states) const
{
for (RuntimeRenderState& state : states)
{
const auto layerIt = std::find_if(mRuntimeHost.mPersistentState.layers.begin(), mRuntimeHost.mPersistentState.layers.end(),
[&state](const RuntimeHost::LayerPersistentState& layer) { return layer.id == state.layerId; });
if (layerIt == mRuntimeHost.mPersistentState.layers.end())
continue;
state.bypass = layerIt->bypass ? 1.0 : 0.0;
state.parameterValues.clear();
for (const ShaderParameterDefinition& definition : state.parameterDefinitions)
{
ShaderParameterValue value = mRuntimeHost.DefaultValueForDefinition(definition);
auto valueIt = layerIt->parameterValues.find(definition.id);
if (valueIt != layerIt->parameterValues.end())
value = valueIt->second;
state.parameterValues[definition.id] = value;
}
}
}
void RuntimeStore::RefreshDynamicRenderStateFieldsLocked(std::vector<RuntimeRenderState>& states) const
{
const RuntimeClockSnapshot clock = GetRuntimeClockSnapshot();
const double timeSeconds = std::chrono::duration_cast<std::chrono::duration<double>>(std::chrono::steady_clock::now() - mRuntimeHost.mStartTime).count();
const double frameCount = static_cast<double>(mRuntimeHost.mFrameCounter.load(std::memory_order_relaxed));
for (RuntimeRenderState& state : states)
{
state.timeSeconds = timeSeconds;
state.utcTimeSeconds = clock.utcTimeSeconds;
state.utcOffsetSeconds = clock.utcOffsetSeconds;
state.startupRandom = mRuntimeHost.mStartupRandom;
state.frameCount = frameCount;
}
}

View File

@@ -2,13 +2,18 @@
#include "RuntimeHost.h"
#include <cstdint>
#include <filesystem>
#include <string>
class RuntimeSnapshotProvider;
class RuntimeStore
{
public:
explicit RuntimeStore(RuntimeHost& runtimeHost);
RuntimeStore();
HealthTelemetry& GetHealthTelemetry();
const HealthTelemetry& GetHealthTelemetry() const;
bool InitializeStore(std::string& error);
std::string BuildPersistentStateJson() const;
@@ -20,9 +25,7 @@ public:
bool MoveStoredLayerToIndex(const std::string& layerId, std::size_t targetIndex, std::string& error);
bool SetStoredLayerBypassState(const std::string& layerId, bool bypassed, std::string& error);
bool SetStoredLayerShaderSelection(const std::string& layerId, const std::string& shaderId, std::string& error);
bool SetStoredParameterValue(const std::string& layerId, const std::string& parameterId, const JsonValue& newValue, std::string& error);
bool SetStoredParameterValueByControlKey(const std::string& layerKey, const std::string& parameterKey, const JsonValue& newValue, std::string& error);
bool SetStoredParameterValueByControlKey(const std::string& layerKey, const std::string& parameterKey, const JsonValue& newValue, bool persistState, std::string& error);
bool SetStoredParameterValue(const std::string& layerId, const std::string& parameterId, const ShaderParameterValue& value, bool persistState, std::string& error);
bool ResetStoredLayerParameterValues(const std::string& layerId, std::string& error);
bool SaveStackPresetSnapshot(const std::string& presetName, std::string& error) const;
bool LoadStackPresetSnapshot(const std::string& presetName, std::string& error);
@@ -48,6 +51,8 @@ public:
void ClearReloadRequest();
private:
friend class RuntimeCoordinator;
friend class RuntimeSnapshotProvider;
bool LoadConfig(std::string& error);
bool LoadPersistentState(std::string& error);
bool SavePersistentState(std::string& error) const;
@@ -60,8 +65,21 @@ private:
bool TryResolveStoredLayerAndParameterByControlKeyLocked(const std::string& layerKey, const std::string& parameterKey,
RuntimeHost::LayerPersistentState*& matchedLayer, const ShaderPackage*& matchedPackage,
std::vector<ShaderParameterDefinition>::const_iterator& parameterIt, std::string& error) const;
bool CopyShaderPackageForStoredLayer(const std::string& layerId, ShaderPackage& shaderPackage, std::string& error) const;
void GetShaderCompilerInputs(std::filesystem::path& repoRoot, std::filesystem::path& wrapperPath,
std::filesystem::path& generatedGlslPath, std::filesystem::path& patchedGlslPath, unsigned& maxTemporalHistoryFrames) const;
uint64_t GetRenderStateVersion() const;
uint64_t GetParameterStateVersion() const;
void AdvanceFrameCounter();
void BuildLayerRenderStates(unsigned outputWidth, unsigned outputHeight, std::vector<RuntimeRenderState>& states) const;
bool TryBuildLayerRenderStates(unsigned outputWidth, unsigned outputHeight, std::vector<RuntimeRenderState>& states) const;
bool TryRefreshLayerParameters(std::vector<RuntimeRenderState>& states) const;
void RefreshDynamicRenderStateFields(std::vector<RuntimeRenderState>& states) const;
void BuildLayerRenderStatesLocked(unsigned outputWidth, unsigned outputHeight, std::vector<RuntimeRenderState>& states) const;
void RefreshLayerParametersLocked(std::vector<RuntimeRenderState>& states) const;
void RefreshDynamicRenderStateFieldsLocked(std::vector<RuntimeRenderState>& states) const;
JsonValue BuildRuntimeStateValue() const;
JsonValue SerializeLayerStack() const;
RuntimeHost& mRuntimeHost;
mutable RuntimeHost mRuntimeHost;
};