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

@@ -64,6 +64,8 @@ set(APP_SOURCES
"${APP_DIR}/gl/OpenGLCompositeRuntimeControls.cpp" "${APP_DIR}/gl/OpenGLCompositeRuntimeControls.cpp"
"${APP_DIR}/gl/RenderEngine.cpp" "${APP_DIR}/gl/RenderEngine.cpp"
"${APP_DIR}/gl/RenderEngine.h" "${APP_DIR}/gl/RenderEngine.h"
"${APP_DIR}/gl/RuntimeUpdateController.cpp"
"${APP_DIR}/gl/RuntimeUpdateController.h"
"${APP_DIR}/gl/pipeline/OpenGLRenderPass.cpp" "${APP_DIR}/gl/pipeline/OpenGLRenderPass.cpp"
"${APP_DIR}/gl/pipeline/OpenGLRenderPass.h" "${APP_DIR}/gl/pipeline/OpenGLRenderPass.h"
"${APP_DIR}/gl/pipeline/OpenGLRenderPipeline.cpp" "${APP_DIR}/gl/pipeline/OpenGLRenderPipeline.cpp"
@@ -100,8 +102,6 @@ set(APP_SOURCES
"${APP_DIR}/platform/NativeHandles.h" "${APP_DIR}/platform/NativeHandles.h"
"${APP_DIR}/platform/NativeSockets.h" "${APP_DIR}/platform/NativeSockets.h"
"${APP_DIR}/resource.h" "${APP_DIR}/resource.h"
"${APP_DIR}/runtime/RuntimeHost.cpp"
"${APP_DIR}/runtime/RuntimeHost.h"
"${APP_DIR}/runtime/HealthTelemetry.cpp" "${APP_DIR}/runtime/HealthTelemetry.cpp"
"${APP_DIR}/runtime/HealthTelemetry.h" "${APP_DIR}/runtime/HealthTelemetry.h"
"${APP_DIR}/runtime/RuntimeCoordinator.cpp" "${APP_DIR}/runtime/RuntimeCoordinator.cpp"

View File

@@ -4,8 +4,12 @@
#include "GlRenderConstants.h" #include "GlRenderConstants.h"
#include "PngScreenshotWriter.h" #include "PngScreenshotWriter.h"
#include "RenderEngine.h" #include "RenderEngine.h"
#include "RuntimeCoordinator.h"
#include "RuntimeParameterUtils.h" #include "RuntimeParameterUtils.h"
#include "RuntimeServices.h" #include "RuntimeServices.h"
#include "RuntimeSnapshotProvider.h"
#include "RuntimeStore.h"
#include "RuntimeUpdateController.h"
#include "ShaderBuildQueue.h" #include "ShaderBuildQueue.h"
#include "VideoBackend.h" #include "VideoBackend.h"
@@ -46,6 +50,13 @@ OpenGLComposite::OpenGLComposite(HWND hWnd, HDC hDC, HGLRC hRC) :
mVideoBackend = std::make_unique<VideoBackend>(*mRenderEngine, mRuntimeStore->GetHealthTelemetry()); mVideoBackend = std::make_unique<VideoBackend>(*mRenderEngine, mRuntimeStore->GetHealthTelemetry());
mShaderBuildQueue = std::make_unique<ShaderBuildQueue>(*mRuntimeSnapshotProvider); mShaderBuildQueue = std::make_unique<ShaderBuildQueue>(*mRuntimeSnapshotProvider);
mRuntimeServices = std::make_unique<RuntimeServices>(); mRuntimeServices = std::make_unique<RuntimeServices>();
mRuntimeUpdateController = std::make_unique<RuntimeUpdateController>(
*mRuntimeStore,
*mRuntimeCoordinator,
*mRuntimeServices,
*mRenderEngine,
*mShaderBuildQueue,
*mVideoBackend);
} }
OpenGLComposite::~OpenGLComposite() OpenGLComposite::~OpenGLComposite()
@@ -245,7 +256,7 @@ bool OpenGLComposite::InitOpenGLState()
mRenderEngine->ResetTemporalHistoryState(); mRenderEngine->ResetTemporalHistoryState();
mRenderEngine->ResetShaderFeedbackState(); mRenderEngine->ResetShaderFeedbackState();
broadcastRuntimeState(); mRuntimeUpdateController->BroadcastRuntimeState();
mRuntimeServices->BeginPolling(*mRuntimeCoordinator); mRuntimeServices->BeginPolling(*mRuntimeCoordinator);
return true; return true;
} }
@@ -273,7 +284,8 @@ bool OpenGLComposite::Stop()
bool OpenGLComposite::ReloadShader(bool preserveFeedbackState) bool OpenGLComposite::ReloadShader(bool preserveFeedbackState)
{ {
return mRuntimeCoordinator && return mRuntimeCoordinator &&
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->RequestShaderReload(preserveFeedbackState)); mRuntimeUpdateController &&
mRuntimeUpdateController->ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->RequestShaderReload(preserveFeedbackState));
} }
bool OpenGLComposite::RequestScreenshot(std::string& error) bool OpenGLComposite::RequestScreenshot(std::string& error)
@@ -285,7 +297,8 @@ bool OpenGLComposite::RequestScreenshot(std::string& error)
void OpenGLComposite::renderEffect() void OpenGLComposite::renderEffect()
{ {
ProcessRuntimePollResults(); if (mRuntimeUpdateController)
mRuntimeUpdateController->ProcessRuntimeWork();
std::vector<RuntimeServices::AppliedOscUpdate> appliedOscUpdates; std::vector<RuntimeServices::AppliedOscUpdate> appliedOscUpdates;
std::vector<RuntimeServices::CompletedOscCommit> completedOscCommits; std::vector<RuntimeServices::CompletedOscCommit> completedOscCommits;
if (mRuntimeServices) if (mRuntimeServices)
@@ -400,105 +413,7 @@ std::filesystem::path OpenGLComposite::BuildScreenshotPath() const
return root / "screenshots" / filename.str(); 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() bool OpenGLComposite::CheckOpenGLExtensions()
{ {
return true; return true;
} }
////////////////////////////////////////////

View File

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

View File

@@ -1,5 +1,9 @@
#include "OpenGLComposite.h" #include "OpenGLComposite.h"
#include "RuntimeCoordinator.h"
#include "RuntimeJson.h"
#include "RuntimeServices.h" #include "RuntimeServices.h"
#include "RuntimeStore.h"
#include "RuntimeUpdateController.h"
std::string OpenGLComposite::GetRuntimeStateJson() const std::string OpenGLComposite::GetRuntimeStateJson() const
{ {
@@ -39,37 +43,43 @@ std::string OpenGLComposite::GetOscAddress() const
bool OpenGLComposite::AddLayer(const std::string& shaderId, std::string& error) bool OpenGLComposite::AddLayer(const std::string& shaderId, std::string& error)
{ {
return mRuntimeCoordinator && return mRuntimeCoordinator &&
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->AddLayer(shaderId), &error); mRuntimeUpdateController &&
mRuntimeUpdateController->ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->AddLayer(shaderId), &error);
} }
bool OpenGLComposite::RemoveLayer(const std::string& layerId, std::string& error) bool OpenGLComposite::RemoveLayer(const std::string& layerId, std::string& error)
{ {
return mRuntimeCoordinator && 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) bool OpenGLComposite::MoveLayer(const std::string& layerId, int direction, std::string& error)
{ {
return mRuntimeCoordinator && 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) bool OpenGLComposite::MoveLayerToIndex(const std::string& layerId, std::size_t targetIndex, std::string& error)
{ {
return mRuntimeCoordinator && 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) bool OpenGLComposite::SetLayerBypass(const std::string& layerId, bool bypassed, std::string& error)
{ {
return mRuntimeCoordinator && 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) bool OpenGLComposite::SetLayerShader(const std::string& layerId, const std::string& shaderId, std::string& error)
{ {
return mRuntimeCoordinator && 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) 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 false;
return mRuntimeCoordinator && 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) 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 false;
return mRuntimeCoordinator && 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) bool OpenGLComposite::ResetLayerParameters(const std::string& layerId, std::string& error)
{ {
return mRuntimeCoordinator && return mRuntimeCoordinator &&
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->ResetLayerParameters(layerId), &error); mRuntimeUpdateController &&
mRuntimeUpdateController->ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->ResetLayerParameters(layerId), &error);
} }
bool OpenGLComposite::SaveStackPreset(const std::string& presetName, std::string& error) bool OpenGLComposite::SaveStackPreset(const std::string& presetName, std::string& error)
{ {
return mRuntimeCoordinator && return mRuntimeCoordinator &&
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->SaveStackPreset(presetName), &error); mRuntimeUpdateController &&
mRuntimeUpdateController->ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->SaveStackPreset(presetName), &error);
} }
bool OpenGLComposite::LoadStackPreset(const std::string& presetName, std::string& error) bool OpenGLComposite::LoadStackPreset(const std::string& presetName, std::string& error)
{ {
return mRuntimeCoordinator && 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); ApplyOscOverlays(renderSnapshot.states, true, oscSmoothing, commitRequests);
if (mCachedParameterStateVersion != versions.parameterStateVersion && if (mCachedParameterStateVersion != versions.parameterStateVersion &&
mRuntimeSnapshotProvider.TryRefreshSnapshotParameters(renderSnapshot)) mRuntimeSnapshotProvider.TryRefreshPublishedSnapshotParameters(renderSnapshot))
{ {
mCachedParameterStateVersion = renderSnapshot.versions.parameterStateVersion; mCachedParameterStateVersion = renderSnapshot.versions.parameterStateVersion;
ApplyOscOverlays(renderSnapshot.states, true, oscSmoothing, commitRequests); ApplyOscOverlays(renderSnapshot.states, true, oscSmoothing, commitRequests);
@@ -392,7 +392,7 @@ bool RenderEngine::ResolveRenderLayerStates(
} }
RuntimeRenderStateSnapshot renderSnapshot; RuntimeRenderStateSnapshot renderSnapshot;
if (mRuntimeSnapshotProvider.TryGetRenderStateSnapshot(renderWidth, renderHeight, renderSnapshot)) if (mRuntimeSnapshotProvider.TryPublishRenderStateSnapshot(renderWidth, renderHeight, renderSnapshot))
{ {
mCachedLayerRenderStates = renderSnapshot.states; mCachedLayerRenderStates = renderSnapshot.states;
mCachedRenderStateVersion = renderSnapshot.versions.renderStateVersion; 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) bool OpenGLShaderPrograms::CompileLayerPrograms(unsigned inputFrameWidth, unsigned inputFrameHeight, int errorMessageSize, char* errorMessage)
{ {
const RuntimeRenderStateSnapshot renderSnapshot = const RuntimeRenderStateSnapshot renderSnapshot =
mRuntimeSnapshotProvider.GetRenderStateSnapshot(inputFrameWidth, inputFrameHeight); mRuntimeSnapshotProvider.PublishRenderStateSnapshot(inputFrameWidth, inputFrameHeight);
const std::vector<RuntimeRenderState>& layerStates = renderSnapshot.states; const std::vector<RuntimeRenderState>& layerStates = renderSnapshot.states;
std::string temporalError; std::string temporalError;
const unsigned historyCap = mRuntimeSnapshotProvider.GetMaxTemporalHistoryFrames(); const unsigned historyCap = mRuntimeSnapshotProvider.GetMaxTemporalHistoryFrames();

View File

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

View File

@@ -1,10 +1,8 @@
#include "RuntimeCoordinator.h" #include "RuntimeCoordinator.h"
#include "RuntimeParameterUtils.h"
#include "RuntimeStore.h" #include "RuntimeStore.h"
#include <algorithm>
#include <chrono>
RuntimeCoordinator::RuntimeCoordinator(RuntimeStore& runtimeStore) : RuntimeCoordinator::RuntimeCoordinator(RuntimeStore& runtimeStore) :
mRuntimeStore(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 RuntimeCoordinator::BuildParameterMutationById(const std::string& layerId, const std::string& parameterId, const JsonValue& newValue,
bool persistState, ResolvedParameterMutation& mutation, std::string& error) const bool persistState, ResolvedParameterMutation& mutation, std::string& error) const
{ {
std::lock_guard<std::mutex> lock(mRuntimeStore.mRuntimeHost.mMutex); RuntimeStore::StoredParameterSnapshot snapshot;
if (!mRuntimeStore.TryGetStoredParameterById(layerId, parameterId, snapshot, error))
RuntimeHost::LayerPersistentState* layer = mRuntimeStore.mRuntimeHost.FindLayerById(layerId);
if (!layer)
{
error = "Unknown layer id: " + layerId;
return false; return false;
}
auto shaderIt = mRuntimeStore.mRuntimeHost.mPackagesById.find(layer->shaderId); return BuildParameterMutationFromSnapshot(snapshot.layerId, snapshot.definition, snapshot.currentValue, snapshot.hasCurrentValue,
if (shaderIt == mRuntimeStore.mRuntimeHost.mPackagesById.end()) newValue, persistState, mutation, error);
{
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 RuntimeCoordinator::BuildParameterMutationByControlKey(const std::string& layerKey, const std::string& parameterKey, const JsonValue& newValue,
bool persistState, ResolvedParameterMutation& mutation, std::string& error) const bool persistState, ResolvedParameterMutation& mutation, std::string& error) const
{ {
std::lock_guard<std::mutex> lock(mRuntimeStore.mRuntimeHost.mMutex); RuntimeStore::StoredParameterSnapshot snapshot;
if (!mRuntimeStore.TryGetStoredParameterByControlKey(layerKey, parameterKey, snapshot, error))
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 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 bool persistState, ResolvedParameterMutation& mutation, std::string& error) const
{ {
mutation.layerId = layer.id; mutation.layerId = layerId;
mutation.parameterId = definition.id; mutation.parameterId = definition.id;
mutation.persistState = persistState; mutation.persistState = persistState;
if (definition.type == ShaderParameterType::Trigger) if (definition.type == ShaderParameterType::Trigger)
{ {
const auto existingValue = layer.parameterValues.find(definition.id); const double previousCount = !hasCurrentValue || currentValue.numberValues.empty()
const double previousCount = existingValue == layer.parameterValues.end() || existingValue->second.numberValues.empty()
? 0.0 ? 0.0
: existingValue->second.numberValues[0]; : currentValue.numberValues[0];
const double triggerTime = std::chrono::duration_cast<std::chrono::duration<double>>( const double triggerTime = mRuntimeStore.GetRuntimeElapsedSeconds();
std::chrono::steady_clock::now() - mRuntimeStore.mRuntimeHost.mStartTime).count();
mutation.value.numberValues = { previousCount + 1.0, triggerTime }; mutation.value.numberValues = { previousCount + 1.0, triggerTime };
mutation.persistState = false; mutation.persistState = false;
return true; return true;
} }
return mRuntimeStore.mRuntimeHost.NormalizeAndValidateValue(definition, newValue, mutation.value, error); return NormalizeAndValidateParameterValue(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 bool RuntimeCoordinator::ValidateLayerExists(const std::string& layerId, std::string& error) const
{ {
std::lock_guard<std::mutex> lock(mRuntimeStore.mRuntimeHost.mMutex); if (mRuntimeStore.HasStoredLayer(layerId))
if (HasLayerLocked(layerId))
return true; return true;
error = "Unknown layer id: " + layerId; 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 bool RuntimeCoordinator::ValidateShaderExists(const std::string& shaderId, std::string& error) const
{ {
std::lock_guard<std::mutex> lock(mRuntimeStore.mRuntimeHost.mMutex); if (mRuntimeStore.HasStoredShader(shaderId))
if (HasShaderLocked(shaderId))
return true; return true;
error = "Unknown shader id: " + shaderId; 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 bool RuntimeCoordinator::ResolveLayerMove(const std::string& layerId, int direction, bool& shouldMove, std::string& error) const
{ {
std::lock_guard<std::mutex> lock(mRuntimeStore.mRuntimeHost.mMutex); return mRuntimeStore.ResolveStoredLayerMove(layerId, direction, shouldMove, error);
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 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); return mRuntimeStore.ResolveStoredLayerMoveToIndex(layerId, targetIndex, shouldMove, error);
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 bool RuntimeCoordinator::ValidatePresetName(const std::string& presetName, std::string& error) const
{ {
if (!mRuntimeStore.MakeSafePresetFileStem(presetName).empty()) if (mRuntimeStore.IsValidStackPresetName(presetName))
return true; return true;
error = "Preset name must include at least one letter or number."; error = "Preset name must include at least one letter or number.";

View File

@@ -1,7 +1,7 @@
#pragma once #pragma once
#include "RuntimeHost.h"
#include "RuntimeJson.h" #include "RuntimeJson.h"
#include "ShaderTypes.h"
#include <atomic> #include <atomic>
#include <cstddef> #include <cstddef>
@@ -80,10 +80,9 @@ private:
bool persistState, ResolvedParameterMutation& mutation, std::string& error) const; bool persistState, ResolvedParameterMutation& mutation, std::string& error) const;
bool BuildParameterMutationByControlKey(const std::string& layerKey, const std::string& parameterKey, const JsonValue& newValue, bool BuildParameterMutationByControlKey(const std::string& layerKey, const std::string& parameterKey, const JsonValue& newValue,
bool persistState, ResolvedParameterMutation& mutation, std::string& error) const; 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 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 ValidateLayerExists(const std::string& layerId, std::string& error) const;
bool ValidateShaderExists(const std::string& shaderId, 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 ResolveLayerMove(const std::string& layerId, int direction, bool& shouldMove, std::string& error) const;

View File

@@ -75,11 +75,14 @@ void RuntimeSnapshotProvider::AdvanceFrame()
mRuntimeStore.AdvanceFrameCounter(); mRuntimeStore.AdvanceFrameCounter();
} }
RuntimeRenderStateSnapshot RuntimeSnapshotProvider::GetRenderStateSnapshot(unsigned outputWidth, unsigned outputHeight) const RuntimeRenderStateSnapshot RuntimeSnapshotProvider::PublishRenderStateSnapshot(unsigned outputWidth, unsigned outputHeight) const
{ {
for (;;) for (;;)
{ {
const RuntimeSnapshotVersions versionsBefore = GetVersions(); const RuntimeSnapshotVersions versionsBefore = GetVersions();
RuntimeRenderStateSnapshot publishedSnapshot;
if (TryGetPublishedRenderStateSnapshot(outputWidth, outputHeight, versionsBefore, publishedSnapshot))
return publishedSnapshot;
RuntimeRenderStateSnapshot snapshot; RuntimeRenderStateSnapshot snapshot;
snapshot.outputWidth = outputWidth; snapshot.outputWidth = outputWidth;
@@ -91,14 +94,17 @@ RuntimeRenderStateSnapshot RuntimeSnapshotProvider::GetRenderStateSnapshot(unsig
versionsBefore.parameterStateVersion == versionsAfter.parameterStateVersion) versionsBefore.parameterStateVersion == versionsAfter.parameterStateVersion)
{ {
snapshot.versions = versionsAfter; snapshot.versions = versionsAfter;
StorePublishedRenderStateSnapshot(snapshot);
return 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(); const RuntimeSnapshotVersions versionsBefore = GetVersions();
if (TryGetPublishedRenderStateSnapshot(outputWidth, outputHeight, versionsBefore, snapshot))
return true;
std::vector<RuntimeRenderState> states; std::vector<RuntimeRenderState> states;
if (!mRuntimeStore.TryBuildLayerRenderStates(outputWidth, outputHeight, states)) if (!mRuntimeStore.TryBuildLayerRenderStates(outputWidth, outputHeight, states))
@@ -115,10 +121,11 @@ bool RuntimeSnapshotProvider::TryGetRenderStateSnapshot(unsigned outputWidth, un
snapshot.outputHeight = outputHeight; snapshot.outputHeight = outputHeight;
snapshot.versions = versionsAfter; snapshot.versions = versionsAfter;
snapshot.states = std::move(states); snapshot.states = std::move(states);
StorePublishedRenderStateSnapshot(snapshot);
return true; return true;
} }
bool RuntimeSnapshotProvider::TryRefreshSnapshotParameters(RuntimeRenderStateSnapshot& snapshot) const bool RuntimeSnapshotProvider::TryRefreshPublishedSnapshotParameters(RuntimeRenderStateSnapshot& snapshot) const
{ {
const uint64_t expectedRenderStateVersion = snapshot.versions.renderStateVersion; const uint64_t expectedRenderStateVersion = snapshot.versions.renderStateVersion;
if (!mRuntimeStore.TryRefreshLayerParameters(snapshot.states)) if (!mRuntimeStore.TryRefreshLayerParameters(snapshot.states))
@@ -129,6 +136,7 @@ bool RuntimeSnapshotProvider::TryRefreshSnapshotParameters(RuntimeRenderStateSna
return false; return false;
snapshot.versions = versions; snapshot.versions = versions;
StorePublishedRenderStateSnapshot(snapshot);
return true; return true;
} }
@@ -136,3 +144,33 @@ void RuntimeSnapshotProvider::RefreshDynamicRenderStateFields(std::vector<Runtim
{ {
mRuntimeStore.RefreshDynamicRenderStateFields(states); 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 "RuntimeStore.h"
#include <cstdint> #include <cstdint>
#include <mutex>
#include <string> #include <string>
#include <vector> #include <vector>
@@ -29,11 +30,20 @@ public:
unsigned GetMaxTemporalHistoryFrames() const; unsigned GetMaxTemporalHistoryFrames() const;
RuntimeSnapshotVersions GetVersions() const; RuntimeSnapshotVersions GetVersions() const;
void AdvanceFrame(); void AdvanceFrame();
RuntimeRenderStateSnapshot GetRenderStateSnapshot(unsigned outputWidth, unsigned outputHeight) const; RuntimeRenderStateSnapshot PublishRenderStateSnapshot(unsigned outputWidth, unsigned outputHeight) const;
bool TryGetRenderStateSnapshot(unsigned outputWidth, unsigned outputHeight, RuntimeRenderStateSnapshot& snapshot) const; bool TryPublishRenderStateSnapshot(unsigned outputWidth, unsigned outputHeight, RuntimeRenderStateSnapshot& snapshot) const;
bool TryRefreshSnapshotParameters(RuntimeRenderStateSnapshot& snapshot) const; bool TryRefreshPublishedSnapshotParameters(RuntimeRenderStateSnapshot& snapshot) const;
void RefreshDynamicRenderStateFields(std::vector<RuntimeRenderState>& states) const; void RefreshDynamicRenderStateFields(std::vector<RuntimeRenderState>& states) const;
private: 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; 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 #pragma once
#include "RuntimeHost.h" #include "HealthTelemetry.h"
#include "RuntimeJson.h"
#include "ShaderTypes.h"
#include <atomic>
#include <chrono>
#include <cstdint> #include <cstdint>
#include <filesystem> #include <filesystem>
#include <map>
#include <mutex>
#include <string> #include <string>
#include <vector>
class RuntimeSnapshotProvider; class RuntimeSnapshotProvider;
class RuntimeStore class RuntimeStore
{ {
public: 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(); RuntimeStore();
HealthTelemetry& GetHealthTelemetry(); HealthTelemetry& GetHealthTelemetry();
const HealthTelemetry& GetHealthTelemetry() const; const HealthTelemetry& GetHealthTelemetry() const;
@@ -29,6 +74,14 @@ public:
bool ResetStoredLayerParameterValues(const std::string& layerId, std::string& error); bool ResetStoredLayerParameterValues(const std::string& layerId, std::string& error);
bool SaveStackPresetSnapshot(const std::string& presetName, std::string& error) const; bool SaveStackPresetSnapshot(const std::string& presetName, std::string& error) const;
bool LoadStackPresetSnapshot(const std::string& presetName, std::string& error); 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& GetRuntimeRepositoryRoot() const;
const std::filesystem::path& GetRuntimeUiRoot() const; const std::filesystem::path& GetRuntimeUiRoot() const;
@@ -51,7 +104,6 @@ public:
void ClearReloadRequest(); void ClearReloadRequest();
private: private:
friend class RuntimeCoordinator;
friend class RuntimeSnapshotProvider; friend class RuntimeSnapshotProvider;
bool LoadConfig(std::string& error); bool LoadConfig(std::string& error);
bool LoadPersistentState(std::string& error); bool LoadPersistentState(std::string& error);
@@ -63,7 +115,7 @@ private:
std::vector<std::string> GetStackPresetNamesLocked() const; std::vector<std::string> GetStackPresetNamesLocked() const;
std::string MakeSafePresetFileStem(const std::string& presetName) const; std::string MakeSafePresetFileStem(const std::string& presetName) const;
bool TryResolveStoredLayerAndParameterByControlKeyLocked(const std::string& layerKey, const std::string& parameterKey, 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; std::vector<ShaderParameterDefinition>::const_iterator& parameterIt, std::string& error) const;
bool CopyShaderPackageForStoredLayer(const std::string& layerId, ShaderPackage& shaderPackage, 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, void GetShaderCompilerInputs(std::filesystem::path& repoRoot, std::filesystem::path& wrapperPath,
@@ -80,6 +132,48 @@ private:
void RefreshDynamicRenderStateFieldsLocked(std::vector<RuntimeRenderState>& states) const; void RefreshDynamicRenderStateFieldsLocked(std::vector<RuntimeRenderState>& states) const;
JsonValue BuildRuntimeStateValue() const; JsonValue BuildRuntimeStateValue() const;
JsonValue SerializeLayerStack() 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;
}; };

View File

@@ -133,12 +133,16 @@ These are still compatibility seams, not a completed subsystem extraction. Some
- render-state and shader-build reads in `OpenGLComposite.cpp`, `OpenGLShaderPrograms.cpp`, and `ShaderBuildQueue.cpp` now route through `RuntimeSnapshotProvider` - render-state and shader-build reads in `OpenGLComposite.cpp`, `OpenGLShaderPrograms.cpp`, and `ShaderBuildQueue.cpp` now route through `RuntimeSnapshotProvider`
- `RuntimeSnapshotProvider` now depends on `RuntimeStore` rather than sharing `RuntimeHost` directly - `RuntimeSnapshotProvider` now depends on `RuntimeStore` rather than sharing `RuntimeHost` directly
- render-state assembly, cached parameter refresh, and frame-context application now flow through `RuntimeSnapshotProvider` and store-owned snapshot helpers instead of `RuntimeHost` public APIs - render-state assembly, cached parameter refresh, and frame-context application now flow through `RuntimeSnapshotProvider` and store-owned snapshot helpers instead of `RuntimeHost` public APIs
- `RuntimeSnapshotProvider` now publishes versioned render snapshot objects and serves matching consumers from the last published snapshot
- service ingress and polling coordination now route through `ControlServices` - service ingress and polling coordination now route through `ControlServices`
- `ControlServices` now queues coordinator results for OSC commit and file-poll outcomes instead of directly deciding runtime/store policy - `ControlServices` now queues coordinator results for OSC commit and file-poll outcomes instead of directly deciding runtime/store policy
- timing and status writes now route through `HealthTelemetry` - timing and status writes now route through `HealthTelemetry`
- `HealthTelemetry` now owns the live signal, video-I/O, and performance snapshots directly instead of `RuntimeHost` keeping those backing fields - `HealthTelemetry` now owns the live signal, video-I/O, and performance snapshots directly instead of `RuntimeHost` keeping those backing fields
- render-side frame advancement and render-performance reporting now flow through `RuntimeSnapshotProvider` and `HealthTelemetry` instead of directly through `RuntimeHost` - render-side frame advancement and render-performance reporting now flow through `RuntimeSnapshotProvider` and `HealthTelemetry` instead of directly through `RuntimeHost`
- `RuntimeStore` now owns its durable/session backing fields directly instead of wrapping a compatibility `RuntimeHost` object
- `RuntimeCoordinator` now uses explicit `RuntimeStore` query APIs/read models instead of friendship or direct store-internal access
- live OSC overlay state and smoothing/commit decisions now live under `RenderEngine` instead of `OpenGLComposite` - live OSC overlay state and smoothing/commit decisions now live under `RenderEngine` instead of `OpenGLComposite`
- coordinator result application, shader-build requests, ready-build application, and runtime-state broadcasts now route through `RuntimeUpdateController` instead of being interpreted directly by `OpenGLComposite`
- `OpenGLComposite` now owns a `RenderEngine` seam for renderer, pipeline, render-pass, and shader-program responsibilities - `OpenGLComposite` now owns a `RenderEngine` seam for renderer, pipeline, render-pass, and shader-program responsibilities
- `OpenGLComposite` now owns a `VideoBackend` seam for device/session ownership and callback wiring - `OpenGLComposite` now owns a `VideoBackend` seam for device/session ownership and callback wiring
- `OpenGLVideoIOBridge` now acts as an explicit compatibility adapter between `VideoBackend` and `RenderEngine`, instead of `OpenGLComposite` directly owning both sides - `OpenGLVideoIOBridge` now acts as an explicit compatibility adapter between `VideoBackend` and `RenderEngine`, instead of `OpenGLComposite` directly owning both sides
@@ -147,9 +151,6 @@ That means the next extraction work can focus on moving responsibility behind th
Remaining extraction work includes: Remaining extraction work includes:
- replacing the compatibility `RuntimeHost` backing object still owned inside `RuntimeStore`
- removing coordinator friendship/access to store-internal host data
- publishing render snapshots as explicit immutable or near-immutable objects rather than building them from store internals on demand
- moving persistence to an asynchronous writer in a later phase - moving persistence to an asynchronous writer in a later phase
- replacing polling/shared-object coordination with the planned internal event model - replacing polling/shared-object coordination with the planned internal event model

View File

@@ -481,7 +481,7 @@ Recommended tests:
Its contract is: Its contract is:
- build from store-owned state - build from store-owned state
- publish immutable or near-immutable render snapshots - publish immutable or near-immutable render snapshots; the current implementation keeps the last matching versioned snapshot in `RuntimeSnapshotProvider`
- version them explicitly - version them explicitly
- keep frame-local timing separate - keep frame-local timing separate
- give render a cheap, lock-light read path - give render a cheap, lock-light read path

View File

@@ -405,7 +405,7 @@ Initial likely contents:
- preset load/save access - preset load/save access
- package catalog read access - package catalog read access
At this stage, `RuntimeHost` may still be the implementation behind the façade. This stage is now past the initial compatibility point: `RuntimeStore` owns its durable/session backing fields directly rather than wrapping a `RuntimeHost` object.
### Step 2: Move Pure Persistence Helpers First ### Step 2: Move Pure Persistence Helpers First