dispatch event intergration
This commit is contained in:
@@ -230,6 +230,23 @@ endif()
|
|||||||
|
|
||||||
add_test(NAME RuntimeClockTests COMMAND RuntimeClockTests)
|
add_test(NAME RuntimeClockTests COMMAND RuntimeClockTests)
|
||||||
|
|
||||||
|
add_executable(HealthTelemetryTests
|
||||||
|
"${APP_DIR}/runtime/telemetry/HealthTelemetry.cpp"
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/tests/HealthTelemetryTests.cpp"
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(HealthTelemetryTests PRIVATE
|
||||||
|
"${APP_DIR}"
|
||||||
|
"${APP_DIR}/runtime"
|
||||||
|
"${APP_DIR}/runtime/telemetry"
|
||||||
|
)
|
||||||
|
|
||||||
|
if(MSVC)
|
||||||
|
target_compile_options(HealthTelemetryTests PRIVATE /W3)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_test(NAME HealthTelemetryTests COMMAND HealthTelemetryTests)
|
||||||
|
|
||||||
add_executable(RuntimeParameterUtilsTests
|
add_executable(RuntimeParameterUtilsTests
|
||||||
"${APP_DIR}/runtime/support/RuntimeJson.cpp"
|
"${APP_DIR}/runtime/support/RuntimeJson.cpp"
|
||||||
"${APP_DIR}/runtime/support/RuntimeParameterUtils.cpp"
|
"${APP_DIR}/runtime/support/RuntimeParameterUtils.cpp"
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include "ControlServer.h"
|
#include "ControlServer.h"
|
||||||
#include "OscServer.h"
|
#include "OscServer.h"
|
||||||
#include "RuntimeControlBridge.h"
|
#include "RuntimeControlBridge.h"
|
||||||
|
#include "RuntimeEventDispatcher.h"
|
||||||
#include "RuntimeStore.h"
|
#include "RuntimeStore.h"
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
@@ -56,6 +57,8 @@ void ControlServices::BroadcastState()
|
|||||||
|
|
||||||
void ControlServices::RequestBroadcastState()
|
void ControlServices::RequestBroadcastState()
|
||||||
{
|
{
|
||||||
|
PublishRuntimeStateBroadcastRequested("control-service-request");
|
||||||
|
|
||||||
if (mControlServer)
|
if (mControlServer)
|
||||||
mControlServer->RequestBroadcastState();
|
mControlServer->RequestBroadcastState();
|
||||||
}
|
}
|
||||||
@@ -105,6 +108,7 @@ bool ControlServices::ApplyPendingOscUpdates(std::vector<AppliedOscUpdate>& appl
|
|||||||
appliedUpdate.parameterKey = entry.second.parameterKey;
|
appliedUpdate.parameterKey = entry.second.parameterKey;
|
||||||
appliedUpdate.targetValue = targetValue;
|
appliedUpdate.targetValue = targetValue;
|
||||||
appliedUpdates.push_back(std::move(appliedUpdate));
|
appliedUpdates.push_back(std::move(appliedUpdate));
|
||||||
|
PublishOscValueReceived(entry.second, entry.first);
|
||||||
}
|
}
|
||||||
|
|
||||||
(void)error;
|
(void)error;
|
||||||
@@ -195,6 +199,7 @@ void ControlServices::PollLoop(RuntimeCoordinator& runtimeCoordinator)
|
|||||||
}
|
}
|
||||||
for (const auto& entry : pendingCommits)
|
for (const auto& entry : pendingCommits)
|
||||||
{
|
{
|
||||||
|
PublishOscCommitRequested(entry.second);
|
||||||
const RuntimeCoordinatorResult result = runtimeCoordinator.CommitOscParameterByControlKey(
|
const RuntimeCoordinatorResult result = runtimeCoordinator.CommitOscParameterByControlKey(
|
||||||
entry.second.layerKey,
|
entry.second.layerKey,
|
||||||
entry.second.parameterKey,
|
entry.second.parameterKey,
|
||||||
@@ -233,3 +238,55 @@ void ControlServices::QueueRuntimeCoordinatorResult(const RuntimeCoordinatorResu
|
|||||||
std::lock_guard<std::mutex> lock(mRuntimeCoordinatorResultMutex);
|
std::lock_guard<std::mutex> lock(mRuntimeCoordinatorResultMutex);
|
||||||
mRuntimeCoordinatorResults.push_back(std::move(serviceResult));
|
mRuntimeCoordinatorResults.push_back(std::move(serviceResult));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ControlServices::PublishRuntimeStateBroadcastRequested(const std::string& reason)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
RuntimeStateBroadcastRequestedEvent event;
|
||||||
|
event.reason = reason;
|
||||||
|
if (!mRuntimeEventDispatcher.PublishPayload(event, "ControlServices"))
|
||||||
|
OutputDebugStringA("RuntimeStateBroadcastRequested event publish failed.\n");
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
OutputDebugStringA("RuntimeStateBroadcastRequested event publish threw.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ControlServices::PublishOscValueReceived(const PendingOscUpdate& update, const std::string& routeKey)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
OscValueReceivedEvent event;
|
||||||
|
event.routeKey = routeKey;
|
||||||
|
event.layerKey = update.layerKey;
|
||||||
|
event.parameterKey = update.parameterKey;
|
||||||
|
event.valueJson = update.valueJson;
|
||||||
|
if (!mRuntimeEventDispatcher.PublishPayload(event, "ControlServices"))
|
||||||
|
OutputDebugStringA("OscValueReceived event publish failed.\n");
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
OutputDebugStringA("OscValueReceived event publish threw.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ControlServices::PublishOscCommitRequested(const PendingOscCommit& commit)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
OscCommitRequestedEvent event;
|
||||||
|
event.routeKey = commit.routeKey;
|
||||||
|
event.layerKey = commit.layerKey;
|
||||||
|
event.parameterKey = commit.parameterKey;
|
||||||
|
event.valueJson = SerializeJson(commit.value, false);
|
||||||
|
event.generation = commit.generation;
|
||||||
|
if (!mRuntimeEventDispatcher.PublishPayload(event, "ControlServices"))
|
||||||
|
OutputDebugStringA("OscCommitRequested event publish failed.\n");
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
OutputDebugStringA("OscCommitRequested event publish threw.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -77,6 +77,9 @@ private:
|
|||||||
void StopPolling();
|
void StopPolling();
|
||||||
void PollLoop(RuntimeCoordinator& runtimeCoordinator);
|
void PollLoop(RuntimeCoordinator& runtimeCoordinator);
|
||||||
void QueueRuntimeCoordinatorResult(const RuntimeCoordinatorResult& result, bool failed = false);
|
void QueueRuntimeCoordinatorResult(const RuntimeCoordinatorResult& result, bool failed = false);
|
||||||
|
void PublishRuntimeStateBroadcastRequested(const std::string& reason);
|
||||||
|
void PublishOscValueReceived(const PendingOscUpdate& update, const std::string& routeKey);
|
||||||
|
void PublishOscCommitRequested(const PendingOscCommit& commit);
|
||||||
|
|
||||||
std::unique_ptr<ControlServer> mControlServer;
|
std::unique_ptr<ControlServer> mControlServer;
|
||||||
std::unique_ptr<OscServer> mOscServer;
|
std::unique_ptr<OscServer> mOscServer;
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ OpenGLComposite::OpenGLComposite(HWND hWnd, HDC hDC, HGLRC hRC) :
|
|||||||
[this]() { ProcessScreenshotRequest(); },
|
[this]() { ProcessScreenshotRequest(); },
|
||||||
[this]() { paintGL(false); });
|
[this]() { paintGL(false); });
|
||||||
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, *mRuntimeEventDispatcher);
|
||||||
mRuntimeServices = std::make_unique<RuntimeServices>(*mRuntimeEventDispatcher);
|
mRuntimeServices = std::make_unique<RuntimeServices>(*mRuntimeEventDispatcher);
|
||||||
mRuntimeUpdateController = std::make_unique<RuntimeUpdateController>(
|
mRuntimeUpdateController = std::make_unique<RuntimeUpdateController>(
|
||||||
*mRuntimeStore,
|
*mRuntimeStore,
|
||||||
|
|||||||
@@ -7,8 +7,26 @@
|
|||||||
#include "ShaderBuildQueue.h"
|
#include "ShaderBuildQueue.h"
|
||||||
#include "VideoBackend.h"
|
#include "VideoBackend.h"
|
||||||
|
|
||||||
|
#include <variant>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
RuntimeCoordinatorRenderResetScope ToRuntimeCoordinatorRenderResetScope(RuntimeEventRenderResetScope scope)
|
||||||
|
{
|
||||||
|
switch (scope)
|
||||||
|
{
|
||||||
|
case RuntimeEventRenderResetScope::TemporalHistoryOnly:
|
||||||
|
return RuntimeCoordinatorRenderResetScope::TemporalHistoryOnly;
|
||||||
|
case RuntimeEventRenderResetScope::TemporalHistoryAndFeedback:
|
||||||
|
return RuntimeCoordinatorRenderResetScope::TemporalHistoryAndFeedback;
|
||||||
|
case RuntimeEventRenderResetScope::None:
|
||||||
|
default:
|
||||||
|
return RuntimeCoordinatorRenderResetScope::None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
RuntimeUpdateController::RuntimeUpdateController(
|
RuntimeUpdateController::RuntimeUpdateController(
|
||||||
RuntimeStore& runtimeStore,
|
RuntimeStore& runtimeStore,
|
||||||
RuntimeCoordinator& runtimeCoordinator,
|
RuntimeCoordinator& runtimeCoordinator,
|
||||||
@@ -28,6 +46,21 @@ RuntimeUpdateController::RuntimeUpdateController(
|
|||||||
mRuntimeEventDispatcher.Subscribe(
|
mRuntimeEventDispatcher.Subscribe(
|
||||||
RuntimeEventType::RuntimeStateBroadcastRequested,
|
RuntimeEventType::RuntimeStateBroadcastRequested,
|
||||||
[this](const RuntimeEvent& event) { HandleRuntimeStateBroadcastRequested(event); });
|
[this](const RuntimeEvent& event) { HandleRuntimeStateBroadcastRequested(event); });
|
||||||
|
mRuntimeEventDispatcher.Subscribe(
|
||||||
|
RuntimeEventType::ShaderBuildRequested,
|
||||||
|
[this](const RuntimeEvent& event) { HandleShaderBuildRequested(event); });
|
||||||
|
mRuntimeEventDispatcher.Subscribe(
|
||||||
|
RuntimeEventType::ShaderBuildPrepared,
|
||||||
|
[this](const RuntimeEvent& event) { HandleShaderBuildPrepared(event); });
|
||||||
|
mRuntimeEventDispatcher.Subscribe(
|
||||||
|
RuntimeEventType::ShaderBuildFailed,
|
||||||
|
[this](const RuntimeEvent& event) { HandleShaderBuildFailed(event); });
|
||||||
|
mRuntimeEventDispatcher.Subscribe(
|
||||||
|
RuntimeEventType::CompileStatusChanged,
|
||||||
|
[this](const RuntimeEvent& event) { HandleCompileStatusChanged(event); });
|
||||||
|
mRuntimeEventDispatcher.Subscribe(
|
||||||
|
RuntimeEventType::RenderResetRequested,
|
||||||
|
[this](const RuntimeEvent& event) { HandleRenderResetRequested(event); });
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RuntimeUpdateController::ApplyRuntimeCoordinatorResult(const RuntimeCoordinatorResult& result, std::string* error)
|
bool RuntimeUpdateController::ApplyRuntimeCoordinatorResult(const RuntimeCoordinatorResult& result, std::string* error)
|
||||||
@@ -40,7 +73,10 @@ bool RuntimeUpdateController::ApplyRuntimeCoordinatorResult(const RuntimeCoordin
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (result.compileStatusChanged)
|
if (result.compileStatusChanged)
|
||||||
|
{
|
||||||
mRuntimeStore.SetCompileStatus(result.compileStatusSucceeded, result.compileStatusMessage);
|
mRuntimeStore.SetCompileStatus(result.compileStatusSucceeded, result.compileStatusMessage);
|
||||||
|
++mPendingCoordinatorCompileStatusEvents;
|
||||||
|
}
|
||||||
|
|
||||||
if (result.clearReloadRequest)
|
if (result.clearReloadRequest)
|
||||||
mRuntimeStore.ClearReloadRequest();
|
mRuntimeStore.ClearReloadRequest();
|
||||||
@@ -54,9 +90,14 @@ bool RuntimeUpdateController::ApplyRuntimeCoordinatorResult(const RuntimeCoordin
|
|||||||
}
|
}
|
||||||
|
|
||||||
mRenderEngine.ApplyRuntimeCoordinatorRenderReset(result.renderResetScope);
|
mRenderEngine.ApplyRuntimeCoordinatorRenderReset(result.renderResetScope);
|
||||||
|
if (result.renderResetScope != RuntimeCoordinatorRenderResetScope::None)
|
||||||
|
++mPendingCoordinatorRenderResetEvents;
|
||||||
|
|
||||||
if (result.shaderBuildRequested)
|
if (result.shaderBuildRequested)
|
||||||
|
{
|
||||||
RequestShaderBuild();
|
RequestShaderBuild();
|
||||||
|
++mPendingCoordinatorShaderBuildEvents;
|
||||||
|
}
|
||||||
|
|
||||||
if (result.runtimeStateBroadcastRequired)
|
if (result.runtimeStateBroadcastRequired)
|
||||||
BroadcastRuntimeState();
|
BroadcastRuntimeState();
|
||||||
@@ -66,8 +107,6 @@ bool RuntimeUpdateController::ApplyRuntimeCoordinatorResult(const RuntimeCoordin
|
|||||||
|
|
||||||
bool RuntimeUpdateController::ProcessRuntimeWork()
|
bool RuntimeUpdateController::ProcessRuntimeWork()
|
||||||
{
|
{
|
||||||
mRuntimeEventDispatcher.DispatchPending();
|
|
||||||
|
|
||||||
bool shaderBuildRequested = false;
|
bool shaderBuildRequested = false;
|
||||||
std::vector<RuntimeCoordinatorServiceResult> serviceResults;
|
std::vector<RuntimeCoordinatorServiceResult> serviceResults;
|
||||||
mRuntimeServices.ConsumeRuntimeCoordinatorResults(serviceResults);
|
mRuntimeServices.ConsumeRuntimeCoordinatorResults(serviceResults);
|
||||||
@@ -82,22 +121,9 @@ bool RuntimeUpdateController::ProcessRuntimeWork()
|
|||||||
if (shaderBuildRequested)
|
if (shaderBuildRequested)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
const RenderEngine::PreparedShaderBuildApplyResult buildResult = mRenderEngine.TryApplyReadyShaderBuild(
|
DispatchRuntimeEvents();
|
||||||
mShaderBuildQueue,
|
|
||||||
mVideoBackend.InputFrameWidth(),
|
|
||||||
mVideoBackend.InputFrameHeight(),
|
|
||||||
mRuntimeCoordinator.PreserveFeedbackOnNextShaderBuild());
|
|
||||||
if (!buildResult.hadReadyBuild)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (!buildResult.applied)
|
return ConsumeReadyShaderBuild(0, true, true);
|
||||||
{
|
|
||||||
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator.HandlePreparedShaderBuildFailure(buildResult.errorMessage));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator.HandlePreparedShaderBuildSuccess());
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RuntimeUpdateController::RequestShaderBuild()
|
void RuntimeUpdateController::RequestShaderBuild()
|
||||||
@@ -115,11 +141,188 @@ void RuntimeUpdateController::BroadcastRuntimeState()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mRuntimeEventDispatcher.DispatchPending();
|
DispatchRuntimeEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RuntimeUpdateController::HandleRuntimeStateBroadcastRequested(const RuntimeEvent& event)
|
void RuntimeUpdateController::HandleRuntimeStateBroadcastRequested(const RuntimeEvent& event)
|
||||||
{
|
{
|
||||||
(void)event;
|
if (event.source == "ControlServices")
|
||||||
|
return;
|
||||||
|
|
||||||
mRuntimeServices.BroadcastState();
|
mRuntimeServices.BroadcastState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RuntimeUpdateController::HandleShaderBuildRequested(const RuntimeEvent& event)
|
||||||
|
{
|
||||||
|
const ShaderBuildEvent* payload = std::get_if<ShaderBuildEvent>(&event.payload);
|
||||||
|
if (!payload || payload->phase != RuntimeEventShaderBuildPhase::Requested)
|
||||||
|
return;
|
||||||
|
if (ShouldSuppressCoordinatorFollowUp(event, mPendingCoordinatorShaderBuildEvents))
|
||||||
|
return;
|
||||||
|
|
||||||
|
RequestShaderBuild();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RuntimeUpdateController::HandleShaderBuildPrepared(const RuntimeEvent& event)
|
||||||
|
{
|
||||||
|
const ShaderBuildEvent* payload = std::get_if<ShaderBuildEvent>(&event.payload);
|
||||||
|
if (!payload || payload->phase != RuntimeEventShaderBuildPhase::Prepared)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ConsumeReadyShaderBuild(payload->generation, false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RuntimeUpdateController::HandleShaderBuildFailed(const RuntimeEvent& event)
|
||||||
|
{
|
||||||
|
const ShaderBuildEvent* payload = std::get_if<ShaderBuildEvent>(&event.payload);
|
||||||
|
if (!payload || payload->phase != RuntimeEventShaderBuildPhase::Failed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ConsumeReadyShaderBuild(payload->generation, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RuntimeUpdateController::HandleCompileStatusChanged(const RuntimeEvent& event)
|
||||||
|
{
|
||||||
|
const CompileStatusChangedEvent* payload = std::get_if<CompileStatusChangedEvent>(&event.payload);
|
||||||
|
if (!payload)
|
||||||
|
return;
|
||||||
|
if (ShouldSuppressCoordinatorFollowUp(event, mPendingCoordinatorCompileStatusEvents))
|
||||||
|
return;
|
||||||
|
|
||||||
|
mRuntimeStore.SetCompileStatus(payload->succeeded, payload->message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RuntimeUpdateController::HandleRenderResetRequested(const RuntimeEvent& event)
|
||||||
|
{
|
||||||
|
const RenderResetEvent* payload = std::get_if<RenderResetEvent>(&event.payload);
|
||||||
|
if (!payload || payload->applied)
|
||||||
|
return;
|
||||||
|
if (ShouldSuppressCoordinatorFollowUp(event, mPendingCoordinatorRenderResetEvents))
|
||||||
|
return;
|
||||||
|
|
||||||
|
mRenderEngine.ApplyRuntimeCoordinatorRenderReset(ToRuntimeCoordinatorRenderResetScope(payload->scope));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RuntimeUpdateController::ConsumeReadyShaderBuild(uint64_t expectedGeneration, bool publishPreparedEvent, bool publishFailureEvent)
|
||||||
|
{
|
||||||
|
PreparedShaderBuild readyBuild;
|
||||||
|
const bool consumed = expectedGeneration == 0
|
||||||
|
? mShaderBuildQueue.TryConsumeReadyBuild(readyBuild)
|
||||||
|
: mShaderBuildQueue.TryConsumeReadyBuild(expectedGeneration, readyBuild);
|
||||||
|
if (!consumed)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
const unsigned inputWidth = mVideoBackend.InputFrameWidth();
|
||||||
|
const unsigned inputHeight = mVideoBackend.InputFrameHeight();
|
||||||
|
if (!readyBuild.succeeded)
|
||||||
|
{
|
||||||
|
if (publishFailureEvent)
|
||||||
|
{
|
||||||
|
PublishShaderBuildLifecycleEvent(
|
||||||
|
RuntimeEventShaderBuildPhase::Failed,
|
||||||
|
readyBuild.generation,
|
||||||
|
inputWidth,
|
||||||
|
inputHeight,
|
||||||
|
false,
|
||||||
|
readyBuild.message);
|
||||||
|
DispatchRuntimeEvents();
|
||||||
|
}
|
||||||
|
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator.HandlePreparedShaderBuildFailure(readyBuild.message));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (publishPreparedEvent)
|
||||||
|
{
|
||||||
|
PublishShaderBuildLifecycleEvent(
|
||||||
|
RuntimeEventShaderBuildPhase::Prepared,
|
||||||
|
readyBuild.generation,
|
||||||
|
inputWidth,
|
||||||
|
inputHeight,
|
||||||
|
true,
|
||||||
|
readyBuild.message);
|
||||||
|
DispatchRuntimeEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
char compilerErrorMessage[1024] = {};
|
||||||
|
if (!mRenderEngine.ApplyPreparedShaderBuild(
|
||||||
|
readyBuild,
|
||||||
|
inputWidth,
|
||||||
|
inputHeight,
|
||||||
|
mRuntimeCoordinator.PreserveFeedbackOnNextShaderBuild(),
|
||||||
|
sizeof(compilerErrorMessage),
|
||||||
|
compilerErrorMessage))
|
||||||
|
{
|
||||||
|
const std::string errorMessage = compilerErrorMessage;
|
||||||
|
if (publishFailureEvent)
|
||||||
|
{
|
||||||
|
PublishShaderBuildLifecycleEvent(
|
||||||
|
RuntimeEventShaderBuildPhase::Failed,
|
||||||
|
readyBuild.generation,
|
||||||
|
inputWidth,
|
||||||
|
inputHeight,
|
||||||
|
false,
|
||||||
|
errorMessage);
|
||||||
|
DispatchRuntimeEvents();
|
||||||
|
}
|
||||||
|
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator.HandlePreparedShaderBuildFailure(errorMessage));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
PublishShaderBuildLifecycleEvent(
|
||||||
|
RuntimeEventShaderBuildPhase::Applied,
|
||||||
|
readyBuild.generation,
|
||||||
|
inputWidth,
|
||||||
|
inputHeight,
|
||||||
|
true,
|
||||||
|
"Shader layers applied successfully.");
|
||||||
|
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator.HandlePreparedShaderBuildSuccess());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RuntimeUpdateController::PublishShaderBuildLifecycleEvent(
|
||||||
|
RuntimeEventShaderBuildPhase phase,
|
||||||
|
uint64_t generation,
|
||||||
|
unsigned inputWidth,
|
||||||
|
unsigned inputHeight,
|
||||||
|
bool succeeded,
|
||||||
|
const std::string& message)
|
||||||
|
{
|
||||||
|
ShaderBuildEvent event;
|
||||||
|
event.phase = phase;
|
||||||
|
event.generation = generation;
|
||||||
|
event.inputWidth = inputWidth;
|
||||||
|
event.inputHeight = inputHeight;
|
||||||
|
event.preserveFeedbackState = mRuntimeCoordinator.PreserveFeedbackOnNextShaderBuild();
|
||||||
|
event.succeeded = succeeded;
|
||||||
|
event.message = message;
|
||||||
|
mRuntimeEventDispatcher.PublishPayload(event, "RuntimeUpdateController");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RuntimeUpdateController::ShouldSuppressCoordinatorFollowUp(const RuntimeEvent& event, std::size_t& pendingSuppressions)
|
||||||
|
{
|
||||||
|
if (event.source != "RuntimeCoordinator")
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (pendingSuppressions > 0)
|
||||||
|
--pendingSuppressions;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
RuntimeEventDispatchResult RuntimeUpdateController::DispatchRuntimeEvents(std::size_t maxEvents)
|
||||||
|
{
|
||||||
|
RuntimeEventDispatchResult result = mRuntimeEventDispatcher.DispatchPending(maxEvents);
|
||||||
|
const RuntimeEventQueueMetrics queueMetrics = mRuntimeEventDispatcher.GetQueueMetrics();
|
||||||
|
HealthTelemetry& telemetry = mRuntimeStore.GetHealthTelemetry();
|
||||||
|
telemetry.TryRecordRuntimeEventDispatchStats(
|
||||||
|
result.dispatchedEvents,
|
||||||
|
result.handlerInvocations,
|
||||||
|
result.handlerFailures,
|
||||||
|
result.dispatchDurationMilliseconds);
|
||||||
|
telemetry.TryRecordRuntimeEventQueueMetrics(
|
||||||
|
"runtime-events",
|
||||||
|
queueMetrics.depth,
|
||||||
|
queueMetrics.capacity,
|
||||||
|
static_cast<uint64_t>(queueMetrics.droppedCount),
|
||||||
|
queueMetrics.oldestEventAgeMilliseconds);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "RuntimeCoordinator.h"
|
#include "RuntimeCoordinator.h"
|
||||||
|
#include "RuntimeEventPayloads.h"
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
class RenderEngine;
|
class RenderEngine;
|
||||||
struct RuntimeEvent;
|
struct RuntimeEvent;
|
||||||
|
struct RuntimeEventDispatchResult;
|
||||||
class RuntimeEventDispatcher;
|
class RuntimeEventDispatcher;
|
||||||
class RuntimeServices;
|
class RuntimeServices;
|
||||||
class RuntimeStore;
|
class RuntimeStore;
|
||||||
@@ -31,6 +35,21 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void HandleRuntimeStateBroadcastRequested(const RuntimeEvent& event);
|
void HandleRuntimeStateBroadcastRequested(const RuntimeEvent& event);
|
||||||
|
void HandleShaderBuildRequested(const RuntimeEvent& event);
|
||||||
|
void HandleShaderBuildPrepared(const RuntimeEvent& event);
|
||||||
|
void HandleShaderBuildFailed(const RuntimeEvent& event);
|
||||||
|
void HandleCompileStatusChanged(const RuntimeEvent& event);
|
||||||
|
void HandleRenderResetRequested(const RuntimeEvent& event);
|
||||||
|
bool ConsumeReadyShaderBuild(uint64_t expectedGeneration, bool publishPreparedEvent, bool publishFailureEvent);
|
||||||
|
void PublishShaderBuildLifecycleEvent(
|
||||||
|
RuntimeEventShaderBuildPhase phase,
|
||||||
|
uint64_t generation,
|
||||||
|
unsigned inputWidth,
|
||||||
|
unsigned inputHeight,
|
||||||
|
bool succeeded,
|
||||||
|
const std::string& message);
|
||||||
|
bool ShouldSuppressCoordinatorFollowUp(const RuntimeEvent& event, std::size_t& pendingSuppressions);
|
||||||
|
RuntimeEventDispatchResult DispatchRuntimeEvents(std::size_t maxEvents = 0);
|
||||||
|
|
||||||
RuntimeStore& mRuntimeStore;
|
RuntimeStore& mRuntimeStore;
|
||||||
RuntimeCoordinator& mRuntimeCoordinator;
|
RuntimeCoordinator& mRuntimeCoordinator;
|
||||||
@@ -39,4 +58,7 @@ private:
|
|||||||
RenderEngine& mRenderEngine;
|
RenderEngine& mRenderEngine;
|
||||||
ShaderBuildQueue& mShaderBuildQueue;
|
ShaderBuildQueue& mShaderBuildQueue;
|
||||||
VideoBackend& mVideoBackend;
|
VideoBackend& mVideoBackend;
|
||||||
|
std::size_t mPendingCoordinatorShaderBuildEvents = 0;
|
||||||
|
std::size_t mPendingCoordinatorCompileStatusEvents = 0;
|
||||||
|
std::size_t mPendingCoordinatorRenderResetEvents = 0;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#include "ShaderBuildQueue.h"
|
#include "ShaderBuildQueue.h"
|
||||||
|
|
||||||
|
#include "RuntimeEventDispatcher.h"
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
@@ -8,8 +10,9 @@ namespace
|
|||||||
constexpr auto kShaderBuildDebounce = std::chrono::milliseconds(400);
|
constexpr auto kShaderBuildDebounce = std::chrono::milliseconds(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderBuildQueue::ShaderBuildQueue(RuntimeSnapshotProvider& runtimeSnapshotProvider) :
|
ShaderBuildQueue::ShaderBuildQueue(RuntimeSnapshotProvider& runtimeSnapshotProvider, RuntimeEventDispatcher& runtimeEventDispatcher) :
|
||||||
mRuntimeSnapshotProvider(runtimeSnapshotProvider),
|
mRuntimeSnapshotProvider(runtimeSnapshotProvider),
|
||||||
|
mRuntimeEventDispatcher(runtimeEventDispatcher),
|
||||||
mWorkerThread([this]() { WorkerLoop(); })
|
mWorkerThread([this]() { WorkerLoop(); })
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -44,6 +47,18 @@ bool ShaderBuildQueue::TryConsumeReadyBuild(PreparedShaderBuild& build)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ShaderBuildQueue::TryConsumeReadyBuild(uint64_t expectedGeneration, PreparedShaderBuild& build)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(mMutex);
|
||||||
|
if (!mHasReadyBuild || mReadyBuild.generation != expectedGeneration)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
build = std::move(mReadyBuild);
|
||||||
|
mReadyBuild = PreparedShaderBuild();
|
||||||
|
mHasReadyBuild = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void ShaderBuildQueue::Stop()
|
void ShaderBuildQueue::Stop()
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@@ -97,13 +112,20 @@ void ShaderBuildQueue::WorkerLoop()
|
|||||||
|
|
||||||
PreparedShaderBuild build = Build(generation, outputWidth, outputHeight);
|
PreparedShaderBuild build = Build(generation, outputWidth, outputHeight);
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(mMutex);
|
bool shouldPublish = false;
|
||||||
if (mStopping)
|
{
|
||||||
return;
|
std::lock_guard<std::mutex> lock(mMutex);
|
||||||
if (generation != mRequestedGeneration)
|
if (mStopping)
|
||||||
continue;
|
return;
|
||||||
mReadyBuild = std::move(build);
|
if (generation != mRequestedGeneration)
|
||||||
mHasReadyBuild = true;
|
continue;
|
||||||
|
mReadyBuild = build;
|
||||||
|
mHasReadyBuild = true;
|
||||||
|
shouldPublish = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldPublish)
|
||||||
|
PublishBuildLifecycleEvent(build, outputWidth, outputHeight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,3 +152,15 @@ PreparedShaderBuild ShaderBuildQueue::Build(uint64_t generation, unsigned output
|
|||||||
build.message = "Shader layers prepared successfully.";
|
build.message = "Shader layers prepared successfully.";
|
||||||
return build;
|
return build;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ShaderBuildQueue::PublishBuildLifecycleEvent(const PreparedShaderBuild& build, unsigned outputWidth, unsigned outputHeight) const
|
||||||
|
{
|
||||||
|
ShaderBuildEvent event;
|
||||||
|
event.phase = build.succeeded ? RuntimeEventShaderBuildPhase::Prepared : RuntimeEventShaderBuildPhase::Failed;
|
||||||
|
event.generation = build.generation;
|
||||||
|
event.inputWidth = outputWidth;
|
||||||
|
event.inputHeight = outputHeight;
|
||||||
|
event.succeeded = build.succeeded;
|
||||||
|
event.message = build.message;
|
||||||
|
mRuntimeEventDispatcher.PublishPayload(event, "ShaderBuildQueue");
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
#include <thread>
|
#include <thread>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
class RuntimeEventDispatcher;
|
||||||
|
|
||||||
struct PreparedLayerShader
|
struct PreparedLayerShader
|
||||||
{
|
{
|
||||||
RuntimeRenderState state;
|
RuntimeRenderState state;
|
||||||
@@ -28,7 +30,7 @@ struct PreparedShaderBuild
|
|||||||
class ShaderBuildQueue
|
class ShaderBuildQueue
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit ShaderBuildQueue(RuntimeSnapshotProvider& runtimeSnapshotProvider);
|
ShaderBuildQueue(RuntimeSnapshotProvider& runtimeSnapshotProvider, RuntimeEventDispatcher& runtimeEventDispatcher);
|
||||||
~ShaderBuildQueue();
|
~ShaderBuildQueue();
|
||||||
|
|
||||||
ShaderBuildQueue(const ShaderBuildQueue&) = delete;
|
ShaderBuildQueue(const ShaderBuildQueue&) = delete;
|
||||||
@@ -36,13 +38,16 @@ public:
|
|||||||
|
|
||||||
void RequestBuild(unsigned outputWidth, unsigned outputHeight);
|
void RequestBuild(unsigned outputWidth, unsigned outputHeight);
|
||||||
bool TryConsumeReadyBuild(PreparedShaderBuild& build);
|
bool TryConsumeReadyBuild(PreparedShaderBuild& build);
|
||||||
|
bool TryConsumeReadyBuild(uint64_t expectedGeneration, PreparedShaderBuild& build);
|
||||||
void Stop();
|
void Stop();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void WorkerLoop();
|
void WorkerLoop();
|
||||||
PreparedShaderBuild Build(uint64_t generation, unsigned outputWidth, unsigned outputHeight);
|
PreparedShaderBuild Build(uint64_t generation, unsigned outputWidth, unsigned outputHeight);
|
||||||
|
void PublishBuildLifecycleEvent(const PreparedShaderBuild& build, unsigned outputWidth, unsigned outputHeight) const;
|
||||||
|
|
||||||
RuntimeSnapshotProvider& mRuntimeSnapshotProvider;
|
RuntimeSnapshotProvider& mRuntimeSnapshotProvider;
|
||||||
|
RuntimeEventDispatcher& mRuntimeEventDispatcher;
|
||||||
std::thread mWorkerThread;
|
std::thread mWorkerThread;
|
||||||
std::mutex mMutex;
|
std::mutex mMutex;
|
||||||
std::condition_variable mCondition;
|
std::condition_variable mCondition;
|
||||||
|
|||||||
@@ -1,8 +1,27 @@
|
|||||||
#include "RuntimeCoordinator.h"
|
#include "RuntimeCoordinator.h"
|
||||||
|
|
||||||
|
#include "RuntimeEventDispatcher.h"
|
||||||
|
#include "RuntimeEventPayloads.h"
|
||||||
#include "RuntimeParameterUtils.h"
|
#include "RuntimeParameterUtils.h"
|
||||||
#include "RuntimeStore.h"
|
#include "RuntimeStore.h"
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
RuntimeEventRenderResetScope ToRuntimeEventRenderResetScope(RuntimeCoordinatorRenderResetScope scope)
|
||||||
|
{
|
||||||
|
switch (scope)
|
||||||
|
{
|
||||||
|
case RuntimeCoordinatorRenderResetScope::TemporalHistoryOnly:
|
||||||
|
return RuntimeEventRenderResetScope::TemporalHistoryOnly;
|
||||||
|
case RuntimeCoordinatorRenderResetScope::TemporalHistoryAndFeedback:
|
||||||
|
return RuntimeEventRenderResetScope::TemporalHistoryAndFeedback;
|
||||||
|
case RuntimeCoordinatorRenderResetScope::None:
|
||||||
|
default:
|
||||||
|
return RuntimeEventRenderResetScope::None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
RuntimeCoordinator::RuntimeCoordinator(RuntimeStore& runtimeStore, RuntimeEventDispatcher& runtimeEventDispatcher) :
|
RuntimeCoordinator::RuntimeCoordinator(RuntimeStore& runtimeStore, RuntimeEventDispatcher& runtimeEventDispatcher) :
|
||||||
mRuntimeStore(runtimeStore),
|
mRuntimeStore(runtimeStore),
|
||||||
mRuntimeEventDispatcher(runtimeEventDispatcher)
|
mRuntimeEventDispatcher(runtimeEventDispatcher)
|
||||||
@@ -14,9 +33,15 @@ RuntimeCoordinatorResult RuntimeCoordinator::AddLayer(const std::string& shaderI
|
|||||||
std::lock_guard<std::mutex> lock(mMutex);
|
std::lock_guard<std::mutex> lock(mMutex);
|
||||||
std::string error;
|
std::string error;
|
||||||
if (!ValidateShaderExists(shaderId, error))
|
if (!ValidateShaderExists(shaderId, error))
|
||||||
return ApplyStoreMutation(false, error, false, false);
|
{
|
||||||
|
RuntimeCoordinatorResult result = ApplyStoreMutation(false, error, false, false);
|
||||||
|
PublishCoordinatorResult("AddLayer", result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
return ApplyStoreMutation(mRuntimeStore.CreateStoredLayer(shaderId, error), error, true, true);
|
RuntimeCoordinatorResult result = ApplyStoreMutation(mRuntimeStore.CreateStoredLayer(shaderId, error), error, true, true);
|
||||||
|
PublishCoordinatorResult("AddLayer", result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
RuntimeCoordinatorResult RuntimeCoordinator::RemoveLayer(const std::string& layerId)
|
RuntimeCoordinatorResult RuntimeCoordinator::RemoveLayer(const std::string& layerId)
|
||||||
@@ -24,9 +49,15 @@ RuntimeCoordinatorResult RuntimeCoordinator::RemoveLayer(const std::string& laye
|
|||||||
std::lock_guard<std::mutex> lock(mMutex);
|
std::lock_guard<std::mutex> lock(mMutex);
|
||||||
std::string error;
|
std::string error;
|
||||||
if (!ValidateLayerExists(layerId, error))
|
if (!ValidateLayerExists(layerId, error))
|
||||||
return ApplyStoreMutation(false, error, false, false);
|
{
|
||||||
|
RuntimeCoordinatorResult result = ApplyStoreMutation(false, error, false, false);
|
||||||
|
PublishCoordinatorResult("RemoveLayer", result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
return ApplyStoreMutation(mRuntimeStore.DeleteStoredLayer(layerId, error), error, true, true);
|
RuntimeCoordinatorResult result = ApplyStoreMutation(mRuntimeStore.DeleteStoredLayer(layerId, error), error, true, true);
|
||||||
|
PublishCoordinatorResult("RemoveLayer", result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
RuntimeCoordinatorResult RuntimeCoordinator::MoveLayer(const std::string& layerId, int direction)
|
RuntimeCoordinatorResult RuntimeCoordinator::MoveLayer(const std::string& layerId, int direction)
|
||||||
@@ -35,11 +66,20 @@ RuntimeCoordinatorResult RuntimeCoordinator::MoveLayer(const std::string& layerI
|
|||||||
std::string error;
|
std::string error;
|
||||||
bool shouldMove = false;
|
bool shouldMove = false;
|
||||||
if (!ResolveLayerMove(layerId, direction, shouldMove, error))
|
if (!ResolveLayerMove(layerId, direction, shouldMove, error))
|
||||||
return ApplyStoreMutation(false, error, false, false);
|
{
|
||||||
|
RuntimeCoordinatorResult result = ApplyStoreMutation(false, error, false, false);
|
||||||
|
PublishCoordinatorResult("MoveLayer", result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
if (!shouldMove)
|
if (!shouldMove)
|
||||||
return BuildAcceptedNoReloadResult();
|
{
|
||||||
|
RuntimeCoordinatorResult result = BuildAcceptedNoReloadResult();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
return ApplyStoreMutation(mRuntimeStore.MoveStoredLayer(layerId, direction, error), error, true, true);
|
RuntimeCoordinatorResult result = ApplyStoreMutation(mRuntimeStore.MoveStoredLayer(layerId, direction, error), error, true, true);
|
||||||
|
PublishCoordinatorResult("MoveLayer", result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
RuntimeCoordinatorResult RuntimeCoordinator::MoveLayerToIndex(const std::string& layerId, std::size_t targetIndex)
|
RuntimeCoordinatorResult RuntimeCoordinator::MoveLayerToIndex(const std::string& layerId, std::size_t targetIndex)
|
||||||
@@ -48,11 +88,20 @@ RuntimeCoordinatorResult RuntimeCoordinator::MoveLayerToIndex(const std::string&
|
|||||||
std::string error;
|
std::string error;
|
||||||
bool shouldMove = false;
|
bool shouldMove = false;
|
||||||
if (!ResolveLayerMoveToIndex(layerId, targetIndex, shouldMove, error))
|
if (!ResolveLayerMoveToIndex(layerId, targetIndex, shouldMove, error))
|
||||||
return ApplyStoreMutation(false, error, false, false);
|
{
|
||||||
|
RuntimeCoordinatorResult result = ApplyStoreMutation(false, error, false, false);
|
||||||
|
PublishCoordinatorResult("MoveLayerToIndex", result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
if (!shouldMove)
|
if (!shouldMove)
|
||||||
return BuildAcceptedNoReloadResult();
|
{
|
||||||
|
RuntimeCoordinatorResult result = BuildAcceptedNoReloadResult();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
return ApplyStoreMutation(mRuntimeStore.MoveStoredLayerToIndex(layerId, targetIndex, error), error, true, true);
|
RuntimeCoordinatorResult result = ApplyStoreMutation(mRuntimeStore.MoveStoredLayerToIndex(layerId, targetIndex, error), error, true, true);
|
||||||
|
PublishCoordinatorResult("MoveLayerToIndex", result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
RuntimeCoordinatorResult RuntimeCoordinator::SetLayerBypass(const std::string& layerId, bool bypassed)
|
RuntimeCoordinatorResult RuntimeCoordinator::SetLayerBypass(const std::string& layerId, bool bypassed)
|
||||||
@@ -60,9 +109,15 @@ RuntimeCoordinatorResult RuntimeCoordinator::SetLayerBypass(const std::string& l
|
|||||||
std::lock_guard<std::mutex> lock(mMutex);
|
std::lock_guard<std::mutex> lock(mMutex);
|
||||||
std::string error;
|
std::string error;
|
||||||
if (!ValidateLayerExists(layerId, error))
|
if (!ValidateLayerExists(layerId, error))
|
||||||
return ApplyStoreMutation(false, error, false, false);
|
{
|
||||||
|
RuntimeCoordinatorResult result = ApplyStoreMutation(false, error, false, false);
|
||||||
|
PublishCoordinatorResult("SetLayerBypass", result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
return ApplyStoreMutation(mRuntimeStore.SetStoredLayerBypassState(layerId, bypassed, error), error, true, false);
|
RuntimeCoordinatorResult result = ApplyStoreMutation(mRuntimeStore.SetStoredLayerBypassState(layerId, bypassed, error), error, true, false);
|
||||||
|
PublishCoordinatorResult("SetLayerBypass", result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
RuntimeCoordinatorResult RuntimeCoordinator::SetLayerShader(const std::string& layerId, const std::string& shaderId)
|
RuntimeCoordinatorResult RuntimeCoordinator::SetLayerShader(const std::string& layerId, const std::string& shaderId)
|
||||||
@@ -70,9 +125,15 @@ RuntimeCoordinatorResult RuntimeCoordinator::SetLayerShader(const std::string& l
|
|||||||
std::lock_guard<std::mutex> lock(mMutex);
|
std::lock_guard<std::mutex> lock(mMutex);
|
||||||
std::string error;
|
std::string error;
|
||||||
if (!ValidateLayerExists(layerId, error) || !ValidateShaderExists(shaderId, error))
|
if (!ValidateLayerExists(layerId, error) || !ValidateShaderExists(shaderId, error))
|
||||||
return ApplyStoreMutation(false, error, false, false);
|
{
|
||||||
|
RuntimeCoordinatorResult result = ApplyStoreMutation(false, error, false, false);
|
||||||
|
PublishCoordinatorResult("SetLayerShader", result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
return ApplyStoreMutation(mRuntimeStore.SetStoredLayerShaderSelection(layerId, shaderId, error), error, true, false);
|
RuntimeCoordinatorResult result = ApplyStoreMutation(mRuntimeStore.SetStoredLayerShaderSelection(layerId, shaderId, error), error, true, false);
|
||||||
|
PublishCoordinatorResult("SetLayerShader", result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
RuntimeCoordinatorResult RuntimeCoordinator::UpdateLayerParameter(const std::string& layerId, const std::string& parameterId, const JsonValue& newValue)
|
RuntimeCoordinatorResult RuntimeCoordinator::UpdateLayerParameter(const std::string& layerId, const std::string& parameterId, const JsonValue& newValue)
|
||||||
@@ -81,9 +142,15 @@ RuntimeCoordinatorResult RuntimeCoordinator::UpdateLayerParameter(const std::str
|
|||||||
std::string error;
|
std::string error;
|
||||||
ResolvedParameterMutation mutation;
|
ResolvedParameterMutation mutation;
|
||||||
if (!BuildParameterMutationById(layerId, parameterId, newValue, true, mutation, error))
|
if (!BuildParameterMutationById(layerId, parameterId, newValue, true, mutation, error))
|
||||||
return ApplyStoreMutation(false, error, false, false);
|
{
|
||||||
|
RuntimeCoordinatorResult result = ApplyStoreMutation(false, error, false, false);
|
||||||
|
PublishCoordinatorResult("UpdateLayerParameter", result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
return ApplyStoreMutation(mRuntimeStore.SetStoredParameterValue(mutation.layerId, mutation.parameterId, mutation.value, mutation.persistState, error), error, false, false);
|
RuntimeCoordinatorResult result = ApplyStoreMutation(mRuntimeStore.SetStoredParameterValue(mutation.layerId, mutation.parameterId, mutation.value, mutation.persistState, error), error, false, false);
|
||||||
|
PublishCoordinatorResult("UpdateLayerParameter", result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
RuntimeCoordinatorResult RuntimeCoordinator::UpdateLayerParameterByControlKey(const std::string& layerKey, const std::string& parameterKey, const JsonValue& newValue)
|
RuntimeCoordinatorResult RuntimeCoordinator::UpdateLayerParameterByControlKey(const std::string& layerKey, const std::string& parameterKey, const JsonValue& newValue)
|
||||||
@@ -92,9 +159,15 @@ RuntimeCoordinatorResult RuntimeCoordinator::UpdateLayerParameterByControlKey(co
|
|||||||
std::string error;
|
std::string error;
|
||||||
ResolvedParameterMutation mutation;
|
ResolvedParameterMutation mutation;
|
||||||
if (!BuildParameterMutationByControlKey(layerKey, parameterKey, newValue, true, mutation, error))
|
if (!BuildParameterMutationByControlKey(layerKey, parameterKey, newValue, true, mutation, error))
|
||||||
return ApplyStoreMutation(false, error, false, false);
|
{
|
||||||
|
RuntimeCoordinatorResult result = ApplyStoreMutation(false, error, false, false);
|
||||||
|
PublishCoordinatorResult("UpdateLayerParameterByControlKey", result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
return ApplyStoreMutation(mRuntimeStore.SetStoredParameterValue(mutation.layerId, mutation.parameterId, mutation.value, mutation.persistState, error), error, false, false);
|
RuntimeCoordinatorResult result = ApplyStoreMutation(mRuntimeStore.SetStoredParameterValue(mutation.layerId, mutation.parameterId, mutation.value, mutation.persistState, error), error, false, false);
|
||||||
|
PublishCoordinatorResult("UpdateLayerParameterByControlKey", result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
RuntimeCoordinatorResult RuntimeCoordinator::CommitOscParameterByControlKey(const std::string& layerKey, const std::string& parameterKey, const JsonValue& newValue)
|
RuntimeCoordinatorResult RuntimeCoordinator::CommitOscParameterByControlKey(const std::string& layerKey, const std::string& parameterKey, const JsonValue& newValue)
|
||||||
@@ -103,9 +176,15 @@ RuntimeCoordinatorResult RuntimeCoordinator::CommitOscParameterByControlKey(cons
|
|||||||
std::string error;
|
std::string error;
|
||||||
ResolvedParameterMutation mutation;
|
ResolvedParameterMutation mutation;
|
||||||
if (!BuildParameterMutationByControlKey(layerKey, parameterKey, newValue, false, mutation, error))
|
if (!BuildParameterMutationByControlKey(layerKey, parameterKey, newValue, false, mutation, error))
|
||||||
return ApplyStoreMutation(false, error, false, false);
|
{
|
||||||
|
RuntimeCoordinatorResult result = ApplyStoreMutation(false, error, false, false);
|
||||||
|
PublishCoordinatorResult("CommitOscParameterByControlKey", result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
return ApplyStoreMutation(mRuntimeStore.SetStoredParameterValue(mutation.layerId, mutation.parameterId, mutation.value, mutation.persistState, error), error, false, false);
|
RuntimeCoordinatorResult result = ApplyStoreMutation(mRuntimeStore.SetStoredParameterValue(mutation.layerId, mutation.parameterId, mutation.value, mutation.persistState, error), error, false, false);
|
||||||
|
PublishCoordinatorResult("CommitOscParameterByControlKey", result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
RuntimeCoordinatorResult RuntimeCoordinator::ResetLayerParameters(const std::string& layerId)
|
RuntimeCoordinatorResult RuntimeCoordinator::ResetLayerParameters(const std::string& layerId)
|
||||||
@@ -113,14 +192,22 @@ RuntimeCoordinatorResult RuntimeCoordinator::ResetLayerParameters(const std::str
|
|||||||
std::lock_guard<std::mutex> lock(mMutex);
|
std::lock_guard<std::mutex> lock(mMutex);
|
||||||
std::string error;
|
std::string error;
|
||||||
if (!ValidateLayerExists(layerId, error))
|
if (!ValidateLayerExists(layerId, error))
|
||||||
return ApplyStoreMutation(false, error, false, false);
|
{
|
||||||
|
RuntimeCoordinatorResult result = ApplyStoreMutation(false, error, false, false);
|
||||||
|
PublishCoordinatorResult("ResetLayerParameters", result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
RuntimeCoordinatorResult result = ApplyStoreMutation(mRuntimeStore.ResetStoredLayerParameterValues(layerId, error), error, false, false);
|
RuntimeCoordinatorResult result = ApplyStoreMutation(mRuntimeStore.ResetStoredLayerParameterValues(layerId, error), error, false, false);
|
||||||
if (!result.accepted)
|
if (!result.accepted)
|
||||||
|
{
|
||||||
|
PublishCoordinatorResult("ResetLayerParameters", result);
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
result.clearTransientOscState = true;
|
result.clearTransientOscState = true;
|
||||||
result.renderResetScope = RuntimeCoordinatorRenderResetScope::TemporalHistoryAndFeedback;
|
result.renderResetScope = RuntimeCoordinatorRenderResetScope::TemporalHistoryAndFeedback;
|
||||||
|
PublishCoordinatorResult("ResetLayerParameters", result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,9 +216,15 @@ RuntimeCoordinatorResult RuntimeCoordinator::SaveStackPreset(const std::string&
|
|||||||
std::lock_guard<std::mutex> lock(mMutex);
|
std::lock_guard<std::mutex> lock(mMutex);
|
||||||
std::string error;
|
std::string error;
|
||||||
if (!ValidatePresetName(presetName, error))
|
if (!ValidatePresetName(presetName, error))
|
||||||
return ApplyStoreMutation(false, error, false, false);
|
{
|
||||||
|
RuntimeCoordinatorResult result = ApplyStoreMutation(false, error, false, false);
|
||||||
|
PublishCoordinatorResult("SaveStackPreset", result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
return ApplyStoreMutation(mRuntimeStore.SaveStackPresetSnapshot(presetName, error), error, false, false);
|
RuntimeCoordinatorResult result = ApplyStoreMutation(mRuntimeStore.SaveStackPresetSnapshot(presetName, error), error, false, false);
|
||||||
|
PublishCoordinatorResult("SaveStackPreset", result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
RuntimeCoordinatorResult RuntimeCoordinator::LoadStackPreset(const std::string& presetName)
|
RuntimeCoordinatorResult RuntimeCoordinator::LoadStackPreset(const std::string& presetName)
|
||||||
@@ -139,15 +232,23 @@ RuntimeCoordinatorResult RuntimeCoordinator::LoadStackPreset(const std::string&
|
|||||||
std::lock_guard<std::mutex> lock(mMutex);
|
std::lock_guard<std::mutex> lock(mMutex);
|
||||||
std::string error;
|
std::string error;
|
||||||
if (!ValidatePresetName(presetName, error))
|
if (!ValidatePresetName(presetName, error))
|
||||||
return ApplyStoreMutation(false, error, false, false);
|
{
|
||||||
|
RuntimeCoordinatorResult result = ApplyStoreMutation(false, error, false, false);
|
||||||
|
PublishCoordinatorResult("LoadStackPreset", result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
return ApplyStoreMutation(mRuntimeStore.LoadStackPresetSnapshot(presetName, error), error, true, false);
|
RuntimeCoordinatorResult result = ApplyStoreMutation(mRuntimeStore.LoadStackPresetSnapshot(presetName, error), error, true, false);
|
||||||
|
PublishCoordinatorResult("LoadStackPreset", result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
RuntimeCoordinatorResult RuntimeCoordinator::RequestShaderReload(bool preserveFeedbackState)
|
RuntimeCoordinatorResult RuntimeCoordinator::RequestShaderReload(bool preserveFeedbackState)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(mMutex);
|
std::lock_guard<std::mutex> lock(mMutex);
|
||||||
return BuildQueuedReloadResult(preserveFeedbackState);
|
RuntimeCoordinatorResult result = BuildQueuedReloadResult(preserveFeedbackState);
|
||||||
|
PublishCoordinatorFollowUpEvents("RequestShaderReload", result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
RuntimeCoordinatorResult RuntimeCoordinator::PollRuntimeStoreChanges(bool& registryChanged)
|
RuntimeCoordinatorResult RuntimeCoordinator::PollRuntimeStoreChanges(bool& registryChanged)
|
||||||
@@ -158,13 +259,24 @@ RuntimeCoordinatorResult RuntimeCoordinator::PollRuntimeStoreChanges(bool& regis
|
|||||||
bool reloadRequested = false;
|
bool reloadRequested = false;
|
||||||
std::string error;
|
std::string error;
|
||||||
if (!mRuntimeStore.PollStoredFileChanges(registryChanged, reloadRequested, error))
|
if (!mRuntimeStore.PollStoredFileChanges(registryChanged, reloadRequested, error))
|
||||||
return HandleRuntimePollFailure(error);
|
{
|
||||||
|
RuntimeCoordinatorResult result = HandleRuntimePollFailure(error);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
if (reloadRequested)
|
if (reloadRequested)
|
||||||
return BuildQueuedReloadResult(false);
|
{
|
||||||
|
RuntimeCoordinatorResult result = BuildQueuedReloadResult(false);
|
||||||
|
PublishCoordinatorFollowUpEvents("PollRuntimeStoreChanges", result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
if (registryChanged)
|
if (registryChanged)
|
||||||
return BuildAcceptedNoReloadResult();
|
{
|
||||||
|
RuntimeCoordinatorResult result = BuildAcceptedNoReloadResult();
|
||||||
|
PublishCoordinatorFollowUpEvents("PollRuntimeStoreChanges", result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
RuntimeCoordinatorResult result;
|
RuntimeCoordinatorResult result;
|
||||||
result.accepted = true;
|
result.accepted = true;
|
||||||
@@ -179,6 +291,7 @@ RuntimeCoordinatorResult RuntimeCoordinator::HandleRuntimePollFailure(const std:
|
|||||||
result.compileStatusChanged = true;
|
result.compileStatusChanged = true;
|
||||||
result.compileStatusSucceeded = false;
|
result.compileStatusSucceeded = false;
|
||||||
result.compileStatusMessage = error;
|
result.compileStatusMessage = error;
|
||||||
|
PublishCoordinatorFollowUpEvents("HandleRuntimePollFailure", result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,6 +308,7 @@ RuntimeCoordinatorResult RuntimeCoordinator::HandlePreparedShaderBuildFailure(co
|
|||||||
result.compileStatusSucceeded = false;
|
result.compileStatusSucceeded = false;
|
||||||
result.compileStatusMessage = error;
|
result.compileStatusMessage = error;
|
||||||
result.committedStateMode = RuntimeCoordinatorCommittedStateMode::UseCommittedStates;
|
result.committedStateMode = RuntimeCoordinatorCommittedStateMode::UseCommittedStates;
|
||||||
|
PublishCoordinatorFollowUpEvents("HandlePreparedShaderBuildFailure", result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,13 +325,16 @@ RuntimeCoordinatorResult RuntimeCoordinator::HandlePreparedShaderBuildSuccess()
|
|||||||
result.compileStatusMessage = "Shader layers compiled successfully.";
|
result.compileStatusMessage = "Shader layers compiled successfully.";
|
||||||
result.committedStateMode = RuntimeCoordinatorCommittedStateMode::UseLiveSnapshots;
|
result.committedStateMode = RuntimeCoordinatorCommittedStateMode::UseLiveSnapshots;
|
||||||
mPreserveFeedbackOnNextShaderBuild = false;
|
mPreserveFeedbackOnNextShaderBuild = false;
|
||||||
|
PublishCoordinatorFollowUpEvents("HandlePreparedShaderBuildSuccess", result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
RuntimeCoordinatorResult RuntimeCoordinator::HandleRuntimeReloadRequest()
|
RuntimeCoordinatorResult RuntimeCoordinator::HandleRuntimeReloadRequest()
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(mMutex);
|
std::lock_guard<std::mutex> lock(mMutex);
|
||||||
return BuildQueuedReloadResult(false);
|
RuntimeCoordinatorResult result = BuildQueuedReloadResult(false);
|
||||||
|
PublishCoordinatorFollowUpEvents("HandleRuntimeReloadRequest", result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RuntimeCoordinator::ApplyCommittedStateMode(RuntimeCoordinatorCommittedStateMode mode)
|
void RuntimeCoordinator::ApplyCommittedStateMode(RuntimeCoordinatorCommittedStateMode mode)
|
||||||
@@ -369,3 +486,68 @@ RuntimeCoordinatorResult RuntimeCoordinator::BuildAcceptedNoReloadResult() const
|
|||||||
result.runtimeStateBroadcastRequired = true;
|
result.runtimeStateBroadcastRequired = true;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RuntimeCoordinator::PublishCoordinatorResult(const std::string& action, const RuntimeCoordinatorResult& result) const
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
RuntimeMutationEvent mutation;
|
||||||
|
mutation.action = action;
|
||||||
|
mutation.accepted = result.accepted;
|
||||||
|
mutation.runtimeStateChanged = result.accepted && result.runtimeStateBroadcastRequired;
|
||||||
|
mutation.runtimeStateBroadcastRequired = result.runtimeStateBroadcastRequired;
|
||||||
|
mutation.shaderBuildRequested = result.shaderBuildRequested;
|
||||||
|
mutation.clearTransientOscState = result.clearTransientOscState;
|
||||||
|
mutation.renderResetScope = ToRuntimeEventRenderResetScope(result.renderResetScope);
|
||||||
|
mutation.errorMessage = result.errorMessage;
|
||||||
|
mRuntimeEventDispatcher.PublishPayload(mutation, "RuntimeCoordinator");
|
||||||
|
|
||||||
|
PublishCoordinatorFollowUpEvents(action, result);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RuntimeCoordinator::PublishCoordinatorFollowUpEvents(const std::string& action, const RuntimeCoordinatorResult& result) const
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!result.accepted)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (result.runtimeStateBroadcastRequired)
|
||||||
|
{
|
||||||
|
RuntimeStateChangedEvent stateChanged;
|
||||||
|
stateChanged.reason = action;
|
||||||
|
stateChanged.renderVisible = result.renderResetScope != RuntimeCoordinatorRenderResetScope::None;
|
||||||
|
mRuntimeEventDispatcher.PublishPayload(stateChanged, "RuntimeCoordinator");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.shaderBuildRequested)
|
||||||
|
{
|
||||||
|
RuntimeReloadRequestedEvent reloadRequested;
|
||||||
|
reloadRequested.preserveFeedbackState = mPreserveFeedbackOnNextShaderBuild;
|
||||||
|
reloadRequested.reason = action;
|
||||||
|
mRuntimeEventDispatcher.PublishPayload(reloadRequested, "RuntimeCoordinator");
|
||||||
|
|
||||||
|
ShaderBuildEvent shaderBuild;
|
||||||
|
shaderBuild.phase = RuntimeEventShaderBuildPhase::Requested;
|
||||||
|
shaderBuild.preserveFeedbackState = mPreserveFeedbackOnNextShaderBuild;
|
||||||
|
shaderBuild.succeeded = true;
|
||||||
|
shaderBuild.message = result.compileStatusMessage;
|
||||||
|
mRuntimeEventDispatcher.PublishPayload(shaderBuild, "RuntimeCoordinator");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.compileStatusChanged)
|
||||||
|
{
|
||||||
|
CompileStatusChangedEvent compileStatus;
|
||||||
|
compileStatus.succeeded = result.compileStatusSucceeded;
|
||||||
|
compileStatus.message = result.compileStatusMessage;
|
||||||
|
mRuntimeEventDispatcher.PublishPayload(compileStatus, "RuntimeCoordinator");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -92,6 +92,8 @@ private:
|
|||||||
RuntimeCoordinatorResult ApplyStoreMutation(bool succeeded, const std::string& errorMessage, bool reloadRequired, bool preserveFeedbackState);
|
RuntimeCoordinatorResult ApplyStoreMutation(bool succeeded, const std::string& errorMessage, bool reloadRequired, bool preserveFeedbackState);
|
||||||
RuntimeCoordinatorResult BuildQueuedReloadResult(bool preserveFeedbackState);
|
RuntimeCoordinatorResult BuildQueuedReloadResult(bool preserveFeedbackState);
|
||||||
RuntimeCoordinatorResult BuildAcceptedNoReloadResult() const;
|
RuntimeCoordinatorResult BuildAcceptedNoReloadResult() const;
|
||||||
|
void PublishCoordinatorResult(const std::string& action, const RuntimeCoordinatorResult& result) const;
|
||||||
|
void PublishCoordinatorFollowUpEvents(const std::string& action, const RuntimeCoordinatorResult& result) const;
|
||||||
|
|
||||||
RuntimeStore& mRuntimeStore;
|
RuntimeStore& mRuntimeStore;
|
||||||
RuntimeEventDispatcher& mRuntimeEventDispatcher;
|
RuntimeEventDispatcher& mRuntimeEventDispatcher;
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ struct RuntimeEventDispatchResult
|
|||||||
std::size_t dispatchedEvents = 0;
|
std::size_t dispatchedEvents = 0;
|
||||||
std::size_t handlerInvocations = 0;
|
std::size_t handlerInvocations = 0;
|
||||||
std::size_t handlerFailures = 0;
|
std::size_t handlerFailures = 0;
|
||||||
|
double dispatchDurationMilliseconds = 0.0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RuntimeEventDispatcher
|
class RuntimeEventDispatcher
|
||||||
@@ -56,6 +57,7 @@ public:
|
|||||||
|
|
||||||
RuntimeEventDispatchResult DispatchPending(std::size_t maxEvents = 0)
|
RuntimeEventDispatchResult DispatchPending(std::size_t maxEvents = 0)
|
||||||
{
|
{
|
||||||
|
const auto startedAt = std::chrono::steady_clock::now();
|
||||||
RuntimeEventDispatchResult result;
|
RuntimeEventDispatchResult result;
|
||||||
std::vector<RuntimeEvent> events = mQueue.Drain(maxEvents);
|
std::vector<RuntimeEvent> events = mQueue.Drain(maxEvents);
|
||||||
result.dispatchedEvents = events.size();
|
result.dispatchedEvents = events.size();
|
||||||
@@ -78,6 +80,8 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result.dispatchDurationMilliseconds =
|
||||||
|
std::chrono::duration<double, std::milli>(std::chrono::steady_clock::now() - startedAt).count();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -143,6 +143,7 @@ struct RuntimeStatePresentationChangedEvent
|
|||||||
struct ShaderBuildEvent
|
struct ShaderBuildEvent
|
||||||
{
|
{
|
||||||
RuntimeEventShaderBuildPhase phase = RuntimeEventShaderBuildPhase::Requested;
|
RuntimeEventShaderBuildPhase phase = RuntimeEventShaderBuildPhase::Requested;
|
||||||
|
uint64_t generation = 0;
|
||||||
unsigned inputWidth = 0;
|
unsigned inputWidth = 0;
|
||||||
unsigned inputHeight = 0;
|
unsigned inputHeight = 0;
|
||||||
bool preserveFeedbackState = false;
|
bool preserveFeedbackState = false;
|
||||||
|
|||||||
@@ -80,6 +80,26 @@ JsonValue RuntimeStatePresenter::BuildRuntimeStateValue(const RuntimeStore& runt
|
|||||||
performance.set("flushedFrameCount", JsonValue(static_cast<double>(telemetrySnapshot.performance.flushedFrameCount)));
|
performance.set("flushedFrameCount", JsonValue(static_cast<double>(telemetrySnapshot.performance.flushedFrameCount)));
|
||||||
root.set("performance", performance);
|
root.set("performance", performance);
|
||||||
|
|
||||||
|
JsonValue eventQueue = JsonValue::MakeObject();
|
||||||
|
eventQueue.set("name", JsonValue(telemetrySnapshot.runtimeEvents.queue.queueName));
|
||||||
|
eventQueue.set("depth", JsonValue(static_cast<double>(telemetrySnapshot.runtimeEvents.queue.depth)));
|
||||||
|
eventQueue.set("capacity", JsonValue(static_cast<double>(telemetrySnapshot.runtimeEvents.queue.capacity)));
|
||||||
|
eventQueue.set("droppedCount", JsonValue(static_cast<double>(telemetrySnapshot.runtimeEvents.queue.droppedCount)));
|
||||||
|
eventQueue.set("oldestEventAgeMs", JsonValue(telemetrySnapshot.runtimeEvents.queue.oldestEventAgeMilliseconds));
|
||||||
|
|
||||||
|
JsonValue eventDispatch = JsonValue::MakeObject();
|
||||||
|
eventDispatch.set("dispatchCallCount", JsonValue(static_cast<double>(telemetrySnapshot.runtimeEvents.dispatch.dispatchCallCount)));
|
||||||
|
eventDispatch.set("dispatchedEventCount", JsonValue(static_cast<double>(telemetrySnapshot.runtimeEvents.dispatch.dispatchedEventCount)));
|
||||||
|
eventDispatch.set("handlerInvocationCount", JsonValue(static_cast<double>(telemetrySnapshot.runtimeEvents.dispatch.handlerInvocationCount)));
|
||||||
|
eventDispatch.set("handlerFailureCount", JsonValue(static_cast<double>(telemetrySnapshot.runtimeEvents.dispatch.handlerFailureCount)));
|
||||||
|
eventDispatch.set("lastDispatchDurationMs", JsonValue(telemetrySnapshot.runtimeEvents.dispatch.lastDispatchDurationMilliseconds));
|
||||||
|
eventDispatch.set("maxDispatchDurationMs", JsonValue(telemetrySnapshot.runtimeEvents.dispatch.maxDispatchDurationMilliseconds));
|
||||||
|
|
||||||
|
JsonValue runtimeEvents = JsonValue::MakeObject();
|
||||||
|
runtimeEvents.set("queue", eventQueue);
|
||||||
|
runtimeEvents.set("dispatch", eventDispatch);
|
||||||
|
root.set("runtimeEvents", runtimeEvents);
|
||||||
|
|
||||||
JsonValue shaderLibrary = JsonValue::MakeArray();
|
JsonValue shaderLibrary = JsonValue::MakeArray();
|
||||||
for (const ShaderPackageStatus& status : model.packageStatuses)
|
for (const ShaderPackageStatus& status : model.packageStatuses)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -111,6 +111,64 @@ bool HealthTelemetry::TryRecordFramePacingStats(double completionIntervalMillise
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HealthTelemetry::RecordRuntimeEventQueueMetrics(const std::string& queueName, std::size_t depth, std::size_t capacity,
|
||||||
|
uint64_t droppedCount, double oldestEventAgeMilliseconds)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(mMutex);
|
||||||
|
mRuntimeEvents.queue.queueName = queueName;
|
||||||
|
mRuntimeEvents.queue.depth = depth;
|
||||||
|
mRuntimeEvents.queue.capacity = capacity;
|
||||||
|
mRuntimeEvents.queue.droppedCount = droppedCount;
|
||||||
|
mRuntimeEvents.queue.oldestEventAgeMilliseconds = std::max(oldestEventAgeMilliseconds, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HealthTelemetry::TryRecordRuntimeEventQueueMetrics(const std::string& queueName, std::size_t depth, std::size_t capacity,
|
||||||
|
uint64_t droppedCount, double oldestEventAgeMilliseconds)
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(mMutex, std::try_to_lock);
|
||||||
|
if (!lock.owns_lock())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
mRuntimeEvents.queue.queueName = queueName;
|
||||||
|
mRuntimeEvents.queue.depth = depth;
|
||||||
|
mRuntimeEvents.queue.capacity = capacity;
|
||||||
|
mRuntimeEvents.queue.droppedCount = droppedCount;
|
||||||
|
mRuntimeEvents.queue.oldestEventAgeMilliseconds = std::max(oldestEventAgeMilliseconds, 0.0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HealthTelemetry::RecordRuntimeEventDispatchStats(std::size_t dispatchedEvents, std::size_t handlerInvocations,
|
||||||
|
std::size_t handlerFailures, double dispatchDurationMilliseconds)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(mMutex);
|
||||||
|
++mRuntimeEvents.dispatch.dispatchCallCount;
|
||||||
|
mRuntimeEvents.dispatch.dispatchedEventCount += static_cast<uint64_t>(dispatchedEvents);
|
||||||
|
mRuntimeEvents.dispatch.handlerInvocationCount += static_cast<uint64_t>(handlerInvocations);
|
||||||
|
mRuntimeEvents.dispatch.handlerFailureCount += static_cast<uint64_t>(handlerFailures);
|
||||||
|
mRuntimeEvents.dispatch.lastDispatchDurationMilliseconds = std::max(dispatchDurationMilliseconds, 0.0);
|
||||||
|
mRuntimeEvents.dispatch.maxDispatchDurationMilliseconds = std::max(
|
||||||
|
mRuntimeEvents.dispatch.maxDispatchDurationMilliseconds,
|
||||||
|
mRuntimeEvents.dispatch.lastDispatchDurationMilliseconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HealthTelemetry::TryRecordRuntimeEventDispatchStats(std::size_t dispatchedEvents, std::size_t handlerInvocations,
|
||||||
|
std::size_t handlerFailures, double dispatchDurationMilliseconds)
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(mMutex, std::try_to_lock);
|
||||||
|
if (!lock.owns_lock())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
++mRuntimeEvents.dispatch.dispatchCallCount;
|
||||||
|
mRuntimeEvents.dispatch.dispatchedEventCount += static_cast<uint64_t>(dispatchedEvents);
|
||||||
|
mRuntimeEvents.dispatch.handlerInvocationCount += static_cast<uint64_t>(handlerInvocations);
|
||||||
|
mRuntimeEvents.dispatch.handlerFailureCount += static_cast<uint64_t>(handlerFailures);
|
||||||
|
mRuntimeEvents.dispatch.lastDispatchDurationMilliseconds = std::max(dispatchDurationMilliseconds, 0.0);
|
||||||
|
mRuntimeEvents.dispatch.maxDispatchDurationMilliseconds = std::max(
|
||||||
|
mRuntimeEvents.dispatch.maxDispatchDurationMilliseconds,
|
||||||
|
mRuntimeEvents.dispatch.lastDispatchDurationMilliseconds);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
HealthTelemetry::SignalStatusSnapshot HealthTelemetry::GetSignalStatusSnapshot() const
|
HealthTelemetry::SignalStatusSnapshot HealthTelemetry::GetSignalStatusSnapshot() const
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(mMutex);
|
std::lock_guard<std::mutex> lock(mMutex);
|
||||||
@@ -129,6 +187,12 @@ HealthTelemetry::PerformanceSnapshot HealthTelemetry::GetPerformanceSnapshot() c
|
|||||||
return mPerformance;
|
return mPerformance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HealthTelemetry::RuntimeEventMetricsSnapshot HealthTelemetry::GetRuntimeEventMetricsSnapshot() const
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(mMutex);
|
||||||
|
return mRuntimeEvents;
|
||||||
|
}
|
||||||
|
|
||||||
HealthTelemetry::Snapshot HealthTelemetry::GetSnapshot() const
|
HealthTelemetry::Snapshot HealthTelemetry::GetSnapshot() const
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(mMutex);
|
std::lock_guard<std::mutex> lock(mMutex);
|
||||||
@@ -137,5 +201,6 @@ HealthTelemetry::Snapshot HealthTelemetry::GetSnapshot() const
|
|||||||
snapshot.signal = mSignalStatus;
|
snapshot.signal = mSignalStatus;
|
||||||
snapshot.videoIO = mVideoIOStatus;
|
snapshot.videoIO = mVideoIOStatus;
|
||||||
snapshot.performance = mPerformance;
|
snapshot.performance = mPerformance;
|
||||||
|
snapshot.runtimeEvents = mRuntimeEvents;
|
||||||
return snapshot;
|
return snapshot;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@@ -43,11 +44,37 @@ public:
|
|||||||
uint64_t flushedFrameCount = 0;
|
uint64_t flushedFrameCount = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct RuntimeEventQueueSnapshot
|
||||||
|
{
|
||||||
|
std::string queueName = "runtime-events";
|
||||||
|
std::size_t depth = 0;
|
||||||
|
std::size_t capacity = 0;
|
||||||
|
uint64_t droppedCount = 0;
|
||||||
|
double oldestEventAgeMilliseconds = 0.0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RuntimeEventDispatchSnapshot
|
||||||
|
{
|
||||||
|
uint64_t dispatchCallCount = 0;
|
||||||
|
uint64_t dispatchedEventCount = 0;
|
||||||
|
uint64_t handlerInvocationCount = 0;
|
||||||
|
uint64_t handlerFailureCount = 0;
|
||||||
|
double lastDispatchDurationMilliseconds = 0.0;
|
||||||
|
double maxDispatchDurationMilliseconds = 0.0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RuntimeEventMetricsSnapshot
|
||||||
|
{
|
||||||
|
RuntimeEventQueueSnapshot queue;
|
||||||
|
RuntimeEventDispatchSnapshot dispatch;
|
||||||
|
};
|
||||||
|
|
||||||
struct Snapshot
|
struct Snapshot
|
||||||
{
|
{
|
||||||
SignalStatusSnapshot signal;
|
SignalStatusSnapshot signal;
|
||||||
VideoIOStatusSnapshot videoIO;
|
VideoIOStatusSnapshot videoIO;
|
||||||
PerformanceSnapshot performance;
|
PerformanceSnapshot performance;
|
||||||
|
RuntimeEventMetricsSnapshot runtimeEvents;
|
||||||
};
|
};
|
||||||
|
|
||||||
HealthTelemetry() = default;
|
HealthTelemetry() = default;
|
||||||
@@ -70,9 +97,20 @@ public:
|
|||||||
bool TryRecordFramePacingStats(double completionIntervalMilliseconds, double smoothedCompletionIntervalMilliseconds,
|
bool TryRecordFramePacingStats(double completionIntervalMilliseconds, double smoothedCompletionIntervalMilliseconds,
|
||||||
double maxCompletionIntervalMilliseconds, uint64_t lateFrameCount, uint64_t droppedFrameCount, uint64_t flushedFrameCount);
|
double maxCompletionIntervalMilliseconds, uint64_t lateFrameCount, uint64_t droppedFrameCount, uint64_t flushedFrameCount);
|
||||||
|
|
||||||
|
void RecordRuntimeEventQueueMetrics(const std::string& queueName, std::size_t depth, std::size_t capacity,
|
||||||
|
uint64_t droppedCount, double oldestEventAgeMilliseconds);
|
||||||
|
bool TryRecordRuntimeEventQueueMetrics(const std::string& queueName, std::size_t depth, std::size_t capacity,
|
||||||
|
uint64_t droppedCount, double oldestEventAgeMilliseconds);
|
||||||
|
|
||||||
|
void RecordRuntimeEventDispatchStats(std::size_t dispatchedEvents, std::size_t handlerInvocations,
|
||||||
|
std::size_t handlerFailures, double dispatchDurationMilliseconds);
|
||||||
|
bool TryRecordRuntimeEventDispatchStats(std::size_t dispatchedEvents, std::size_t handlerInvocations,
|
||||||
|
std::size_t handlerFailures, double dispatchDurationMilliseconds);
|
||||||
|
|
||||||
SignalStatusSnapshot GetSignalStatusSnapshot() const;
|
SignalStatusSnapshot GetSignalStatusSnapshot() const;
|
||||||
VideoIOStatusSnapshot GetVideoIOStatusSnapshot() const;
|
VideoIOStatusSnapshot GetVideoIOStatusSnapshot() const;
|
||||||
PerformanceSnapshot GetPerformanceSnapshot() const;
|
PerformanceSnapshot GetPerformanceSnapshot() const;
|
||||||
|
RuntimeEventMetricsSnapshot GetRuntimeEventMetricsSnapshot() const;
|
||||||
Snapshot GetSnapshot() const;
|
Snapshot GetSnapshot() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -80,4 +118,5 @@ private:
|
|||||||
SignalStatusSnapshot mSignalStatus;
|
SignalStatusSnapshot mSignalStatus;
|
||||||
VideoIOStatusSnapshot mVideoIOStatus;
|
VideoIOStatusSnapshot mVideoIOStatus;
|
||||||
PerformanceSnapshot mPerformance;
|
PerformanceSnapshot mPerformance;
|
||||||
|
RuntimeEventMetricsSnapshot mRuntimeEvents;
|
||||||
};
|
};
|
||||||
|
|||||||
72
tests/HealthTelemetryTests.cpp
Normal file
72
tests/HealthTelemetryTests.cpp
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
#include "HealthTelemetry.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
int gFailures = 0;
|
||||||
|
|
||||||
|
void Expect(bool condition, const char* message)
|
||||||
|
{
|
||||||
|
if (condition)
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::cerr << "FAIL: " << message << "\n";
|
||||||
|
++gFailures;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestRuntimeEventQueueMetrics()
|
||||||
|
{
|
||||||
|
HealthTelemetry telemetry;
|
||||||
|
telemetry.RecordRuntimeEventQueueMetrics("runtime-events", 3, 64, 2, 12.5);
|
||||||
|
|
||||||
|
const HealthTelemetry::RuntimeEventMetricsSnapshot metrics = telemetry.GetRuntimeEventMetricsSnapshot();
|
||||||
|
Expect(metrics.queue.queueName == "runtime-events", "queue metrics store queue name");
|
||||||
|
Expect(metrics.queue.depth == 3, "queue metrics store depth");
|
||||||
|
Expect(metrics.queue.capacity == 64, "queue metrics store capacity");
|
||||||
|
Expect(metrics.queue.droppedCount == 2, "queue metrics store dropped count");
|
||||||
|
Expect(metrics.queue.oldestEventAgeMilliseconds == 12.5, "queue metrics store oldest event age");
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestRuntimeEventDispatchStats()
|
||||||
|
{
|
||||||
|
HealthTelemetry telemetry;
|
||||||
|
telemetry.RecordRuntimeEventDispatchStats(2, 5, 1, 0.75);
|
||||||
|
telemetry.RecordRuntimeEventDispatchStats(3, 6, 0, 0.25);
|
||||||
|
|
||||||
|
const HealthTelemetry::Snapshot snapshot = telemetry.GetSnapshot();
|
||||||
|
Expect(snapshot.runtimeEvents.dispatch.dispatchCallCount == 2, "dispatch stats count dispatch calls");
|
||||||
|
Expect(snapshot.runtimeEvents.dispatch.dispatchedEventCount == 5, "dispatch stats accumulate dispatched events");
|
||||||
|
Expect(snapshot.runtimeEvents.dispatch.handlerInvocationCount == 11, "dispatch stats accumulate handler invocations");
|
||||||
|
Expect(snapshot.runtimeEvents.dispatch.handlerFailureCount == 1, "dispatch stats accumulate handler failures");
|
||||||
|
Expect(snapshot.runtimeEvents.dispatch.lastDispatchDurationMilliseconds == 0.25, "dispatch stats store latest duration");
|
||||||
|
Expect(snapshot.runtimeEvents.dispatch.maxDispatchDurationMilliseconds == 0.75, "dispatch stats store max duration");
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestRuntimeEventTryRecord()
|
||||||
|
{
|
||||||
|
HealthTelemetry telemetry;
|
||||||
|
Expect(telemetry.TryRecordRuntimeEventQueueMetrics("runtime-events", 1, 4, 0, -5.0), "try queue metrics succeeds when uncontended");
|
||||||
|
Expect(telemetry.TryRecordRuntimeEventDispatchStats(1, 2, 0, -1.0), "try dispatch stats succeeds when uncontended");
|
||||||
|
|
||||||
|
const HealthTelemetry::RuntimeEventMetricsSnapshot metrics = telemetry.GetRuntimeEventMetricsSnapshot();
|
||||||
|
Expect(metrics.queue.oldestEventAgeMilliseconds == 0.0, "queue age is clamped to non-negative values");
|
||||||
|
Expect(metrics.dispatch.lastDispatchDurationMilliseconds == 0.0, "dispatch duration is clamped to non-negative values");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
TestRuntimeEventQueueMetrics();
|
||||||
|
TestRuntimeEventDispatchStats();
|
||||||
|
TestRuntimeEventTryRecord();
|
||||||
|
|
||||||
|
if (gFailures != 0)
|
||||||
|
{
|
||||||
|
std::cerr << gFailures << " HealthTelemetry test failure(s).\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "HealthTelemetry tests passed.\n";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user