further phase 1
This commit is contained in:
@@ -35,9 +35,9 @@ bool ControlServices::Start(OpenGLComposite& composite, RuntimeHost& runtimeHost
|
||||
return true;
|
||||
}
|
||||
|
||||
void ControlServices::BeginPolling(RuntimeHost& runtimeHost, RuntimeStore& runtimeStore)
|
||||
void ControlServices::BeginPolling(RuntimeStore& runtimeStore)
|
||||
{
|
||||
StartPolling(runtimeHost, runtimeStore);
|
||||
StartPolling(runtimeStore);
|
||||
}
|
||||
|
||||
void ControlServices::Stop()
|
||||
@@ -175,12 +175,12 @@ RuntimePollEvents ControlServices::ConsumePollEvents()
|
||||
return events;
|
||||
}
|
||||
|
||||
void ControlServices::StartPolling(RuntimeHost& runtimeHost, RuntimeStore& runtimeStore)
|
||||
void ControlServices::StartPolling(RuntimeStore& runtimeStore)
|
||||
{
|
||||
if (mPollRunning.exchange(true))
|
||||
return;
|
||||
|
||||
mPollThread = std::thread([this, &runtimeHost, &runtimeStore]() { PollLoop(runtimeHost, runtimeStore); });
|
||||
mPollThread = std::thread([this, &runtimeStore]() { PollLoop(runtimeStore); });
|
||||
}
|
||||
|
||||
void ControlServices::StopPolling()
|
||||
@@ -192,7 +192,7 @@ void ControlServices::StopPolling()
|
||||
mPollThread.join();
|
||||
}
|
||||
|
||||
void ControlServices::PollLoop(RuntimeHost& runtimeHost, RuntimeStore& runtimeStore)
|
||||
void ControlServices::PollLoop(RuntimeStore& runtimeStore)
|
||||
{
|
||||
while (mPollRunning)
|
||||
{
|
||||
@@ -226,7 +226,7 @@ void ControlServices::PollLoop(RuntimeHost& runtimeHost, RuntimeStore& runtimeSt
|
||||
bool registryChanged = false;
|
||||
bool reloadRequested = false;
|
||||
std::string runtimeError;
|
||||
if (!runtimeHost.PollFileChanges(registryChanged, reloadRequested, runtimeError))
|
||||
if (!runtimeStore.PollStoredFileChanges(registryChanged, reloadRequested, runtimeError))
|
||||
{
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mPollErrorMutex);
|
||||
|
||||
@@ -46,7 +46,7 @@ public:
|
||||
~ControlServices();
|
||||
|
||||
bool Start(OpenGLComposite& composite, RuntimeHost& runtimeHost, std::string& error);
|
||||
void BeginPolling(RuntimeHost& runtimeHost, RuntimeStore& runtimeStore);
|
||||
void BeginPolling(RuntimeStore& runtimeStore);
|
||||
void Stop();
|
||||
void BroadcastState();
|
||||
void RequestBroadcastState();
|
||||
@@ -74,9 +74,9 @@ private:
|
||||
uint64_t generation = 0;
|
||||
};
|
||||
|
||||
void StartPolling(RuntimeHost& runtimeHost, RuntimeStore& runtimeStore);
|
||||
void StartPolling(RuntimeStore& runtimeStore);
|
||||
void StopPolling();
|
||||
void PollLoop(RuntimeHost& runtimeHost, RuntimeStore& runtimeStore);
|
||||
void PollLoop(RuntimeStore& runtimeStore);
|
||||
|
||||
std::unique_ptr<ControlServer> mControlServer;
|
||||
std::unique_ptr<OscServer> mOscServer;
|
||||
|
||||
@@ -17,10 +17,10 @@ bool RuntimeServices::Start(OpenGLComposite& composite, RuntimeHost& runtimeHost
|
||||
return mControlServices && mControlServices->Start(composite, runtimeHost, error);
|
||||
}
|
||||
|
||||
void RuntimeServices::BeginPolling(RuntimeHost& runtimeHost, RuntimeStore& runtimeStore)
|
||||
void RuntimeServices::BeginPolling(RuntimeStore& runtimeStore)
|
||||
{
|
||||
if (mControlServices)
|
||||
mControlServices->BeginPolling(runtimeHost, runtimeStore);
|
||||
mControlServices->BeginPolling(runtimeStore);
|
||||
}
|
||||
|
||||
void RuntimeServices::Stop()
|
||||
|
||||
@@ -18,7 +18,7 @@ public:
|
||||
~RuntimeServices();
|
||||
|
||||
bool Start(OpenGLComposite& composite, RuntimeHost& runtimeHost, std::string& error);
|
||||
void BeginPolling(RuntimeHost& runtimeHost, RuntimeStore& runtimeStore);
|
||||
void BeginPolling(RuntimeStore& runtimeStore);
|
||||
void Stop();
|
||||
void BroadcastState();
|
||||
void RequestBroadcastState();
|
||||
|
||||
@@ -28,7 +28,6 @@ namespace
|
||||
|
||||
OpenGLComposite::OpenGLComposite(HWND hWnd, HDC hDC, HGLRC hRC) :
|
||||
hGLWnd(hWnd), hGLDC(hDC), hGLRC(hRC),
|
||||
mUseCommittedLayerStates(false),
|
||||
mScreenshotRequested(false)
|
||||
{
|
||||
InitializeCriticalSection(&pMutex);
|
||||
@@ -121,9 +120,11 @@ bool OpenGLComposite::InitVideoIO()
|
||||
goto error;
|
||||
}
|
||||
|
||||
PublishVideoIOStatus(mVideoBackend->OutputModelName().empty()
|
||||
? "DeckLink output device selected."
|
||||
: ("Selected output device: " + mVideoBackend->OutputModelName()));
|
||||
mVideoBackend->PublishStatus(
|
||||
mRuntimeStore && mRuntimeStore->IsExternalKeyingConfigured(),
|
||||
mVideoBackend->OutputModelName().empty()
|
||||
? "DeckLink output device selected."
|
||||
: ("Selected output device: " + mVideoBackend->OutputModelName()));
|
||||
|
||||
// Resize window to match output video frame, but scale large formats down by half for viewing.
|
||||
if (mVideoBackend->OutputFrameWidth() < 1920)
|
||||
@@ -135,21 +136,17 @@ bool OpenGLComposite::InitVideoIO()
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
if (!mVideoBackend->HasInputDevice() && mRuntimeHost)
|
||||
{
|
||||
mRuntimeHost->GetHealthTelemetry().ReportSignalStatus(
|
||||
false,
|
||||
mVideoBackend->InputFrameWidth(),
|
||||
mVideoBackend->InputFrameHeight(),
|
||||
mVideoBackend->InputDisplayModeName());
|
||||
}
|
||||
if (!mVideoBackend->HasInputDevice())
|
||||
mVideoBackend->ReportNoInputDeviceSignalStatus();
|
||||
|
||||
if (!mVideoBackend->ConfigureOutput(videoModes.output, mRuntimeStore && mRuntimeStore->IsExternalKeyingConfigured(), initFailureReason))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
|
||||
PublishVideoIOStatus(mVideoBackend->StatusMessage());
|
||||
mVideoBackend->PublishStatus(
|
||||
mRuntimeStore && mRuntimeStore->IsExternalKeyingConfigured(),
|
||||
mVideoBackend->StatusMessage());
|
||||
|
||||
return true;
|
||||
|
||||
@@ -194,25 +191,6 @@ void OpenGLComposite::resizeWindow(int width, int height)
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLComposite::PublishVideoIOStatus(const std::string& statusMessage)
|
||||
{
|
||||
if (!mRuntimeHost)
|
||||
return;
|
||||
|
||||
if (!statusMessage.empty())
|
||||
mVideoBackend->SetStatusMessage(statusMessage);
|
||||
|
||||
mRuntimeHost->GetHealthTelemetry().ReportVideoIOStatus(
|
||||
"decklink",
|
||||
mVideoBackend->OutputModelName(),
|
||||
mVideoBackend->SupportsInternalKeying(),
|
||||
mVideoBackend->SupportsExternalKeying(),
|
||||
mVideoBackend->KeyerInterfaceAvailable(),
|
||||
mRuntimeStore ? mRuntimeStore->IsExternalKeyingConfigured() : false,
|
||||
mVideoBackend->ExternalKeyingActive(),
|
||||
mVideoBackend->StatusMessage());
|
||||
}
|
||||
|
||||
bool OpenGLComposite::InitOpenGLState()
|
||||
{
|
||||
if (! ResolveGLExtensions())
|
||||
@@ -264,13 +242,12 @@ bool OpenGLComposite::InitOpenGLState()
|
||||
return false;
|
||||
}
|
||||
mRuntimeStore->SetCompileStatus(true, "Shader layers compiled successfully.");
|
||||
mUseCommittedLayerStates = false;
|
||||
|
||||
mRenderEngine->ResetTemporalHistoryState();
|
||||
mRenderEngine->ResetShaderFeedbackState();
|
||||
|
||||
broadcastRuntimeState();
|
||||
mRuntimeServices->BeginPolling(*mRuntimeHost, *mRuntimeStore);
|
||||
mRuntimeServices->BeginPolling(*mRuntimeStore);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -287,7 +264,9 @@ bool OpenGLComposite::Stop()
|
||||
const bool wasExternalKeyingActive = mVideoBackend->ExternalKeyingActive();
|
||||
mVideoBackend->Stop();
|
||||
if (wasExternalKeyingActive)
|
||||
PublishVideoIOStatus("External keying has been disabled.");
|
||||
mVideoBackend->PublishStatus(
|
||||
mRuntimeStore && mRuntimeStore->IsExternalKeyingConfigured(),
|
||||
"External keying has been disabled.");
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -340,7 +319,7 @@ void OpenGLComposite::renderEffect()
|
||||
std::vector<RenderEngine::OscOverlayCommitRequest> overlayCommitRequests;
|
||||
const double smoothing = mRuntimeStore ? mRuntimeStore->GetConfiguredOscSmoothing() : 0.0;
|
||||
mRenderEngine->ResolveRenderLayerStates(
|
||||
mUseCommittedLayerStates.load(),
|
||||
mRuntimeCoordinator && mRuntimeCoordinator->UseCommittedLayerStates(),
|
||||
mVideoBackend->InputFrameWidth(),
|
||||
mVideoBackend->InputFrameHeight(),
|
||||
smoothing,
|
||||
@@ -439,20 +418,20 @@ bool OpenGLComposite::ProcessRuntimePollResults()
|
||||
|
||||
if (!events.reloadRequested)
|
||||
{
|
||||
PreparedShaderBuild readyBuild;
|
||||
if (!mShaderBuildQueue || !mShaderBuildQueue->TryConsumeReadyBuild(readyBuild))
|
||||
if (!mShaderBuildQueue || !mRenderEngine)
|
||||
return true;
|
||||
|
||||
char compilerErrorMessage[1024] = {};
|
||||
if (!mRenderEngine->ApplyPreparedShaderBuild(
|
||||
readyBuild,
|
||||
const RenderEngine::PreparedShaderBuildApplyResult buildResult = mRenderEngine->TryApplyReadyShaderBuild(
|
||||
*mShaderBuildQueue,
|
||||
mVideoBackend->InputFrameWidth(),
|
||||
mVideoBackend->InputFrameHeight(),
|
||||
mRuntimeCoordinator && mRuntimeCoordinator->PreserveFeedbackOnNextShaderBuild(),
|
||||
sizeof(compilerErrorMessage),
|
||||
compilerErrorMessage))
|
||||
mRuntimeCoordinator && mRuntimeCoordinator->PreserveFeedbackOnNextShaderBuild());
|
||||
if (!buildResult.hadReadyBuild)
|
||||
return true;
|
||||
|
||||
if (!buildResult.applied)
|
||||
{
|
||||
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->HandlePreparedShaderBuildFailure(compilerErrorMessage));
|
||||
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->HandlePreparedShaderBuildFailure(buildResult.errorMessage));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -487,18 +466,8 @@ bool OpenGLComposite::ApplyRuntimeCoordinatorResult(const RuntimeCoordinatorResu
|
||||
if (result.clearReloadRequest && mRuntimeStore)
|
||||
mRuntimeStore->ClearReloadRequest();
|
||||
|
||||
switch (result.committedStateMode)
|
||||
{
|
||||
case RuntimeCoordinatorCommittedStateMode::UseCommittedStates:
|
||||
mUseCommittedLayerStates = true;
|
||||
break;
|
||||
case RuntimeCoordinatorCommittedStateMode::UseLiveSnapshots:
|
||||
mUseCommittedLayerStates = false;
|
||||
break;
|
||||
case RuntimeCoordinatorCommittedStateMode::Unchanged:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (mRuntimeCoordinator)
|
||||
mRuntimeCoordinator->ApplyCommittedStateMode(result.committedStateMode);
|
||||
|
||||
if (result.clearTransientOscState)
|
||||
{
|
||||
@@ -508,7 +477,8 @@ bool OpenGLComposite::ApplyRuntimeCoordinatorResult(const RuntimeCoordinatorResu
|
||||
mRuntimeServices->ClearOscState();
|
||||
}
|
||||
|
||||
ApplyRuntimeCoordinatorRenderReset(result.renderResetScope);
|
||||
if (mRenderEngine)
|
||||
mRenderEngine->ApplyRuntimeCoordinatorRenderReset(result.renderResetScope);
|
||||
|
||||
if (result.shaderBuildRequested)
|
||||
RequestShaderBuild();
|
||||
@@ -519,26 +489,6 @@ bool OpenGLComposite::ApplyRuntimeCoordinatorResult(const RuntimeCoordinatorResu
|
||||
return true;
|
||||
}
|
||||
|
||||
void OpenGLComposite::ApplyRuntimeCoordinatorRenderReset(RuntimeCoordinatorRenderResetScope resetScope)
|
||||
{
|
||||
if (!mRenderEngine)
|
||||
return;
|
||||
|
||||
switch (resetScope)
|
||||
{
|
||||
case RuntimeCoordinatorRenderResetScope::TemporalHistoryOnly:
|
||||
mRenderEngine->ResetTemporalHistoryState();
|
||||
break;
|
||||
case RuntimeCoordinatorRenderResetScope::TemporalHistoryAndFeedback:
|
||||
mRenderEngine->ResetTemporalHistoryState();
|
||||
mRenderEngine->ResetShaderFeedbackState();
|
||||
break;
|
||||
case RuntimeCoordinatorRenderResetScope::None:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLComposite::broadcastRuntimeState()
|
||||
{
|
||||
if (mRuntimeServices)
|
||||
|
||||
@@ -67,7 +67,6 @@ public:
|
||||
private:
|
||||
void resizeWindow(int width, int height);
|
||||
bool CheckOpenGLExtensions();
|
||||
void PublishVideoIOStatus(const std::string& statusMessage);
|
||||
|
||||
HWND hGLWnd;
|
||||
HDC hGLDC;
|
||||
@@ -82,7 +81,6 @@ private:
|
||||
std::unique_ptr<ShaderBuildQueue> mShaderBuildQueue;
|
||||
std::unique_ptr<RuntimeServices> mRuntimeServices;
|
||||
std::unique_ptr<VideoBackend> mVideoBackend;
|
||||
std::atomic<bool> mUseCommittedLayerStates;
|
||||
std::atomic<bool> mScreenshotRequested;
|
||||
|
||||
bool InitOpenGLState();
|
||||
@@ -90,7 +88,6 @@ private:
|
||||
bool ProcessRuntimePollResults();
|
||||
void RequestShaderBuild();
|
||||
bool ApplyRuntimeCoordinatorResult(const RuntimeCoordinatorResult& result, std::string* error = nullptr);
|
||||
void ApplyRuntimeCoordinatorRenderReset(RuntimeCoordinatorRenderResetScope resetScope);
|
||||
void ProcessScreenshotRequest();
|
||||
std::filesystem::path BuildScreenshotPath() const;
|
||||
void broadcastRuntimeState();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "RenderEngine.h"
|
||||
|
||||
#include "RuntimeParameterUtils.h"
|
||||
#include "ShaderBuildQueue.h"
|
||||
|
||||
#include <gl/gl.h>
|
||||
|
||||
@@ -165,6 +166,35 @@ bool RenderEngine::ApplyPreparedShaderBuild(
|
||||
return true;
|
||||
}
|
||||
|
||||
RenderEngine::PreparedShaderBuildApplyResult RenderEngine::TryApplyReadyShaderBuild(
|
||||
ShaderBuildQueue& shaderBuildQueue,
|
||||
unsigned inputFrameWidth,
|
||||
unsigned inputFrameHeight,
|
||||
bool preserveFeedbackState)
|
||||
{
|
||||
PreparedShaderBuildApplyResult result;
|
||||
PreparedShaderBuild readyBuild;
|
||||
if (!shaderBuildQueue.TryConsumeReadyBuild(readyBuild))
|
||||
return result;
|
||||
|
||||
result.hadReadyBuild = true;
|
||||
char compilerErrorMessage[1024] = {};
|
||||
if (!ApplyPreparedShaderBuild(
|
||||
readyBuild,
|
||||
inputFrameWidth,
|
||||
inputFrameHeight,
|
||||
preserveFeedbackState,
|
||||
sizeof(compilerErrorMessage),
|
||||
compilerErrorMessage))
|
||||
{
|
||||
result.errorMessage = compilerErrorMessage;
|
||||
return result;
|
||||
}
|
||||
|
||||
result.applied = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
const std::vector<RuntimeRenderState>& RenderEngine::CommittedLayerStates() const
|
||||
{
|
||||
return mShaderPrograms.CommittedLayerStates();
|
||||
@@ -180,6 +210,23 @@ void RenderEngine::ResetShaderFeedbackState()
|
||||
mShaderPrograms.ResetShaderFeedbackState();
|
||||
}
|
||||
|
||||
void RenderEngine::ApplyRuntimeCoordinatorRenderReset(RuntimeCoordinatorRenderResetScope resetScope)
|
||||
{
|
||||
switch (resetScope)
|
||||
{
|
||||
case RuntimeCoordinatorRenderResetScope::TemporalHistoryOnly:
|
||||
ResetTemporalHistoryState();
|
||||
break;
|
||||
case RuntimeCoordinatorRenderResetScope::TemporalHistoryAndFeedback:
|
||||
ResetTemporalHistoryState();
|
||||
ResetShaderFeedbackState();
|
||||
break;
|
||||
case RuntimeCoordinatorRenderResetScope::None:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void RenderEngine::ClearOscOverlayState()
|
||||
{
|
||||
mOscOverlayStates.clear();
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "OpenGLRenderer.h"
|
||||
#include "OpenGLShaderPrograms.h"
|
||||
#include "HealthTelemetry.h"
|
||||
#include "RuntimeCoordinator.h"
|
||||
#include "RuntimeSnapshotProvider.h"
|
||||
|
||||
#include <windows.h>
|
||||
@@ -16,6 +17,8 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class ShaderBuildQueue;
|
||||
|
||||
class RenderEngine
|
||||
{
|
||||
public:
|
||||
@@ -46,6 +49,13 @@ public:
|
||||
uint64_t generation = 0;
|
||||
};
|
||||
|
||||
struct PreparedShaderBuildApplyResult
|
||||
{
|
||||
bool hadReadyBuild = false;
|
||||
bool applied = false;
|
||||
std::string errorMessage;
|
||||
};
|
||||
|
||||
RenderEngine(
|
||||
RuntimeSnapshotProvider& runtimeSnapshotProvider,
|
||||
HealthTelemetry& healthTelemetry,
|
||||
@@ -76,10 +86,16 @@ public:
|
||||
bool preserveFeedbackState,
|
||||
int errorMessageSize,
|
||||
char* errorMessage);
|
||||
PreparedShaderBuildApplyResult TryApplyReadyShaderBuild(
|
||||
ShaderBuildQueue& shaderBuildQueue,
|
||||
unsigned inputFrameWidth,
|
||||
unsigned inputFrameHeight,
|
||||
bool preserveFeedbackState);
|
||||
|
||||
const std::vector<RuntimeRenderState>& CommittedLayerStates() const;
|
||||
void ResetTemporalHistoryState();
|
||||
void ResetShaderFeedbackState();
|
||||
void ApplyRuntimeCoordinatorRenderReset(RuntimeCoordinatorRenderResetScope resetScope);
|
||||
void ClearOscOverlayState();
|
||||
void UpdateOscOverlayState(
|
||||
const std::vector<OscOverlayUpdate>& updates,
|
||||
|
||||
@@ -98,6 +98,7 @@ RuntimeCoordinatorResult RuntimeCoordinator::HandleRuntimePollFailure(const std:
|
||||
RuntimeCoordinatorResult RuntimeCoordinator::HandlePreparedShaderBuildFailure(const std::string& error)
|
||||
{
|
||||
mPreserveFeedbackOnNextShaderBuild = false;
|
||||
mUseCommittedLayerStates = true;
|
||||
|
||||
RuntimeCoordinatorResult result;
|
||||
result.accepted = true;
|
||||
@@ -111,6 +112,8 @@ RuntimeCoordinatorResult RuntimeCoordinator::HandlePreparedShaderBuildFailure(co
|
||||
|
||||
RuntimeCoordinatorResult RuntimeCoordinator::HandlePreparedShaderBuildSuccess()
|
||||
{
|
||||
mUseCommittedLayerStates = false;
|
||||
|
||||
RuntimeCoordinatorResult result;
|
||||
result.accepted = true;
|
||||
result.runtimeStateBroadcastRequired = true;
|
||||
@@ -127,6 +130,27 @@ RuntimeCoordinatorResult RuntimeCoordinator::HandleRuntimeReloadRequest()
|
||||
return BuildQueuedReloadResult(false);
|
||||
}
|
||||
|
||||
void RuntimeCoordinator::ApplyCommittedStateMode(RuntimeCoordinatorCommittedStateMode mode)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case RuntimeCoordinatorCommittedStateMode::UseCommittedStates:
|
||||
mUseCommittedLayerStates = true;
|
||||
break;
|
||||
case RuntimeCoordinatorCommittedStateMode::UseLiveSnapshots:
|
||||
mUseCommittedLayerStates = false;
|
||||
break;
|
||||
case RuntimeCoordinatorCommittedStateMode::Unchanged:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool RuntimeCoordinator::UseCommittedLayerStates() const
|
||||
{
|
||||
return mUseCommittedLayerStates.load();
|
||||
}
|
||||
|
||||
bool RuntimeCoordinator::PreserveFeedbackOnNextShaderBuild() const
|
||||
{
|
||||
return mPreserveFeedbackOnNextShaderBuild;
|
||||
@@ -151,6 +175,7 @@ RuntimeCoordinatorResult RuntimeCoordinator::ApplyStoreMutation(bool succeeded,
|
||||
RuntimeCoordinatorResult RuntimeCoordinator::BuildQueuedReloadResult(bool preserveFeedbackState)
|
||||
{
|
||||
mPreserveFeedbackOnNextShaderBuild = preserveFeedbackState;
|
||||
mUseCommittedLayerStates = true;
|
||||
|
||||
RuntimeCoordinatorResult result;
|
||||
result.accepted = true;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "RuntimeJson.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
|
||||
@@ -58,6 +59,8 @@ public:
|
||||
RuntimeCoordinatorResult HandlePreparedShaderBuildFailure(const std::string& error);
|
||||
RuntimeCoordinatorResult HandlePreparedShaderBuildSuccess();
|
||||
RuntimeCoordinatorResult HandleRuntimeReloadRequest();
|
||||
void ApplyCommittedStateMode(RuntimeCoordinatorCommittedStateMode mode);
|
||||
bool UseCommittedLayerStates() const;
|
||||
bool PreserveFeedbackOnNextShaderBuild() const;
|
||||
|
||||
private:
|
||||
@@ -67,4 +70,5 @@ private:
|
||||
|
||||
RuntimeStore& mRuntimeStore;
|
||||
bool mPreserveFeedbackOnNextShaderBuild = false;
|
||||
std::atomic<bool> mUseCommittedLayerStates{ false };
|
||||
};
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
#include "RuntimeClock.h"
|
||||
#include "RuntimeParameterUtils.h"
|
||||
#include "ShaderCompiler.h"
|
||||
#include "ShaderPackageRegistry.h"
|
||||
|
||||
#include <algorithm>
|
||||
@@ -212,42 +211,6 @@ bool ParseShaderParameterType(const std::string& typeName, ShaderParameterType&
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TextureAssetsEqual(const std::vector<ShaderTextureAsset>& left, const std::vector<ShaderTextureAsset>& right)
|
||||
{
|
||||
if (left.size() != right.size())
|
||||
return false;
|
||||
|
||||
for (std::size_t index = 0; index < left.size(); ++index)
|
||||
{
|
||||
if (left[index].id != right[index].id ||
|
||||
left[index].path != right[index].path ||
|
||||
left[index].writeTime != right[index].writeTime)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FontAssetsEqual(const std::vector<ShaderFontAsset>& left, const std::vector<ShaderFontAsset>& right)
|
||||
{
|
||||
if (left.size() != right.size())
|
||||
return false;
|
||||
|
||||
for (std::size_t index = 0; index < left.size(); ++index)
|
||||
{
|
||||
if (left[index].id != right[index].id ||
|
||||
left[index].path != right[index].path ||
|
||||
left[index].writeTime != right[index].writeTime)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string ManifestPathMessage(const std::filesystem::path& manifestPath)
|
||||
{
|
||||
return manifestPath.string();
|
||||
@@ -712,126 +675,6 @@ RuntimeHost::RuntimeHost()
|
||||
{
|
||||
}
|
||||
|
||||
bool RuntimeHost::PollFileChanges(bool& registryChanged, bool& reloadRequested, std::string& error)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
registryChanged = false;
|
||||
reloadRequested = false;
|
||||
|
||||
if (!mAutoReloadEnabled)
|
||||
{
|
||||
reloadRequested = mReloadRequested;
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto now = std::chrono::steady_clock::now();
|
||||
if (mLastScanTime != std::chrono::steady_clock::time_point::min() &&
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(now - mLastScanTime).count() < 250)
|
||||
{
|
||||
reloadRequested = mReloadRequested;
|
||||
return true;
|
||||
}
|
||||
|
||||
mLastScanTime = now;
|
||||
|
||||
std::string scanError;
|
||||
std::map<std::string, ShaderPackage> previousPackages = mPackagesById;
|
||||
std::vector<std::string> previousOrder = mPackageOrder;
|
||||
std::map<std::string, std::pair<std::filesystem::file_time_type, std::filesystem::file_time_type>> previousLayerShaderTimes;
|
||||
for (const LayerPersistentState& layer : mPersistentState.layers)
|
||||
{
|
||||
auto previous = previousPackages.find(layer.shaderId);
|
||||
if (previous != previousPackages.end())
|
||||
previousLayerShaderTimes[layer.id] = std::make_pair(previous->second.shaderWriteTime, previous->second.manifestWriteTime);
|
||||
}
|
||||
|
||||
if (!ScanShaderPackages(scanError))
|
||||
{
|
||||
error = scanError;
|
||||
return false;
|
||||
}
|
||||
|
||||
registryChanged = previousOrder != mPackageOrder;
|
||||
if (!registryChanged && previousPackages.size() == mPackagesById.size())
|
||||
{
|
||||
for (const auto& item : mPackagesById)
|
||||
{
|
||||
auto previous = previousPackages.find(item.first);
|
||||
if (previous == previousPackages.end())
|
||||
{
|
||||
registryChanged = true;
|
||||
break;
|
||||
}
|
||||
if (previous->second.shaderWriteTime != item.second.shaderWriteTime ||
|
||||
previous->second.manifestWriteTime != item.second.manifestWriteTime ||
|
||||
!TextureAssetsEqual(previous->second.textureAssets, item.second.textureAssets) ||
|
||||
!FontAssetsEqual(previous->second.fontAssets, item.second.fontAssets))
|
||||
{
|
||||
registryChanged = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (LayerPersistentState& layer : mPersistentState.layers)
|
||||
{
|
||||
auto active = mPackagesById.find(layer.shaderId);
|
||||
auto previous = previousLayerShaderTimes.find(layer.id);
|
||||
if (active == mPackagesById.end())
|
||||
continue;
|
||||
EnsureLayerDefaultsLocked(layer, active->second);
|
||||
if (previous != previousLayerShaderTimes.end())
|
||||
{
|
||||
auto previousPackage = previousPackages.find(layer.shaderId);
|
||||
if (previous->second.first != active->second.shaderWriteTime ||
|
||||
previous->second.second != active->second.manifestWriteTime ||
|
||||
(previousPackage != previousPackages.end() &&
|
||||
(!TextureAssetsEqual(previousPackage->second.textureAssets, active->second.textureAssets) ||
|
||||
!FontAssetsEqual(previousPackage->second.fontAssets, active->second.fontAssets))))
|
||||
{
|
||||
mReloadRequested = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
reloadRequested = mReloadRequested;
|
||||
if (registryChanged || reloadRequested)
|
||||
MarkRenderStateDirtyLocked();
|
||||
return true;
|
||||
}
|
||||
catch (const std::exception& exception)
|
||||
{
|
||||
error = std::string("RuntimeHost::PollFileChanges exception: ") + exception.what();
|
||||
return false;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
error = "RuntimeHost::PollFileChanges threw a non-standard exception.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool RuntimeHost::ManualReloadRequested()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
return mReloadRequested;
|
||||
}
|
||||
|
||||
void RuntimeHost::ClearReloadRequest()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
mReloadRequested = false;
|
||||
}
|
||||
|
||||
void RuntimeHost::SetCompileStatus(bool succeeded, const std::string& message)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
mCompileSucceeded = succeeded;
|
||||
mCompileMessage = message;
|
||||
}
|
||||
|
||||
void RuntimeHost::SetSignalStatus(bool hasSignal, unsigned width, unsigned height, const std::string& modeName)
|
||||
{
|
||||
const HealthTelemetry::SignalStatusSnapshot previousStatus = mHealthTelemetry.GetSignalStatusSnapshot();
|
||||
@@ -921,69 +764,6 @@ bool RuntimeHost::TrySetFramePacingStats(double completionIntervalMilliseconds,
|
||||
maxCompletionIntervalMilliseconds, lateFrameCount, droppedFrameCount, flushedFrameCount);
|
||||
}
|
||||
|
||||
void RuntimeHost::AdvanceFrame()
|
||||
{
|
||||
++mFrameCounter;
|
||||
}
|
||||
|
||||
bool RuntimeHost::TryAdvanceFrame()
|
||||
{
|
||||
++mFrameCounter;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RuntimeHost::BuildLayerPassFragmentShaderSources(const std::string& layerId, std::vector<ShaderPassBuildSource>& passSources, std::string& error)
|
||||
{
|
||||
try
|
||||
{
|
||||
ShaderPackage shaderPackage;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
const LayerPersistentState* layer = FindLayerById(layerId);
|
||||
if (!layer)
|
||||
{
|
||||
error = "Unknown layer id: " + layerId;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto it = mPackagesById.find(layer->shaderId);
|
||||
if (it == mPackagesById.end())
|
||||
{
|
||||
error = "Unknown shader id: " + layer->shaderId;
|
||||
return false;
|
||||
}
|
||||
shaderPackage = it->second;
|
||||
}
|
||||
|
||||
ShaderCompiler compiler(mRepoRoot, mWrapperPath, mGeneratedGlslPath, mPatchedGlslPath, mConfig.maxTemporalHistoryFrames);
|
||||
// Compile every declared pass while the caller remains backend-neutral.
|
||||
// The GL layer decides how the resulting pass sources are routed.
|
||||
passSources.clear();
|
||||
passSources.reserve(shaderPackage.passes.size());
|
||||
for (const ShaderPassDefinition& pass : shaderPackage.passes)
|
||||
{
|
||||
ShaderPassBuildSource passSource;
|
||||
passSource.passId = pass.id;
|
||||
passSource.inputNames = pass.inputNames;
|
||||
passSource.outputName = pass.outputName;
|
||||
if (!compiler.BuildPassFragmentShaderSource(shaderPackage, pass, passSource.fragmentShaderSource, error))
|
||||
return false;
|
||||
passSources.push_back(std::move(passSource));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (const std::exception& exception)
|
||||
{
|
||||
error = std::string("RuntimeHost::BuildLayerPassFragmentShaderSources exception: ") + exception.what();
|
||||
return false;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
error = "RuntimeHost::BuildLayerPassFragmentShaderSources threw a non-standard exception.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void RuntimeHost::SetServerPort(unsigned short port)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
|
||||
@@ -20,12 +20,6 @@ class RuntimeHost
|
||||
{
|
||||
public:
|
||||
RuntimeHost();
|
||||
|
||||
bool PollFileChanges(bool& registryChanged, bool& reloadRequested, std::string& error);
|
||||
bool ManualReloadRequested();
|
||||
void ClearReloadRequest();
|
||||
|
||||
void SetCompileStatus(bool succeeded, const std::string& message);
|
||||
void SetSignalStatus(bool hasSignal, unsigned width, unsigned height, const std::string& modeName);
|
||||
bool TrySetSignalStatus(bool hasSignal, unsigned width, unsigned height, const std::string& modeName);
|
||||
void SetDeckLinkOutputStatus(const std::string& modelName, bool supportsInternalKeying, bool supportsExternalKeying,
|
||||
@@ -38,15 +32,9 @@ public:
|
||||
double maxCompletionIntervalMilliseconds, uint64_t lateFrameCount, uint64_t droppedFrameCount, uint64_t flushedFrameCount);
|
||||
bool TrySetFramePacingStats(double completionIntervalMilliseconds, double smoothedCompletionIntervalMilliseconds,
|
||||
double maxCompletionIntervalMilliseconds, uint64_t lateFrameCount, uint64_t droppedFrameCount, uint64_t flushedFrameCount);
|
||||
void AdvanceFrame();
|
||||
bool TryAdvanceFrame();
|
||||
HealthTelemetry& GetHealthTelemetry() { return mHealthTelemetry; }
|
||||
const HealthTelemetry& GetHealthTelemetry() const { return mHealthTelemetry; }
|
||||
|
||||
bool BuildLayerPassFragmentShaderSources(const std::string& layerId, std::vector<ShaderPassBuildSource>& passSources, std::string& error);
|
||||
uint64_t GetRenderStateVersion() const { return mRenderStateVersion.load(std::memory_order_relaxed); }
|
||||
uint64_t GetParameterStateVersion() const { return mParameterStateVersion.load(std::memory_order_relaxed); }
|
||||
|
||||
const std::filesystem::path& GetRepoRoot() const { return mRepoRoot; }
|
||||
const std::filesystem::path& GetUiRoot() const { return mUiRoot; }
|
||||
const std::filesystem::path& GetDocsRoot() const { return mDocsRoot; }
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "RuntimeSnapshotProvider.h"
|
||||
|
||||
#include "RuntimeClock.h"
|
||||
#include "ShaderCompiler.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <mutex>
|
||||
@@ -13,7 +14,57 @@ RuntimeSnapshotProvider::RuntimeSnapshotProvider(RuntimeHost& runtimeHost) :
|
||||
|
||||
bool RuntimeSnapshotProvider::BuildLayerPassFragmentShaderSources(const std::string& layerId, std::vector<ShaderPassBuildSource>& passSources, std::string& error) const
|
||||
{
|
||||
return mRuntimeHost.BuildLayerPassFragmentShaderSources(layerId, passSources, error);
|
||||
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;
|
||||
}
|
||||
|
||||
auto it = mRuntimeHost.mPackagesById.find(layer->shaderId);
|
||||
if (it == mRuntimeHost.mPackagesById.end())
|
||||
{
|
||||
error = "Unknown shader id: " + layer->shaderId;
|
||||
return false;
|
||||
}
|
||||
shaderPackage = it->second;
|
||||
}
|
||||
|
||||
ShaderCompiler compiler(
|
||||
mRuntimeHost.mRepoRoot,
|
||||
mRuntimeHost.mWrapperPath,
|
||||
mRuntimeHost.mGeneratedGlslPath,
|
||||
mRuntimeHost.mPatchedGlslPath,
|
||||
mRuntimeHost.mConfig.maxTemporalHistoryFrames);
|
||||
passSources.clear();
|
||||
passSources.reserve(shaderPackage.passes.size());
|
||||
for (const ShaderPassDefinition& pass : shaderPackage.passes)
|
||||
{
|
||||
ShaderPassBuildSource passSource;
|
||||
passSource.passId = pass.id;
|
||||
passSource.inputNames = pass.inputNames;
|
||||
passSource.outputName = pass.outputName;
|
||||
if (!compiler.BuildPassFragmentShaderSource(shaderPackage, pass, passSource.fragmentShaderSource, error))
|
||||
return false;
|
||||
passSources.push_back(std::move(passSource));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (const std::exception& exception)
|
||||
{
|
||||
error = std::string("RuntimeSnapshotProvider::BuildLayerPassFragmentShaderSources exception: ") + exception.what();
|
||||
return false;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
error = "RuntimeSnapshotProvider::BuildLayerPassFragmentShaderSources threw a non-standard exception.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned RuntimeSnapshotProvider::GetMaxTemporalHistoryFrames() const
|
||||
@@ -24,8 +75,8 @@ unsigned RuntimeSnapshotProvider::GetMaxTemporalHistoryFrames() const
|
||||
RuntimeSnapshotVersions RuntimeSnapshotProvider::GetVersions() const
|
||||
{
|
||||
RuntimeSnapshotVersions versions;
|
||||
versions.renderStateVersion = mRuntimeHost.GetRenderStateVersion();
|
||||
versions.parameterStateVersion = mRuntimeHost.GetParameterStateVersion();
|
||||
versions.renderStateVersion = mRuntimeHost.mRenderStateVersion.load(std::memory_order_relaxed);
|
||||
versions.parameterStateVersion = mRuntimeHost.mParameterStateVersion.load(std::memory_order_relaxed);
|
||||
return versions;
|
||||
}
|
||||
|
||||
@@ -46,12 +97,13 @@ RuntimeRenderFrameContext RuntimeSnapshotProvider::GetFrameContext() const
|
||||
|
||||
void RuntimeSnapshotProvider::AdvanceFrame()
|
||||
{
|
||||
mRuntimeHost.AdvanceFrame();
|
||||
++mRuntimeHost.mFrameCounter;
|
||||
}
|
||||
|
||||
bool RuntimeSnapshotProvider::TryAdvanceFrame()
|
||||
{
|
||||
return mRuntimeHost.TryAdvanceFrame();
|
||||
++mRuntimeHost.mFrameCounter;
|
||||
return true;
|
||||
}
|
||||
|
||||
RuntimeRenderStateSnapshot RuntimeSnapshotProvider::GetRenderStateSnapshot(unsigned outputWidth, unsigned outputHeight) const
|
||||
|
||||
@@ -30,6 +30,42 @@ bool MatchesControlKey(const std::string& candidate, const std::string& key)
|
||||
{
|
||||
return candidate == key || SimplifyControlKey(candidate) == SimplifyControlKey(key);
|
||||
}
|
||||
|
||||
bool TextureAssetsEqual(const std::vector<ShaderTextureAsset>& left, const std::vector<ShaderTextureAsset>& right)
|
||||
{
|
||||
if (left.size() != right.size())
|
||||
return false;
|
||||
|
||||
for (std::size_t index = 0; index < left.size(); ++index)
|
||||
{
|
||||
if (left[index].id != right[index].id ||
|
||||
left[index].path != right[index].path ||
|
||||
left[index].writeTime != right[index].writeTime)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FontAssetsEqual(const std::vector<ShaderFontAsset>& left, const std::vector<ShaderFontAsset>& right)
|
||||
{
|
||||
if (left.size() != right.size())
|
||||
return false;
|
||||
|
||||
for (std::size_t index = 0; index < left.size(); ++index)
|
||||
{
|
||||
if (left[index].id != right[index].id ||
|
||||
left[index].path != right[index].path ||
|
||||
left[index].writeTime != right[index].writeTime)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
RuntimeStore::RuntimeStore(RuntimeHost& runtimeHost) :
|
||||
@@ -94,6 +130,107 @@ std::string RuntimeStore::BuildPersistentStateJson() const
|
||||
return SerializeJson(BuildRuntimeStateValue(), true);
|
||||
}
|
||||
|
||||
bool RuntimeStore::PollStoredFileChanges(bool& registryChanged, bool& reloadRequested, std::string& error)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mRuntimeHost.mMutex);
|
||||
registryChanged = false;
|
||||
reloadRequested = false;
|
||||
|
||||
if (!mRuntimeHost.mAutoReloadEnabled)
|
||||
{
|
||||
reloadRequested = mRuntimeHost.mReloadRequested;
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto now = std::chrono::steady_clock::now();
|
||||
if (mRuntimeHost.mLastScanTime != std::chrono::steady_clock::time_point::min() &&
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(now - mRuntimeHost.mLastScanTime).count() < 250)
|
||||
{
|
||||
reloadRequested = mRuntimeHost.mReloadRequested;
|
||||
return true;
|
||||
}
|
||||
|
||||
mRuntimeHost.mLastScanTime = now;
|
||||
|
||||
std::string scanError;
|
||||
std::map<std::string, ShaderPackage> previousPackages = mRuntimeHost.mPackagesById;
|
||||
std::vector<std::string> previousOrder = mRuntimeHost.mPackageOrder;
|
||||
std::map<std::string, std::pair<std::filesystem::file_time_type, std::filesystem::file_time_type>> previousLayerShaderTimes;
|
||||
for (const RuntimeHost::LayerPersistentState& layer : mRuntimeHost.mPersistentState.layers)
|
||||
{
|
||||
auto previous = previousPackages.find(layer.shaderId);
|
||||
if (previous != previousPackages.end())
|
||||
previousLayerShaderTimes[layer.id] = std::make_pair(previous->second.shaderWriteTime, previous->second.manifestWriteTime);
|
||||
}
|
||||
|
||||
if (!mRuntimeHost.ScanShaderPackages(scanError))
|
||||
{
|
||||
error = scanError;
|
||||
return false;
|
||||
}
|
||||
|
||||
registryChanged = previousOrder != mRuntimeHost.mPackageOrder;
|
||||
if (!registryChanged && previousPackages.size() == mRuntimeHost.mPackagesById.size())
|
||||
{
|
||||
for (const auto& item : mRuntimeHost.mPackagesById)
|
||||
{
|
||||
auto previous = previousPackages.find(item.first);
|
||||
if (previous == previousPackages.end())
|
||||
{
|
||||
registryChanged = true;
|
||||
break;
|
||||
}
|
||||
if (previous->second.shaderWriteTime != item.second.shaderWriteTime ||
|
||||
previous->second.manifestWriteTime != item.second.manifestWriteTime ||
|
||||
!TextureAssetsEqual(previous->second.textureAssets, item.second.textureAssets) ||
|
||||
!FontAssetsEqual(previous->second.fontAssets, item.second.fontAssets))
|
||||
{
|
||||
registryChanged = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (RuntimeHost::LayerPersistentState& layer : mRuntimeHost.mPersistentState.layers)
|
||||
{
|
||||
auto active = mRuntimeHost.mPackagesById.find(layer.shaderId);
|
||||
auto previous = previousLayerShaderTimes.find(layer.id);
|
||||
if (active == mRuntimeHost.mPackagesById.end())
|
||||
continue;
|
||||
mRuntimeHost.EnsureLayerDefaultsLocked(layer, active->second);
|
||||
if (previous != previousLayerShaderTimes.end())
|
||||
{
|
||||
auto previousPackage = previousPackages.find(layer.shaderId);
|
||||
if (previous->second.first != active->second.shaderWriteTime ||
|
||||
previous->second.second != active->second.manifestWriteTime ||
|
||||
(previousPackage != previousPackages.end() &&
|
||||
(!TextureAssetsEqual(previousPackage->second.textureAssets, active->second.textureAssets) ||
|
||||
!FontAssetsEqual(previousPackage->second.fontAssets, active->second.fontAssets))))
|
||||
{
|
||||
mRuntimeHost.mReloadRequested = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
reloadRequested = mRuntimeHost.mReloadRequested;
|
||||
if (registryChanged || reloadRequested)
|
||||
mRuntimeHost.MarkRenderStateDirtyLocked();
|
||||
return true;
|
||||
}
|
||||
catch (const std::exception& exception)
|
||||
{
|
||||
error = std::string("RuntimeStore::PollStoredFileChanges exception: ") + exception.what();
|
||||
return false;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
error = "RuntimeStore::PollStoredFileChanges threw a non-standard exception.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool RuntimeStore::CreateStoredLayer(const std::string& shaderId, std::string& error)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mRuntimeHost.mMutex);
|
||||
@@ -465,12 +602,15 @@ const std::string& RuntimeStore::GetConfiguredOutputFrameRate() const
|
||||
|
||||
void RuntimeStore::SetCompileStatus(bool succeeded, const std::string& message)
|
||||
{
|
||||
mRuntimeHost.SetCompileStatus(succeeded, message);
|
||||
std::lock_guard<std::mutex> lock(mRuntimeHost.mMutex);
|
||||
mRuntimeHost.mCompileSucceeded = succeeded;
|
||||
mRuntimeHost.mCompileMessage = message;
|
||||
}
|
||||
|
||||
void RuntimeStore::ClearReloadRequest()
|
||||
{
|
||||
mRuntimeHost.ClearReloadRequest();
|
||||
std::lock_guard<std::mutex> lock(mRuntimeHost.mMutex);
|
||||
mRuntimeHost.mReloadRequested = false;
|
||||
}
|
||||
|
||||
JsonValue RuntimeStore::BuildRuntimeStateValue() const
|
||||
|
||||
@@ -12,6 +12,7 @@ public:
|
||||
|
||||
bool InitializeStore(std::string& error);
|
||||
std::string BuildPersistentStateJson() const;
|
||||
bool PollStoredFileChanges(bool& registryChanged, bool& reloadRequested, std::string& error);
|
||||
|
||||
bool CreateStoredLayer(const std::string& shaderId, std::string& error);
|
||||
bool DeleteStoredLayer(const std::string& layerId, std::string& error);
|
||||
|
||||
@@ -177,6 +177,31 @@ void VideoBackend::SetStatusMessage(const std::string& message)
|
||||
mVideoIODevice->SetStatusMessage(message);
|
||||
}
|
||||
|
||||
void VideoBackend::PublishStatus(bool externalKeyingConfigured, const std::string& statusMessage)
|
||||
{
|
||||
if (!statusMessage.empty())
|
||||
SetStatusMessage(statusMessage);
|
||||
|
||||
mHealthTelemetry.ReportVideoIOStatus(
|
||||
"decklink",
|
||||
OutputModelName(),
|
||||
SupportsInternalKeying(),
|
||||
SupportsExternalKeying(),
|
||||
KeyerInterfaceAvailable(),
|
||||
externalKeyingConfigured,
|
||||
ExternalKeyingActive(),
|
||||
StatusMessage());
|
||||
}
|
||||
|
||||
void VideoBackend::ReportNoInputDeviceSignalStatus()
|
||||
{
|
||||
mHealthTelemetry.ReportSignalStatus(
|
||||
false,
|
||||
InputFrameWidth(),
|
||||
InputFrameHeight(),
|
||||
InputDisplayModeName());
|
||||
}
|
||||
|
||||
void VideoBackend::HandleInputFrame(const VideoIOFrame& frame)
|
||||
{
|
||||
const VideoIOState& state = mVideoIODevice->State();
|
||||
|
||||
@@ -50,6 +50,8 @@ public:
|
||||
bool ExternalKeyingActive() const;
|
||||
const std::string& StatusMessage() const;
|
||||
void SetStatusMessage(const std::string& message);
|
||||
void PublishStatus(bool externalKeyingConfigured, const std::string& statusMessage = std::string());
|
||||
void ReportNoInputDeviceSignalStatus();
|
||||
|
||||
private:
|
||||
void HandleInputFrame(const VideoIOFrame& frame);
|
||||
|
||||
Reference in New Issue
Block a user