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

This commit is contained in:
Aiden
2026-05-11 01:29:44 +10:00
parent c4883d3413
commit b2369c418b
18 changed files with 1143 additions and 484 deletions

View File

@@ -4,8 +4,12 @@
#include "GlRenderConstants.h"
#include "PngScreenshotWriter.h"
#include "RenderEngine.h"
#include "RuntimeCoordinator.h"
#include "RuntimeParameterUtils.h"
#include "RuntimeServices.h"
#include "RuntimeSnapshotProvider.h"
#include "RuntimeStore.h"
#include "RuntimeUpdateController.h"
#include "ShaderBuildQueue.h"
#include "VideoBackend.h"
@@ -46,6 +50,13 @@ OpenGLComposite::OpenGLComposite(HWND hWnd, HDC hDC, HGLRC hRC) :
mVideoBackend = std::make_unique<VideoBackend>(*mRenderEngine, mRuntimeStore->GetHealthTelemetry());
mShaderBuildQueue = std::make_unique<ShaderBuildQueue>(*mRuntimeSnapshotProvider);
mRuntimeServices = std::make_unique<RuntimeServices>();
mRuntimeUpdateController = std::make_unique<RuntimeUpdateController>(
*mRuntimeStore,
*mRuntimeCoordinator,
*mRuntimeServices,
*mRenderEngine,
*mShaderBuildQueue,
*mVideoBackend);
}
OpenGLComposite::~OpenGLComposite()
@@ -245,7 +256,7 @@ bool OpenGLComposite::InitOpenGLState()
mRenderEngine->ResetTemporalHistoryState();
mRenderEngine->ResetShaderFeedbackState();
broadcastRuntimeState();
mRuntimeUpdateController->BroadcastRuntimeState();
mRuntimeServices->BeginPolling(*mRuntimeCoordinator);
return true;
}
@@ -273,7 +284,8 @@ bool OpenGLComposite::Stop()
bool OpenGLComposite::ReloadShader(bool preserveFeedbackState)
{
return mRuntimeCoordinator &&
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->RequestShaderReload(preserveFeedbackState));
mRuntimeUpdateController &&
mRuntimeUpdateController->ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->RequestShaderReload(preserveFeedbackState));
}
bool OpenGLComposite::RequestScreenshot(std::string& error)
@@ -285,7 +297,8 @@ bool OpenGLComposite::RequestScreenshot(std::string& error)
void OpenGLComposite::renderEffect()
{
ProcessRuntimePollResults();
if (mRuntimeUpdateController)
mRuntimeUpdateController->ProcessRuntimeWork();
std::vector<RuntimeServices::AppliedOscUpdate> appliedOscUpdates;
std::vector<RuntimeServices::CompletedOscCommit> completedOscCommits;
if (mRuntimeServices)
@@ -400,105 +413,7 @@ std::filesystem::path OpenGLComposite::BuildScreenshotPath() const
return root / "screenshots" / filename.str();
}
bool OpenGLComposite::ProcessRuntimePollResults()
{
if (!mRuntimeServices)
return true;
bool shaderBuildRequested = false;
std::vector<RuntimeCoordinatorServiceResult> serviceResults;
mRuntimeServices->ConsumeRuntimeCoordinatorResults(serviceResults);
for (const RuntimeCoordinatorServiceResult& serviceResult : serviceResults)
{
shaderBuildRequested = shaderBuildRequested || serviceResult.result.shaderBuildRequested;
ApplyRuntimeCoordinatorResult(serviceResult.result);
if (serviceResult.failed)
return false;
}
if (!shaderBuildRequested)
{
if (!mShaderBuildQueue || !mRenderEngine)
return true;
const RenderEngine::PreparedShaderBuildApplyResult buildResult = mRenderEngine->TryApplyReadyShaderBuild(
*mShaderBuildQueue,
mVideoBackend->InputFrameWidth(),
mVideoBackend->InputFrameHeight(),
mRuntimeCoordinator && mRuntimeCoordinator->PreserveFeedbackOnNextShaderBuild());
if (!buildResult.hadReadyBuild)
return true;
if (!buildResult.applied)
{
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->HandlePreparedShaderBuildFailure(buildResult.errorMessage));
return false;
}
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->HandlePreparedShaderBuildSuccess());
return true;
}
return true;
}
void OpenGLComposite::RequestShaderBuild()
{
if (!mShaderBuildQueue || !mVideoBackend)
return;
mShaderBuildQueue->RequestBuild(mVideoBackend->InputFrameWidth(), mVideoBackend->InputFrameHeight());
}
bool OpenGLComposite::ApplyRuntimeCoordinatorResult(const RuntimeCoordinatorResult& result, std::string* error)
{
if (!result.accepted)
{
if (error)
*error = result.errorMessage;
return false;
}
if (result.compileStatusChanged && mRuntimeStore)
mRuntimeStore->SetCompileStatus(result.compileStatusSucceeded, result.compileStatusMessage);
if (result.clearReloadRequest && mRuntimeStore)
mRuntimeStore->ClearReloadRequest();
if (mRuntimeCoordinator)
mRuntimeCoordinator->ApplyCommittedStateMode(result.committedStateMode);
if (result.clearTransientOscState)
{
if (mRenderEngine)
mRenderEngine->ClearOscOverlayState();
if (mRuntimeServices)
mRuntimeServices->ClearOscState();
}
if (mRenderEngine)
mRenderEngine->ApplyRuntimeCoordinatorRenderReset(result.renderResetScope);
if (result.shaderBuildRequested)
RequestShaderBuild();
if (result.runtimeStateBroadcastRequired)
broadcastRuntimeState();
return true;
}
void OpenGLComposite::broadcastRuntimeState()
{
if (mRuntimeServices)
mRuntimeServices->BroadcastState();
}
bool OpenGLComposite::CheckOpenGLExtensions()
{
return true;
}
////////////////////////////////////////////

View File

@@ -12,9 +12,6 @@
#include <comutil.h>
#include "GLExtensions.h"
#include "RuntimeCoordinator.h"
#include "RuntimeSnapshotProvider.h"
#include "RuntimeStore.h"
#include <functional>
#include <atomic>
@@ -24,7 +21,11 @@
#include <vector>
class RenderEngine;
class RuntimeCoordinator;
class RuntimeSnapshotProvider;
class RuntimeServices;
class RuntimeStore;
class RuntimeUpdateController;
class ShaderBuildQueue;
class VideoBackend;
@@ -78,17 +79,14 @@ private:
std::unique_ptr<RenderEngine> mRenderEngine;
std::unique_ptr<ShaderBuildQueue> mShaderBuildQueue;
std::unique_ptr<RuntimeServices> mRuntimeServices;
std::unique_ptr<RuntimeUpdateController> mRuntimeUpdateController;
std::unique_ptr<VideoBackend> mVideoBackend;
std::atomic<bool> mScreenshotRequested;
bool InitOpenGLState();
void renderEffect();
bool ProcessRuntimePollResults();
void RequestShaderBuild();
bool ApplyRuntimeCoordinatorResult(const RuntimeCoordinatorResult& result, std::string* error = nullptr);
void ProcessScreenshotRequest();
std::filesystem::path BuildScreenshotPath() const;
void broadcastRuntimeState();
};
#endif // __OPENGL_COMPOSITE_H__

View File

@@ -1,5 +1,9 @@
#include "OpenGLComposite.h"
#include "RuntimeCoordinator.h"
#include "RuntimeJson.h"
#include "RuntimeServices.h"
#include "RuntimeStore.h"
#include "RuntimeUpdateController.h"
std::string OpenGLComposite::GetRuntimeStateJson() const
{
@@ -39,37 +43,43 @@ std::string OpenGLComposite::GetOscAddress() const
bool OpenGLComposite::AddLayer(const std::string& shaderId, std::string& error)
{
return mRuntimeCoordinator &&
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->AddLayer(shaderId), &error);
mRuntimeUpdateController &&
mRuntimeUpdateController->ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->AddLayer(shaderId), &error);
}
bool OpenGLComposite::RemoveLayer(const std::string& layerId, std::string& error)
{
return mRuntimeCoordinator &&
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->RemoveLayer(layerId), &error);
mRuntimeUpdateController &&
mRuntimeUpdateController->ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->RemoveLayer(layerId), &error);
}
bool OpenGLComposite::MoveLayer(const std::string& layerId, int direction, std::string& error)
{
return mRuntimeCoordinator &&
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->MoveLayer(layerId, direction), &error);
mRuntimeUpdateController &&
mRuntimeUpdateController->ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->MoveLayer(layerId, direction), &error);
}
bool OpenGLComposite::MoveLayerToIndex(const std::string& layerId, std::size_t targetIndex, std::string& error)
{
return mRuntimeCoordinator &&
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->MoveLayerToIndex(layerId, targetIndex), &error);
mRuntimeUpdateController &&
mRuntimeUpdateController->ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->MoveLayerToIndex(layerId, targetIndex), &error);
}
bool OpenGLComposite::SetLayerBypass(const std::string& layerId, bool bypassed, std::string& error)
{
return mRuntimeCoordinator &&
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->SetLayerBypass(layerId, bypassed), &error);
mRuntimeUpdateController &&
mRuntimeUpdateController->ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->SetLayerBypass(layerId, bypassed), &error);
}
bool OpenGLComposite::SetLayerShader(const std::string& layerId, const std::string& shaderId, std::string& error)
{
return mRuntimeCoordinator &&
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->SetLayerShader(layerId, shaderId), &error);
mRuntimeUpdateController &&
mRuntimeUpdateController->ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->SetLayerShader(layerId, shaderId), &error);
}
bool OpenGLComposite::UpdateLayerParameterJson(const std::string& layerId, const std::string& parameterId, const std::string& valueJson, std::string& error)
@@ -79,7 +89,8 @@ bool OpenGLComposite::UpdateLayerParameterJson(const std::string& layerId, const
return false;
return mRuntimeCoordinator &&
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->UpdateLayerParameter(layerId, parameterId, parsedValue), &error);
mRuntimeUpdateController &&
mRuntimeUpdateController->ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->UpdateLayerParameter(layerId, parameterId, parsedValue), &error);
}
bool OpenGLComposite::UpdateLayerParameterByControlKeyJson(const std::string& layerKey, const std::string& parameterKey, const std::string& valueJson, std::string& error)
@@ -89,23 +100,27 @@ bool OpenGLComposite::UpdateLayerParameterByControlKeyJson(const std::string& la
return false;
return mRuntimeCoordinator &&
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->UpdateLayerParameterByControlKey(layerKey, parameterKey, parsedValue), &error);
mRuntimeUpdateController &&
mRuntimeUpdateController->ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->UpdateLayerParameterByControlKey(layerKey, parameterKey, parsedValue), &error);
}
bool OpenGLComposite::ResetLayerParameters(const std::string& layerId, std::string& error)
{
return mRuntimeCoordinator &&
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->ResetLayerParameters(layerId), &error);
mRuntimeUpdateController &&
mRuntimeUpdateController->ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->ResetLayerParameters(layerId), &error);
}
bool OpenGLComposite::SaveStackPreset(const std::string& presetName, std::string& error)
{
return mRuntimeCoordinator &&
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->SaveStackPreset(presetName), &error);
mRuntimeUpdateController &&
mRuntimeUpdateController->ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->SaveStackPreset(presetName), &error);
}
bool OpenGLComposite::LoadStackPreset(const std::string& presetName, std::string& error)
{
return mRuntimeCoordinator &&
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->LoadStackPreset(presetName), &error);
mRuntimeUpdateController &&
mRuntimeUpdateController->ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->LoadStackPreset(presetName), &error);
}

View File

@@ -379,7 +379,7 @@ bool RenderEngine::ResolveRenderLayerStates(
ApplyOscOverlays(renderSnapshot.states, true, oscSmoothing, commitRequests);
if (mCachedParameterStateVersion != versions.parameterStateVersion &&
mRuntimeSnapshotProvider.TryRefreshSnapshotParameters(renderSnapshot))
mRuntimeSnapshotProvider.TryRefreshPublishedSnapshotParameters(renderSnapshot))
{
mCachedParameterStateVersion = renderSnapshot.versions.parameterStateVersion;
ApplyOscOverlays(renderSnapshot.states, true, oscSmoothing, commitRequests);
@@ -392,7 +392,7 @@ bool RenderEngine::ResolveRenderLayerStates(
}
RuntimeRenderStateSnapshot renderSnapshot;
if (mRuntimeSnapshotProvider.TryGetRenderStateSnapshot(renderWidth, renderHeight, renderSnapshot))
if (mRuntimeSnapshotProvider.TryPublishRenderStateSnapshot(renderWidth, renderHeight, renderSnapshot))
{
mCachedLayerRenderStates = renderSnapshot.states;
mCachedRenderStateVersion = renderSnapshot.versions.renderStateVersion;

View File

@@ -0,0 +1,103 @@
#include "RuntimeUpdateController.h"
#include "RenderEngine.h"
#include "RuntimeServices.h"
#include "RuntimeStore.h"
#include "ShaderBuildQueue.h"
#include "VideoBackend.h"
#include <vector>
RuntimeUpdateController::RuntimeUpdateController(
RuntimeStore& runtimeStore,
RuntimeCoordinator& runtimeCoordinator,
RuntimeServices& runtimeServices,
RenderEngine& renderEngine,
ShaderBuildQueue& shaderBuildQueue,
VideoBackend& videoBackend) :
mRuntimeStore(runtimeStore),
mRuntimeCoordinator(runtimeCoordinator),
mRuntimeServices(runtimeServices),
mRenderEngine(renderEngine),
mShaderBuildQueue(shaderBuildQueue),
mVideoBackend(videoBackend)
{
}
bool RuntimeUpdateController::ApplyRuntimeCoordinatorResult(const RuntimeCoordinatorResult& result, std::string* error)
{
if (!result.accepted)
{
if (error)
*error = result.errorMessage;
return false;
}
if (result.compileStatusChanged)
mRuntimeStore.SetCompileStatus(result.compileStatusSucceeded, result.compileStatusMessage);
if (result.clearReloadRequest)
mRuntimeStore.ClearReloadRequest();
mRuntimeCoordinator.ApplyCommittedStateMode(result.committedStateMode);
if (result.clearTransientOscState)
{
mRenderEngine.ClearOscOverlayState();
mRuntimeServices.ClearOscState();
}
mRenderEngine.ApplyRuntimeCoordinatorRenderReset(result.renderResetScope);
if (result.shaderBuildRequested)
RequestShaderBuild();
if (result.runtimeStateBroadcastRequired)
BroadcastRuntimeState();
return true;
}
bool RuntimeUpdateController::ProcessRuntimeWork()
{
bool shaderBuildRequested = false;
std::vector<RuntimeCoordinatorServiceResult> serviceResults;
mRuntimeServices.ConsumeRuntimeCoordinatorResults(serviceResults);
for (const RuntimeCoordinatorServiceResult& serviceResult : serviceResults)
{
shaderBuildRequested = shaderBuildRequested || serviceResult.result.shaderBuildRequested;
ApplyRuntimeCoordinatorResult(serviceResult.result);
if (serviceResult.failed)
return false;
}
if (shaderBuildRequested)
return true;
const RenderEngine::PreparedShaderBuildApplyResult buildResult = mRenderEngine.TryApplyReadyShaderBuild(
mShaderBuildQueue,
mVideoBackend.InputFrameWidth(),
mVideoBackend.InputFrameHeight(),
mRuntimeCoordinator.PreserveFeedbackOnNextShaderBuild());
if (!buildResult.hadReadyBuild)
return true;
if (!buildResult.applied)
{
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator.HandlePreparedShaderBuildFailure(buildResult.errorMessage));
return false;
}
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator.HandlePreparedShaderBuildSuccess());
return true;
}
void RuntimeUpdateController::RequestShaderBuild()
{
mShaderBuildQueue.RequestBuild(mVideoBackend.InputFrameWidth(), mVideoBackend.InputFrameHeight());
}
void RuntimeUpdateController::BroadcastRuntimeState()
{
mRuntimeServices.BroadcastState();
}

View File

@@ -0,0 +1,36 @@
#pragma once
#include "RuntimeCoordinator.h"
#include <string>
class RenderEngine;
class RuntimeServices;
class RuntimeStore;
class ShaderBuildQueue;
class VideoBackend;
class RuntimeUpdateController
{
public:
RuntimeUpdateController(
RuntimeStore& runtimeStore,
RuntimeCoordinator& runtimeCoordinator,
RuntimeServices& runtimeServices,
RenderEngine& renderEngine,
ShaderBuildQueue& shaderBuildQueue,
VideoBackend& videoBackend);
bool ApplyRuntimeCoordinatorResult(const RuntimeCoordinatorResult& result, std::string* error = nullptr);
bool ProcessRuntimeWork();
void RequestShaderBuild();
void BroadcastRuntimeState();
private:
RuntimeStore& mRuntimeStore;
RuntimeCoordinator& mRuntimeCoordinator;
RuntimeServices& mRuntimeServices;
RenderEngine& mRenderEngine;
ShaderBuildQueue& mShaderBuildQueue;
VideoBackend& mVideoBackend;
};

View File

@@ -40,7 +40,7 @@ OpenGLShaderPrograms::OpenGLShaderPrograms(OpenGLRenderer& renderer, RuntimeSnap
bool OpenGLShaderPrograms::CompileLayerPrograms(unsigned inputFrameWidth, unsigned inputFrameHeight, int errorMessageSize, char* errorMessage)
{
const RuntimeRenderStateSnapshot renderSnapshot =
mRuntimeSnapshotProvider.GetRenderStateSnapshot(inputFrameWidth, inputFrameHeight);
mRuntimeSnapshotProvider.PublishRenderStateSnapshot(inputFrameWidth, inputFrameHeight);
const std::vector<RuntimeRenderState>& layerStates = renderSnapshot.states;
std::string temporalError;
const unsigned historyCap = mRuntimeSnapshotProvider.GetMaxTemporalHistoryFrames();

View File

@@ -111,7 +111,7 @@ PreparedShaderBuild ShaderBuildQueue::Build(uint64_t generation, unsigned output
{
PreparedShaderBuild build;
build.generation = generation;
build.renderSnapshot = mRuntimeSnapshotProvider.GetRenderStateSnapshot(outputWidth, outputHeight);
build.renderSnapshot = mRuntimeSnapshotProvider.PublishRenderStateSnapshot(outputWidth, outputHeight);
build.layers.reserve(build.renderSnapshot.states.size());
for (const RuntimeRenderState& state : build.renderSnapshot.states)

View File

@@ -1,10 +1,8 @@
#include "RuntimeCoordinator.h"
#include "RuntimeParameterUtils.h"
#include "RuntimeStore.h"
#include <algorithm>
#include <chrono>
RuntimeCoordinator::RuntimeCoordinator(RuntimeStore& runtimeStore) :
mRuntimeStore(runtimeStore)
{
@@ -252,84 +250,50 @@ bool RuntimeCoordinator::PreserveFeedbackOnNextShaderBuild() const
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;
RuntimeStore::StoredParameterSnapshot snapshot;
if (!mRuntimeStore.TryGetStoredParameterById(layerId, parameterId, snapshot, error))
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);
return BuildParameterMutationFromSnapshot(snapshot.layerId, snapshot.definition, snapshot.currentValue, snapshot.hasCurrentValue,
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))
RuntimeStore::StoredParameterSnapshot snapshot;
if (!mRuntimeStore.TryGetStoredParameterByControlKey(layerKey, parameterKey, snapshot, error))
return false;
return BuildParameterMutationLocked(*matchedLayer, *parameterIt, newValue, persistState, mutation, error);
return BuildParameterMutationFromSnapshot(snapshot.layerId, snapshot.definition, snapshot.currentValue, snapshot.hasCurrentValue,
newValue, persistState, mutation, error);
}
bool RuntimeCoordinator::BuildParameterMutationLocked(RuntimeHost::LayerPersistentState& layer, const ShaderParameterDefinition& definition, const JsonValue& newValue,
bool RuntimeCoordinator::BuildParameterMutationFromSnapshot(const std::string& layerId, const ShaderParameterDefinition& definition,
const ShaderParameterValue& currentValue, bool hasCurrentValue, const JsonValue& newValue,
bool persistState, ResolvedParameterMutation& mutation, std::string& error) const
{
mutation.layerId = layer.id;
mutation.layerId = layerId;
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()
const double previousCount = !hasCurrentValue || currentValue.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();
: currentValue.numberValues[0];
const double triggerTime = mRuntimeStore.GetRuntimeElapsedSeconds();
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();
return NormalizeAndValidateParameterValue(definition, newValue, mutation.value, error);
}
bool RuntimeCoordinator::ValidateLayerExists(const std::string& layerId, std::string& error) const
{
std::lock_guard<std::mutex> lock(mRuntimeStore.mRuntimeHost.mMutex);
if (HasLayerLocked(layerId))
if (mRuntimeStore.HasStoredLayer(layerId))
return true;
error = "Unknown layer id: " + layerId;
@@ -338,8 +302,7 @@ bool RuntimeCoordinator::ValidateLayerExists(const std::string& layerId, std::st
bool RuntimeCoordinator::ValidateShaderExists(const std::string& shaderId, std::string& error) const
{
std::lock_guard<std::mutex> lock(mRuntimeStore.mRuntimeHost.mMutex);
if (HasShaderLocked(shaderId))
if (mRuntimeStore.HasStoredShader(shaderId))
return true;
error = "Unknown shader id: " + shaderId;
@@ -348,49 +311,17 @@ bool RuntimeCoordinator::ValidateShaderExists(const std::string& shaderId, std::
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;
return mRuntimeStore.ResolveStoredLayerMove(layerId, direction, shouldMove, error);
}
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;
return mRuntimeStore.ResolveStoredLayerMoveToIndex(layerId, targetIndex, shouldMove, error);
}
bool RuntimeCoordinator::ValidatePresetName(const std::string& presetName, std::string& error) const
{
if (!mRuntimeStore.MakeSafePresetFileStem(presetName).empty())
if (mRuntimeStore.IsValidStackPresetName(presetName))
return true;
error = "Preset name must include at least one letter or number.";

View File

@@ -1,7 +1,7 @@
#pragma once
#include "RuntimeHost.h"
#include "RuntimeJson.h"
#include "ShaderTypes.h"
#include <atomic>
#include <cstddef>
@@ -80,10 +80,9 @@ private:
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 BuildParameterMutationFromSnapshot(const std::string& layerId, const ShaderParameterDefinition& definition,
const ShaderParameterValue& currentValue, bool hasCurrentValue, 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;

View File

@@ -75,11 +75,14 @@ void RuntimeSnapshotProvider::AdvanceFrame()
mRuntimeStore.AdvanceFrameCounter();
}
RuntimeRenderStateSnapshot RuntimeSnapshotProvider::GetRenderStateSnapshot(unsigned outputWidth, unsigned outputHeight) const
RuntimeRenderStateSnapshot RuntimeSnapshotProvider::PublishRenderStateSnapshot(unsigned outputWidth, unsigned outputHeight) const
{
for (;;)
{
const RuntimeSnapshotVersions versionsBefore = GetVersions();
RuntimeRenderStateSnapshot publishedSnapshot;
if (TryGetPublishedRenderStateSnapshot(outputWidth, outputHeight, versionsBefore, publishedSnapshot))
return publishedSnapshot;
RuntimeRenderStateSnapshot snapshot;
snapshot.outputWidth = outputWidth;
@@ -91,14 +94,17 @@ RuntimeRenderStateSnapshot RuntimeSnapshotProvider::GetRenderStateSnapshot(unsig
versionsBefore.parameterStateVersion == versionsAfter.parameterStateVersion)
{
snapshot.versions = versionsAfter;
StorePublishedRenderStateSnapshot(snapshot);
return snapshot;
}
}
}
bool RuntimeSnapshotProvider::TryGetRenderStateSnapshot(unsigned outputWidth, unsigned outputHeight, RuntimeRenderStateSnapshot& snapshot) const
bool RuntimeSnapshotProvider::TryPublishRenderStateSnapshot(unsigned outputWidth, unsigned outputHeight, RuntimeRenderStateSnapshot& snapshot) const
{
const RuntimeSnapshotVersions versionsBefore = GetVersions();
if (TryGetPublishedRenderStateSnapshot(outputWidth, outputHeight, versionsBefore, snapshot))
return true;
std::vector<RuntimeRenderState> states;
if (!mRuntimeStore.TryBuildLayerRenderStates(outputWidth, outputHeight, states))
@@ -115,10 +121,11 @@ bool RuntimeSnapshotProvider::TryGetRenderStateSnapshot(unsigned outputWidth, un
snapshot.outputHeight = outputHeight;
snapshot.versions = versionsAfter;
snapshot.states = std::move(states);
StorePublishedRenderStateSnapshot(snapshot);
return true;
}
bool RuntimeSnapshotProvider::TryRefreshSnapshotParameters(RuntimeRenderStateSnapshot& snapshot) const
bool RuntimeSnapshotProvider::TryRefreshPublishedSnapshotParameters(RuntimeRenderStateSnapshot& snapshot) const
{
const uint64_t expectedRenderStateVersion = snapshot.versions.renderStateVersion;
if (!mRuntimeStore.TryRefreshLayerParameters(snapshot.states))
@@ -129,6 +136,7 @@ bool RuntimeSnapshotProvider::TryRefreshSnapshotParameters(RuntimeRenderStateSna
return false;
snapshot.versions = versions;
StorePublishedRenderStateSnapshot(snapshot);
return true;
}
@@ -136,3 +144,33 @@ void RuntimeSnapshotProvider::RefreshDynamicRenderStateFields(std::vector<Runtim
{
mRuntimeStore.RefreshDynamicRenderStateFields(states);
}
bool RuntimeSnapshotProvider::TryGetPublishedRenderStateSnapshot(unsigned outputWidth, unsigned outputHeight,
const RuntimeSnapshotVersions& versions, RuntimeRenderStateSnapshot& snapshot) const
{
std::lock_guard<std::mutex> lock(mPublishedSnapshotMutex);
if (!mHasPublishedRenderStateSnapshot ||
!SnapshotMatches(mPublishedRenderStateSnapshot, outputWidth, outputHeight, versions))
{
return false;
}
snapshot = mPublishedRenderStateSnapshot;
return true;
}
void RuntimeSnapshotProvider::StorePublishedRenderStateSnapshot(const RuntimeRenderStateSnapshot& snapshot) const
{
std::lock_guard<std::mutex> lock(mPublishedSnapshotMutex);
mPublishedRenderStateSnapshot = snapshot;
mHasPublishedRenderStateSnapshot = true;
}
bool RuntimeSnapshotProvider::SnapshotMatches(const RuntimeRenderStateSnapshot& snapshot, unsigned outputWidth, unsigned outputHeight,
const RuntimeSnapshotVersions& versions)
{
return snapshot.outputWidth == outputWidth &&
snapshot.outputHeight == outputHeight &&
snapshot.versions.renderStateVersion == versions.renderStateVersion &&
snapshot.versions.parameterStateVersion == versions.parameterStateVersion;
}

View File

@@ -3,6 +3,7 @@
#include "RuntimeStore.h"
#include <cstdint>
#include <mutex>
#include <string>
#include <vector>
@@ -29,11 +30,20 @@ public:
unsigned GetMaxTemporalHistoryFrames() const;
RuntimeSnapshotVersions GetVersions() const;
void AdvanceFrame();
RuntimeRenderStateSnapshot GetRenderStateSnapshot(unsigned outputWidth, unsigned outputHeight) const;
bool TryGetRenderStateSnapshot(unsigned outputWidth, unsigned outputHeight, RuntimeRenderStateSnapshot& snapshot) const;
bool TryRefreshSnapshotParameters(RuntimeRenderStateSnapshot& snapshot) const;
RuntimeRenderStateSnapshot PublishRenderStateSnapshot(unsigned outputWidth, unsigned outputHeight) const;
bool TryPublishRenderStateSnapshot(unsigned outputWidth, unsigned outputHeight, RuntimeRenderStateSnapshot& snapshot) const;
bool TryRefreshPublishedSnapshotParameters(RuntimeRenderStateSnapshot& snapshot) const;
void RefreshDynamicRenderStateFields(std::vector<RuntimeRenderState>& states) const;
private:
bool TryGetPublishedRenderStateSnapshot(unsigned outputWidth, unsigned outputHeight,
const RuntimeSnapshotVersions& versions, RuntimeRenderStateSnapshot& snapshot) const;
void StorePublishedRenderStateSnapshot(const RuntimeRenderStateSnapshot& snapshot) const;
static bool SnapshotMatches(const RuntimeRenderStateSnapshot& snapshot, unsigned outputWidth, unsigned outputHeight,
const RuntimeSnapshotVersions& versions);
RuntimeStore& mRuntimeStore;
mutable std::mutex mPublishedSnapshotMutex;
mutable bool mHasPublishedRenderStateSnapshot = false;
mutable RuntimeRenderStateSnapshot mPublishedRenderStateSnapshot;
};

File diff suppressed because it is too large Load Diff

View File

@@ -1,16 +1,61 @@
#pragma once
#include "RuntimeHost.h"
#include "HealthTelemetry.h"
#include "RuntimeJson.h"
#include "ShaderTypes.h"
#include <atomic>
#include <chrono>
#include <cstdint>
#include <filesystem>
#include <map>
#include <mutex>
#include <string>
#include <vector>
class RuntimeSnapshotProvider;
class RuntimeStore
{
public:
struct StoredParameterSnapshot
{
std::string layerId;
ShaderParameterDefinition definition;
ShaderParameterValue currentValue;
bool hasCurrentValue = false;
};
struct AppConfig
{
std::string shaderLibrary = "shaders";
unsigned short serverPort = 8080;
unsigned short oscPort = 9000;
std::string oscBindAddress = "127.0.0.1";
double oscSmoothing = 0.18;
bool autoReload = true;
unsigned maxTemporalHistoryFrames = 4;
unsigned previewFps = 30;
bool enableExternalKeying = false;
std::string inputVideoFormat = "1080p";
std::string inputFrameRate = "59.94";
std::string outputVideoFormat = "1080p";
std::string outputFrameRate = "59.94";
};
struct LayerPersistentState
{
std::string id;
std::string shaderId;
bool bypass = false;
std::map<std::string, ShaderParameterValue> parameterValues;
};
struct PersistentState
{
std::vector<LayerPersistentState> layers;
};
RuntimeStore();
HealthTelemetry& GetHealthTelemetry();
const HealthTelemetry& GetHealthTelemetry() const;
@@ -29,6 +74,14 @@ public:
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);
bool HasStoredLayer(const std::string& layerId) const;
bool HasStoredShader(const std::string& shaderId) const;
bool TryGetStoredParameterById(const std::string& layerId, const std::string& parameterId, StoredParameterSnapshot& snapshot, std::string& error) const;
bool TryGetStoredParameterByControlKey(const std::string& layerKey, const std::string& parameterKey, StoredParameterSnapshot& snapshot, std::string& error) const;
bool ResolveStoredLayerMove(const std::string& layerId, int direction, bool& shouldMove, std::string& error) const;
bool ResolveStoredLayerMoveToIndex(const std::string& layerId, std::size_t targetIndex, bool& shouldMove, std::string& error) const;
bool IsValidStackPresetName(const std::string& presetName) const;
double GetRuntimeElapsedSeconds() const;
const std::filesystem::path& GetRuntimeRepositoryRoot() const;
const std::filesystem::path& GetRuntimeUiRoot() const;
@@ -51,7 +104,6 @@ public:
void ClearReloadRequest();
private:
friend class RuntimeCoordinator;
friend class RuntimeSnapshotProvider;
bool LoadConfig(std::string& error);
bool LoadPersistentState(std::string& error);
@@ -63,7 +115,7 @@ private:
std::vector<std::string> GetStackPresetNamesLocked() const;
std::string MakeSafePresetFileStem(const std::string& presetName) const;
bool TryResolveStoredLayerAndParameterByControlKeyLocked(const std::string& layerKey, const std::string& parameterKey,
RuntimeHost::LayerPersistentState*& matchedLayer, const ShaderPackage*& matchedPackage,
const 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,
@@ -80,6 +132,48 @@ private:
void RefreshDynamicRenderStateFieldsLocked(std::vector<RuntimeRenderState>& states) const;
JsonValue BuildRuntimeStateValue() const;
JsonValue SerializeLayerStack() const;
bool NormalizeAndValidateValue(const ShaderParameterDefinition& definition, const JsonValue& value, ShaderParameterValue& normalizedValue, std::string& error) const;
ShaderParameterValue DefaultValueForDefinition(const ShaderParameterDefinition& definition) const;
void EnsureLayerDefaultsLocked(LayerPersistentState& layerState, const ShaderPackage& shaderPackage) const;
JsonValue SerializeLayerStackLocked() const;
bool DeserializeLayerStackLocked(const JsonValue& layersValue, std::vector<LayerPersistentState>& layers, std::string& error);
void NormalizePersistentLayerIdsLocked();
JsonValue SerializeParameterValue(const ShaderParameterDefinition& definition, const ShaderParameterValue& value) const;
std::string TemporalHistorySourceToString(TemporalHistorySource source) const;
LayerPersistentState* FindLayerById(const std::string& layerId);
const LayerPersistentState* FindLayerById(const std::string& layerId) const;
std::string GenerateLayerId();
void MarkRenderStateDirtyLocked();
void MarkParameterStateDirtyLocked();
mutable RuntimeHost mRuntimeHost;
HealthTelemetry mHealthTelemetry;
mutable std::mutex mMutex;
AppConfig mConfig;
PersistentState mPersistentState;
std::filesystem::path mRepoRoot;
std::filesystem::path mUiRoot;
std::filesystem::path mDocsRoot;
std::filesystem::path mShaderRoot;
std::filesystem::path mRuntimeRoot;
std::filesystem::path mPresetRoot;
std::filesystem::path mRuntimeStatePath;
std::filesystem::path mConfigPath;
std::filesystem::path mWrapperPath;
std::filesystem::path mGeneratedGlslPath;
std::filesystem::path mPatchedGlslPath;
std::map<std::string, ShaderPackage> mPackagesById;
std::vector<std::string> mPackageOrder;
std::vector<ShaderPackageStatus> mPackageStatuses;
bool mReloadRequested;
bool mCompileSucceeded;
std::string mCompileMessage;
double mStartupRandom;
unsigned short mServerPort;
bool mAutoReloadEnabled;
std::chrono::steady_clock::time_point mStartTime;
std::chrono::steady_clock::time_point mLastScanTime;
std::atomic<uint64_t> mFrameCounter{ 0 };
std::atomic<uint64_t> mRenderStateVersion{ 0 };
std::atomic<uint64_t> mParameterStateVersion{ 0 };
uint64_t mNextLayerId;
};