257 lines
8.8 KiB
C++
257 lines
8.8 KiB
C++
#include "RuntimeSnapshotProvider.h"
|
|
|
|
#include "RuntimeClock.h"
|
|
|
|
#include <algorithm>
|
|
#include <mutex>
|
|
#include <utility>
|
|
|
|
RuntimeSnapshotProvider::RuntimeSnapshotProvider(RuntimeHost& runtimeHost) :
|
|
mRuntimeHost(runtimeHost)
|
|
{
|
|
}
|
|
|
|
bool RuntimeSnapshotProvider::BuildLayerPassFragmentShaderSources(const std::string& layerId, std::vector<ShaderPassBuildSource>& passSources, std::string& error) const
|
|
{
|
|
return mRuntimeHost.BuildLayerPassFragmentShaderSources(layerId, passSources, error);
|
|
}
|
|
|
|
unsigned RuntimeSnapshotProvider::GetMaxTemporalHistoryFrames() const
|
|
{
|
|
return mRuntimeHost.GetMaxTemporalHistoryFrames();
|
|
}
|
|
|
|
RuntimeSnapshotVersions RuntimeSnapshotProvider::GetVersions() const
|
|
{
|
|
RuntimeSnapshotVersions versions;
|
|
versions.renderStateVersion = mRuntimeHost.GetRenderStateVersion();
|
|
versions.parameterStateVersion = mRuntimeHost.GetParameterStateVersion();
|
|
return versions;
|
|
}
|
|
|
|
RuntimeRenderFrameContext RuntimeSnapshotProvider::GetFrameContext() const
|
|
{
|
|
std::vector<RuntimeRenderState> stateScratch(1);
|
|
RefreshDynamicRenderStateFields(stateScratch);
|
|
|
|
RuntimeRenderFrameContext frameContext;
|
|
const RuntimeRenderState& state = stateScratch.front();
|
|
frameContext.timeSeconds = state.timeSeconds;
|
|
frameContext.utcTimeSeconds = state.utcTimeSeconds;
|
|
frameContext.utcOffsetSeconds = state.utcOffsetSeconds;
|
|
frameContext.startupRandom = state.startupRandom;
|
|
frameContext.frameCount = state.frameCount;
|
|
return frameContext;
|
|
}
|
|
|
|
void RuntimeSnapshotProvider::AdvanceFrame()
|
|
{
|
|
mRuntimeHost.AdvanceFrame();
|
|
}
|
|
|
|
bool RuntimeSnapshotProvider::TryAdvanceFrame()
|
|
{
|
|
return mRuntimeHost.TryAdvanceFrame();
|
|
}
|
|
|
|
RuntimeRenderStateSnapshot RuntimeSnapshotProvider::GetRenderStateSnapshot(unsigned outputWidth, unsigned outputHeight) const
|
|
{
|
|
for (;;)
|
|
{
|
|
const RuntimeSnapshotVersions versionsBefore = GetVersions();
|
|
|
|
RuntimeRenderStateSnapshot snapshot;
|
|
snapshot.outputWidth = outputWidth;
|
|
snapshot.outputHeight = outputHeight;
|
|
snapshot.states = GetLayerRenderStates(outputWidth, outputHeight);
|
|
|
|
const RuntimeSnapshotVersions versionsAfter = GetVersions();
|
|
if (versionsBefore.renderStateVersion == versionsAfter.renderStateVersion &&
|
|
versionsBefore.parameterStateVersion == versionsAfter.parameterStateVersion)
|
|
{
|
|
snapshot.versions = versionsAfter;
|
|
return snapshot;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool RuntimeSnapshotProvider::TryGetRenderStateSnapshot(unsigned outputWidth, unsigned outputHeight, RuntimeRenderStateSnapshot& snapshot) const
|
|
{
|
|
const RuntimeSnapshotVersions versionsBefore = GetVersions();
|
|
|
|
std::vector<RuntimeRenderState> states;
|
|
if (!TryGetLayerRenderStates(outputWidth, outputHeight, states))
|
|
return false;
|
|
|
|
const RuntimeSnapshotVersions versionsAfter = GetVersions();
|
|
if (versionsBefore.renderStateVersion != versionsAfter.renderStateVersion ||
|
|
versionsBefore.parameterStateVersion != versionsAfter.parameterStateVersion)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
snapshot.outputWidth = outputWidth;
|
|
snapshot.outputHeight = outputHeight;
|
|
snapshot.versions = versionsAfter;
|
|
snapshot.states = std::move(states);
|
|
return true;
|
|
}
|
|
|
|
bool RuntimeSnapshotProvider::TryRefreshSnapshotParameters(RuntimeRenderStateSnapshot& snapshot) const
|
|
{
|
|
const uint64_t expectedRenderStateVersion = snapshot.versions.renderStateVersion;
|
|
if (!TryRefreshCachedLayerStates(snapshot.states))
|
|
return false;
|
|
|
|
const RuntimeSnapshotVersions versions = GetVersions();
|
|
if (versions.renderStateVersion != expectedRenderStateVersion)
|
|
return false;
|
|
|
|
snapshot.versions = versions;
|
|
return true;
|
|
}
|
|
|
|
void RuntimeSnapshotProvider::ApplyFrameContext(std::vector<RuntimeRenderState>& states, const RuntimeRenderFrameContext& frameContext) const
|
|
{
|
|
for (RuntimeRenderState& state : states)
|
|
{
|
|
state.timeSeconds = frameContext.timeSeconds;
|
|
state.utcTimeSeconds = frameContext.utcTimeSeconds;
|
|
state.utcOffsetSeconds = frameContext.utcOffsetSeconds;
|
|
state.startupRandom = frameContext.startupRandom;
|
|
state.frameCount = frameContext.frameCount;
|
|
}
|
|
}
|
|
|
|
void RuntimeSnapshotProvider::ApplyFrameContext(RuntimeRenderStateSnapshot& snapshot, const RuntimeRenderFrameContext& frameContext) const
|
|
{
|
|
ApplyFrameContext(snapshot.states, frameContext);
|
|
}
|
|
|
|
std::vector<RuntimeRenderState> RuntimeSnapshotProvider::GetLayerRenderStates(unsigned outputWidth, unsigned outputHeight) const
|
|
{
|
|
std::lock_guard<std::mutex> lock(mRuntimeHost.mMutex);
|
|
std::vector<RuntimeRenderState> states;
|
|
BuildLayerRenderStatesLocked(outputWidth, outputHeight, states);
|
|
return states;
|
|
}
|
|
|
|
bool RuntimeSnapshotProvider::TryGetLayerRenderStates(unsigned outputWidth, unsigned outputHeight, std::vector<RuntimeRenderState>& states) const
|
|
{
|
|
std::unique_lock<std::mutex> lock(mRuntimeHost.mMutex, std::try_to_lock);
|
|
if (!lock.owns_lock())
|
|
return false;
|
|
|
|
states.clear();
|
|
BuildLayerRenderStatesLocked(outputWidth, outputHeight, states);
|
|
return true;
|
|
}
|
|
|
|
bool RuntimeSnapshotProvider::TryRefreshCachedLayerStates(std::vector<RuntimeRenderState>& states) const
|
|
{
|
|
std::unique_lock<std::mutex> lock(mRuntimeHost.mMutex, std::try_to_lock);
|
|
if (!lock.owns_lock())
|
|
return false;
|
|
|
|
RefreshCachedLayerStatesLocked(states);
|
|
return true;
|
|
}
|
|
|
|
void RuntimeSnapshotProvider::RefreshDynamicRenderStateFields(std::vector<RuntimeRenderState>& states) const
|
|
{
|
|
std::lock_guard<std::mutex> lock(mRuntimeHost.mMutex);
|
|
RefreshDynamicRenderStateFieldsLocked(states);
|
|
}
|
|
|
|
uint64_t RuntimeSnapshotProvider::GetRenderStateVersion() const
|
|
{
|
|
return GetVersions().renderStateVersion;
|
|
}
|
|
|
|
uint64_t RuntimeSnapshotProvider::GetParameterStateVersion() const
|
|
{
|
|
return GetVersions().parameterStateVersion;
|
|
}
|
|
|
|
void RuntimeSnapshotProvider::BuildLayerRenderStatesLocked(unsigned outputWidth, unsigned outputHeight, std::vector<RuntimeRenderState>& states) const
|
|
{
|
|
const HealthTelemetry::SignalStatusSnapshot signalStatus = mRuntimeHost.mHealthTelemetry.GetSignalStatusSnapshot();
|
|
|
|
for (const RuntimeHost::LayerPersistentState& layer : mRuntimeHost.mPersistentState.layers)
|
|
{
|
|
auto shaderIt = mRuntimeHost.mPackagesById.find(layer.shaderId);
|
|
if (shaderIt == mRuntimeHost.mPackagesById.end())
|
|
continue;
|
|
|
|
RuntimeRenderState state;
|
|
state.layerId = layer.id;
|
|
state.shaderId = layer.shaderId;
|
|
state.shaderName = shaderIt->second.displayName;
|
|
state.mixAmount = 1.0;
|
|
state.bypass = layer.bypass ? 1.0 : 0.0;
|
|
state.inputWidth = signalStatus.width;
|
|
state.inputHeight = signalStatus.height;
|
|
state.outputWidth = outputWidth;
|
|
state.outputHeight = outputHeight;
|
|
state.parameterDefinitions = shaderIt->second.parameters;
|
|
state.textureAssets = shaderIt->second.textureAssets;
|
|
state.fontAssets = shaderIt->second.fontAssets;
|
|
state.isTemporal = shaderIt->second.temporal.enabled;
|
|
state.temporalHistorySource = shaderIt->second.temporal.historySource;
|
|
state.requestedTemporalHistoryLength = shaderIt->second.temporal.requestedHistoryLength;
|
|
state.effectiveTemporalHistoryLength = shaderIt->second.temporal.effectiveHistoryLength;
|
|
state.feedback = shaderIt->second.feedback;
|
|
|
|
for (const ShaderParameterDefinition& definition : shaderIt->second.parameters)
|
|
{
|
|
ShaderParameterValue value = mRuntimeHost.DefaultValueForDefinition(definition);
|
|
auto valueIt = layer.parameterValues.find(definition.id);
|
|
if (valueIt != layer.parameterValues.end())
|
|
value = valueIt->second;
|
|
state.parameterValues[definition.id] = value;
|
|
}
|
|
|
|
states.push_back(state);
|
|
}
|
|
|
|
RefreshDynamicRenderStateFieldsLocked(states);
|
|
}
|
|
|
|
void RuntimeSnapshotProvider::RefreshCachedLayerStatesLocked(std::vector<RuntimeRenderState>& states) const
|
|
{
|
|
for (RuntimeRenderState& state : states)
|
|
{
|
|
const auto layerIt = std::find_if(mRuntimeHost.mPersistentState.layers.begin(), mRuntimeHost.mPersistentState.layers.end(),
|
|
[&state](const RuntimeHost::LayerPersistentState& layer) { return layer.id == state.layerId; });
|
|
if (layerIt == mRuntimeHost.mPersistentState.layers.end())
|
|
continue;
|
|
|
|
state.bypass = layerIt->bypass ? 1.0 : 0.0;
|
|
state.parameterValues.clear();
|
|
for (const ShaderParameterDefinition& definition : state.parameterDefinitions)
|
|
{
|
|
ShaderParameterValue value = mRuntimeHost.DefaultValueForDefinition(definition);
|
|
auto valueIt = layerIt->parameterValues.find(definition.id);
|
|
if (valueIt != layerIt->parameterValues.end())
|
|
value = valueIt->second;
|
|
state.parameterValues[definition.id] = value;
|
|
}
|
|
}
|
|
}
|
|
|
|
void RuntimeSnapshotProvider::RefreshDynamicRenderStateFieldsLocked(std::vector<RuntimeRenderState>& states) const
|
|
{
|
|
const RuntimeClockSnapshot clock = GetRuntimeClockSnapshot();
|
|
const double timeSeconds = std::chrono::duration_cast<std::chrono::duration<double>>(std::chrono::steady_clock::now() - mRuntimeHost.mStartTime).count();
|
|
const double frameCount = static_cast<double>(mRuntimeHost.mFrameCounter.load(std::memory_order_relaxed));
|
|
|
|
for (RuntimeRenderState& state : states)
|
|
{
|
|
state.timeSeconds = timeSeconds;
|
|
state.utcTimeSeconds = clock.utcTimeSeconds;
|
|
state.utcOffsetSeconds = clock.utcOffsetSeconds;
|
|
state.startupRandom = mRuntimeHost.mStartupRandom;
|
|
state.frameCount = frameCount;
|
|
}
|
|
}
|