Organisation
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include "ShaderTypes.h"
|
||||
#include "VideoIOTypes.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
struct RenderFrameInput
|
||||
{
|
||||
bool useCommittedLayerStates = false;
|
||||
bool hasInputSource = false;
|
||||
unsigned renderWidth = 0;
|
||||
unsigned renderHeight = 0;
|
||||
unsigned inputFrameWidth = 0;
|
||||
unsigned inputFrameHeight = 0;
|
||||
unsigned captureTextureWidth = 0;
|
||||
VideoIOPixelFormat inputPixelFormat = VideoIOPixelFormat::Uyvy8;
|
||||
unsigned historyCap = 0;
|
||||
double oscSmoothing = 0.0;
|
||||
};
|
||||
|
||||
struct RenderFrameState
|
||||
{
|
||||
bool hasInputSource = false;
|
||||
unsigned inputFrameWidth = 0;
|
||||
unsigned inputFrameHeight = 0;
|
||||
unsigned captureTextureWidth = 0;
|
||||
VideoIOPixelFormat inputPixelFormat = VideoIOPixelFormat::Uyvy8;
|
||||
unsigned historyCap = 0;
|
||||
std::vector<RuntimeRenderState> layerStates;
|
||||
};
|
||||
@@ -0,0 +1,119 @@
|
||||
#include "RenderFrameStateResolver.h"
|
||||
|
||||
#include <chrono>
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr auto kOscOverlayCommitDelay = std::chrono::milliseconds(150);
|
||||
}
|
||||
|
||||
RenderFrameStateResolver::RenderFrameStateResolver(RuntimeSnapshotProvider& runtimeSnapshotProvider) :
|
||||
mRuntimeSnapshotProvider(runtimeSnapshotProvider)
|
||||
{
|
||||
}
|
||||
|
||||
void RenderFrameStateResolver::StoreCommittedSnapshot(
|
||||
const RuntimeRenderStateSnapshot& snapshot,
|
||||
const std::vector<RuntimeRenderState>& committedLayerStates)
|
||||
{
|
||||
mCachedLayerRenderStates = committedLayerStates;
|
||||
mCachedRenderStateVersion = snapshot.versions.renderStateVersion;
|
||||
mCachedParameterStateVersion = snapshot.versions.parameterStateVersion;
|
||||
mCachedRenderStateWidth = snapshot.outputWidth;
|
||||
mCachedRenderStateHeight = snapshot.outputHeight;
|
||||
}
|
||||
|
||||
bool RenderFrameStateResolver::Resolve(
|
||||
const RenderFrameInput& input,
|
||||
const std::vector<RuntimeRenderState>& committedLayerStates,
|
||||
RuntimeLiveState& liveState,
|
||||
std::vector<RuntimeLiveOscCommitRequest>* commitRequests,
|
||||
RenderFrameState& frameState)
|
||||
{
|
||||
frameState.hasInputSource = input.hasInputSource;
|
||||
frameState.inputFrameWidth = input.inputFrameWidth;
|
||||
frameState.inputFrameHeight = input.inputFrameHeight;
|
||||
frameState.captureTextureWidth = input.captureTextureWidth;
|
||||
frameState.inputPixelFormat = input.inputPixelFormat;
|
||||
frameState.historyCap = input.historyCap;
|
||||
frameState.layerStates.clear();
|
||||
|
||||
if (input.useCommittedLayerStates)
|
||||
{
|
||||
frameState.layerStates = ComposeLayerStates(committedLayerStates, liveState, false, input.oscSmoothing, commitRequests);
|
||||
mRuntimeSnapshotProvider.RefreshDynamicRenderStateFields(frameState.layerStates);
|
||||
return true;
|
||||
}
|
||||
|
||||
const RuntimeSnapshotVersions versions = mRuntimeSnapshotProvider.GetVersions();
|
||||
const bool renderStateCacheValid =
|
||||
!mCachedLayerRenderStates.empty() &&
|
||||
mCachedRenderStateVersion == versions.renderStateVersion &&
|
||||
mCachedRenderStateWidth == input.renderWidth &&
|
||||
mCachedRenderStateHeight == input.renderHeight;
|
||||
|
||||
if (renderStateCacheValid)
|
||||
{
|
||||
RuntimeRenderStateSnapshot renderSnapshot;
|
||||
renderSnapshot.outputWidth = input.renderWidth;
|
||||
renderSnapshot.outputHeight = input.renderHeight;
|
||||
renderSnapshot.versions.renderStateVersion = mCachedRenderStateVersion;
|
||||
renderSnapshot.versions.parameterStateVersion = mCachedParameterStateVersion;
|
||||
renderSnapshot.states = mCachedLayerRenderStates;
|
||||
|
||||
renderSnapshot.states = ComposeLayerStates(renderSnapshot.states, liveState, true, input.oscSmoothing, commitRequests);
|
||||
if (mCachedParameterStateVersion != versions.parameterStateVersion &&
|
||||
mRuntimeSnapshotProvider.TryRefreshPublishedSnapshotParameters(renderSnapshot))
|
||||
{
|
||||
mCachedParameterStateVersion = renderSnapshot.versions.parameterStateVersion;
|
||||
renderSnapshot.states = ComposeLayerStates(renderSnapshot.states, liveState, true, input.oscSmoothing, commitRequests);
|
||||
}
|
||||
|
||||
mCachedLayerRenderStates = renderSnapshot.states;
|
||||
frameState.layerStates = renderSnapshot.states;
|
||||
mRuntimeSnapshotProvider.RefreshDynamicRenderStateFields(frameState.layerStates);
|
||||
return true;
|
||||
}
|
||||
|
||||
RuntimeRenderStateSnapshot renderSnapshot;
|
||||
if (mRuntimeSnapshotProvider.TryPublishRenderStateSnapshot(input.renderWidth, input.renderHeight, renderSnapshot))
|
||||
{
|
||||
mCachedLayerRenderStates = renderSnapshot.states;
|
||||
mCachedRenderStateVersion = renderSnapshot.versions.renderStateVersion;
|
||||
mCachedParameterStateVersion = renderSnapshot.versions.parameterStateVersion;
|
||||
mCachedRenderStateWidth = renderSnapshot.outputWidth;
|
||||
mCachedRenderStateHeight = renderSnapshot.outputHeight;
|
||||
mCachedLayerRenderStates = ComposeLayerStates(mCachedLayerRenderStates, liveState, true, input.oscSmoothing, commitRequests);
|
||||
frameState.layerStates = mCachedLayerRenderStates;
|
||||
return true;
|
||||
}
|
||||
|
||||
frameState.layerStates = ComposeLayerStates(mCachedLayerRenderStates, liveState, true, input.oscSmoothing, commitRequests);
|
||||
mRuntimeSnapshotProvider.RefreshDynamicRenderStateFields(frameState.layerStates);
|
||||
return !frameState.layerStates.empty();
|
||||
}
|
||||
|
||||
std::vector<RuntimeRenderState> RenderFrameStateResolver::ComposeLayerStates(
|
||||
const std::vector<RuntimeRenderState>& baseStates,
|
||||
RuntimeLiveState& liveState,
|
||||
bool allowCommit,
|
||||
double smoothing,
|
||||
std::vector<RuntimeLiveOscCommitRequest>* commitRequests) const
|
||||
{
|
||||
LayeredRenderStateInput input;
|
||||
input.committedLiveLayerStates = &baseStates;
|
||||
input.transientAutomationOverlay = &liveState;
|
||||
input.allowTransientAutomationCommits = allowCommit;
|
||||
input.collectTransientAutomationCommitRequests = commitRequests != nullptr;
|
||||
input.transientAutomationSmoothing = smoothing;
|
||||
input.transientAutomationCommitDelay = kOscOverlayCommitDelay;
|
||||
input.now = std::chrono::steady_clock::now();
|
||||
const RenderStateCompositionResult result = mRenderStateComposer.BuildFrameState(input);
|
||||
|
||||
if (commitRequests)
|
||||
{
|
||||
for (const RuntimeLiveOscCommitRequest& request : result.commitRequests)
|
||||
commitRequests->push_back(request);
|
||||
}
|
||||
return result.layerStates;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
#include "RenderFrameState.h"
|
||||
#include "RenderStateComposer.h"
|
||||
#include "RuntimeSnapshotProvider.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
class RenderFrameStateResolver
|
||||
{
|
||||
public:
|
||||
explicit RenderFrameStateResolver(RuntimeSnapshotProvider& runtimeSnapshotProvider);
|
||||
|
||||
void StoreCommittedSnapshot(
|
||||
const RuntimeRenderStateSnapshot& snapshot,
|
||||
const std::vector<RuntimeRenderState>& committedLayerStates);
|
||||
bool Resolve(
|
||||
const RenderFrameInput& input,
|
||||
const std::vector<RuntimeRenderState>& committedLayerStates,
|
||||
RuntimeLiveState& liveState,
|
||||
std::vector<RuntimeLiveOscCommitRequest>* commitRequests,
|
||||
RenderFrameState& frameState);
|
||||
|
||||
private:
|
||||
std::vector<RuntimeRenderState> ComposeLayerStates(
|
||||
const std::vector<RuntimeRenderState>& baseStates,
|
||||
RuntimeLiveState& liveState,
|
||||
bool allowCommit,
|
||||
double smoothing,
|
||||
std::vector<RuntimeLiveOscCommitRequest>* commitRequests) const;
|
||||
|
||||
RuntimeSnapshotProvider& mRuntimeSnapshotProvider;
|
||||
RenderStateComposer mRenderStateComposer;
|
||||
std::vector<RuntimeRenderState> mCachedLayerRenderStates;
|
||||
uint64_t mCachedRenderStateVersion = 0;
|
||||
uint64_t mCachedParameterStateVersion = 0;
|
||||
unsigned mCachedRenderStateWidth = 0;
|
||||
unsigned mCachedRenderStateHeight = 0;
|
||||
};
|
||||
@@ -0,0 +1,365 @@
|
||||
#include "RuntimeUpdateController.h"
|
||||
|
||||
#include "RenderEngine.h"
|
||||
#include "RuntimeEventDispatcher.h"
|
||||
#include "RuntimeServices.h"
|
||||
#include "RuntimeStore.h"
|
||||
#include "ShaderBuildQueue.h"
|
||||
#include "VideoBackend.h"
|
||||
|
||||
#include <variant>
|
||||
|
||||
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(
|
||||
RuntimeStore& runtimeStore,
|
||||
RuntimeCoordinator& runtimeCoordinator,
|
||||
RuntimeEventDispatcher& runtimeEventDispatcher,
|
||||
RuntimeServices& runtimeServices,
|
||||
RenderEngine& renderEngine,
|
||||
ShaderBuildQueue& shaderBuildQueue,
|
||||
VideoBackend& videoBackend) :
|
||||
mRuntimeStore(runtimeStore),
|
||||
mRuntimeCoordinator(runtimeCoordinator),
|
||||
mRuntimeEventDispatcher(runtimeEventDispatcher),
|
||||
mRuntimeServices(runtimeServices),
|
||||
mRenderEngine(renderEngine),
|
||||
mShaderBuildQueue(shaderBuildQueue),
|
||||
mVideoBackend(videoBackend)
|
||||
{
|
||||
mRuntimeEventDispatcher.Subscribe(
|
||||
RuntimeEventType::RuntimeStateBroadcastRequested,
|
||||
[this](const RuntimeEvent& event) { HandleRuntimeStateBroadcastRequested(event); });
|
||||
mRuntimeEventDispatcher.Subscribe(
|
||||
RuntimeEventType::RuntimeReloadRequested,
|
||||
[this](const RuntimeEvent& event) { HandleRuntimeReloadRequested(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)
|
||||
{
|
||||
if (!result.accepted)
|
||||
{
|
||||
if (error)
|
||||
*error = result.errorMessage;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (result.compileStatusChanged)
|
||||
{
|
||||
mRuntimeStore.SetCompileStatus(result.compileStatusSucceeded, result.compileStatusMessage);
|
||||
++mPendingCoordinatorCompileStatusEvents;
|
||||
}
|
||||
|
||||
if (result.clearReloadRequest)
|
||||
mRuntimeStore.ClearReloadRequest();
|
||||
|
||||
mRuntimeCoordinator.ApplyCommittedStateMode(result.committedStateMode);
|
||||
|
||||
switch (result.transientOscInvalidation)
|
||||
{
|
||||
case RuntimeCoordinatorTransientOscInvalidation::All:
|
||||
mRenderEngine.ClearOscOverlayState();
|
||||
mRuntimeServices.ClearOscState();
|
||||
break;
|
||||
case RuntimeCoordinatorTransientOscInvalidation::Layer:
|
||||
mRenderEngine.ClearOscOverlayStateForLayerKey(result.transientOscLayerKey);
|
||||
mRuntimeServices.ClearOscStateForLayerKey(result.transientOscLayerKey);
|
||||
break;
|
||||
case RuntimeCoordinatorTransientOscInvalidation::None:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
mRenderEngine.ApplyRuntimeCoordinatorRenderReset(result.renderResetScope);
|
||||
if (result.renderResetScope != RuntimeCoordinatorRenderResetScope::None)
|
||||
++mPendingCoordinatorRenderResetEvents;
|
||||
|
||||
if (result.shaderBuildRequested)
|
||||
{
|
||||
RequestShaderBuild();
|
||||
++mPendingCoordinatorShaderBuildEvents;
|
||||
}
|
||||
|
||||
if (result.runtimeStateBroadcastRequired)
|
||||
BroadcastRuntimeState();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RuntimeUpdateController::ProcessRuntimeWork()
|
||||
{
|
||||
DispatchRuntimeEvents();
|
||||
|
||||
return ConsumeReadyShaderBuild(0, true, true);
|
||||
}
|
||||
|
||||
void RuntimeUpdateController::RequestShaderBuild()
|
||||
{
|
||||
mShaderBuildQueue.RequestBuild(mVideoBackend.InputFrameWidth(), mVideoBackend.InputFrameHeight());
|
||||
}
|
||||
|
||||
void RuntimeUpdateController::BroadcastRuntimeState()
|
||||
{
|
||||
RuntimeStateBroadcastRequestedEvent event;
|
||||
event.reason = "runtime-state-changed";
|
||||
if (!mRuntimeEventDispatcher.PublishPayload(event, "RuntimeUpdateController"))
|
||||
{
|
||||
mRuntimeServices.BroadcastState();
|
||||
return;
|
||||
}
|
||||
|
||||
DispatchRuntimeEvents();
|
||||
}
|
||||
|
||||
void RuntimeUpdateController::HandleRuntimeStateBroadcastRequested(const RuntimeEvent& event)
|
||||
{
|
||||
if (event.source == "ControlServices")
|
||||
return;
|
||||
|
||||
mRuntimeServices.BroadcastState();
|
||||
}
|
||||
|
||||
void RuntimeUpdateController::HandleRuntimeReloadRequested(const RuntimeEvent& event)
|
||||
{
|
||||
const RuntimeReloadRequestedEvent* payload = std::get_if<RuntimeReloadRequestedEvent>(&event.payload);
|
||||
if (!payload)
|
||||
return;
|
||||
|
||||
mRuntimeStore.ClearReloadRequest();
|
||||
}
|
||||
|
||||
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);
|
||||
PublishRuntimeEventHealthObservations(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void RuntimeUpdateController::PublishRuntimeEventHealthObservations(const RuntimeEventDispatchResult& result)
|
||||
{
|
||||
const RuntimeEventQueueMetrics queueMetrics = mRuntimeEventDispatcher.GetQueueMetrics();
|
||||
if (queueMetrics.depth != mLastReportedRuntimeEventQueueDepth ||
|
||||
queueMetrics.droppedCount != mLastReportedRuntimeEventDroppedCount ||
|
||||
queueMetrics.coalescedCount != mLastReportedRuntimeEventCoalescedCount)
|
||||
{
|
||||
QueueDepthChangedEvent queueDepth;
|
||||
queueDepth.queueName = "runtime-events";
|
||||
queueDepth.depth = queueMetrics.depth;
|
||||
queueDepth.capacity = queueMetrics.capacity;
|
||||
queueDepth.droppedCount = queueMetrics.droppedCount;
|
||||
queueDepth.coalescedCount = queueMetrics.coalescedCount;
|
||||
mRuntimeEventDispatcher.PublishPayload(queueDepth, "HealthTelemetry");
|
||||
mLastReportedRuntimeEventQueueDepth = queueMetrics.depth;
|
||||
mLastReportedRuntimeEventDroppedCount = queueMetrics.droppedCount;
|
||||
mLastReportedRuntimeEventCoalescedCount = queueMetrics.coalescedCount;
|
||||
}
|
||||
|
||||
if (result.handlerInvocations == 0 && result.handlerFailures == 0)
|
||||
return;
|
||||
|
||||
TimingSampleRecordedEvent timing;
|
||||
timing.subsystem = "RuntimeEventDispatcher";
|
||||
timing.metric = "dispatchDuration";
|
||||
timing.value = result.dispatchDurationMilliseconds;
|
||||
timing.unit = "ms";
|
||||
mRuntimeEventDispatcher.PublishPayload(timing, "HealthTelemetry");
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
#pragma once
|
||||
|
||||
#include "RuntimeCoordinator.h"
|
||||
#include "RuntimeEventPayloads.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
class RenderEngine;
|
||||
struct RuntimeEvent;
|
||||
struct RuntimeEventDispatchResult;
|
||||
class RuntimeEventDispatcher;
|
||||
class RuntimeServices;
|
||||
class RuntimeStore;
|
||||
class ShaderBuildQueue;
|
||||
class VideoBackend;
|
||||
|
||||
class RuntimeUpdateController
|
||||
{
|
||||
public:
|
||||
RuntimeUpdateController(
|
||||
RuntimeStore& runtimeStore,
|
||||
RuntimeCoordinator& runtimeCoordinator,
|
||||
RuntimeEventDispatcher& runtimeEventDispatcher,
|
||||
RuntimeServices& runtimeServices,
|
||||
RenderEngine& renderEngine,
|
||||
ShaderBuildQueue& shaderBuildQueue,
|
||||
VideoBackend& videoBackend);
|
||||
|
||||
bool ApplyRuntimeCoordinatorResult(const RuntimeCoordinatorResult& result, std::string* error = nullptr);
|
||||
bool ProcessRuntimeWork();
|
||||
void RequestShaderBuild();
|
||||
void BroadcastRuntimeState();
|
||||
|
||||
private:
|
||||
void HandleRuntimeStateBroadcastRequested(const RuntimeEvent& event);
|
||||
void HandleRuntimeReloadRequested(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);
|
||||
void PublishRuntimeEventHealthObservations(const RuntimeEventDispatchResult& result);
|
||||
|
||||
RuntimeStore& mRuntimeStore;
|
||||
RuntimeCoordinator& mRuntimeCoordinator;
|
||||
RuntimeEventDispatcher& mRuntimeEventDispatcher;
|
||||
RuntimeServices& mRuntimeServices;
|
||||
RenderEngine& mRenderEngine;
|
||||
ShaderBuildQueue& mShaderBuildQueue;
|
||||
VideoBackend& mVideoBackend;
|
||||
std::size_t mPendingCoordinatorShaderBuildEvents = 0;
|
||||
std::size_t mPendingCoordinatorCompileStatusEvents = 0;
|
||||
std::size_t mPendingCoordinatorRenderResetEvents = 0;
|
||||
std::size_t mLastReportedRuntimeEventQueueDepth = static_cast<std::size_t>(-1);
|
||||
std::size_t mLastReportedRuntimeEventDroppedCount = static_cast<std::size_t>(-1);
|
||||
std::size_t mLastReportedRuntimeEventCoalescedCount = static_cast<std::size_t>(-1);
|
||||
};
|
||||
Reference in New Issue
Block a user