re organisation
This commit is contained in:
@@ -0,0 +1,208 @@
|
||||
#include "RenderSnapshotBuilder.h"
|
||||
|
||||
#include "RuntimeClock.h"
|
||||
#include "RuntimeParameterUtils.h"
|
||||
#include "RuntimeStore.h"
|
||||
#include "ShaderCompiler.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <filesystem>
|
||||
#include <mutex>
|
||||
#include <utility>
|
||||
|
||||
RenderSnapshotBuilder::RenderSnapshotBuilder(RuntimeStore& runtimeStore) :
|
||||
mRuntimeStore(runtimeStore)
|
||||
{
|
||||
}
|
||||
|
||||
bool RenderSnapshotBuilder::BuildLayerPassFragmentShaderSources(const std::string& layerId, std::vector<ShaderPassBuildSource>& passSources, std::string& error) const
|
||||
{
|
||||
try
|
||||
{
|
||||
ShaderPackage shaderPackage;
|
||||
if (!mRuntimeStore.CopyShaderPackageForStoredLayer(layerId, shaderPackage, error))
|
||||
return false;
|
||||
|
||||
std::filesystem::path repoRoot;
|
||||
std::filesystem::path wrapperPath;
|
||||
std::filesystem::path generatedGlslPath;
|
||||
std::filesystem::path patchedGlslPath;
|
||||
unsigned maxTemporalHistoryFrames = 0;
|
||||
mRuntimeStore.GetShaderCompilerInputs(repoRoot, wrapperPath, generatedGlslPath, patchedGlslPath, maxTemporalHistoryFrames);
|
||||
|
||||
ShaderCompiler compiler(
|
||||
repoRoot,
|
||||
wrapperPath,
|
||||
generatedGlslPath,
|
||||
patchedGlslPath,
|
||||
maxTemporalHistoryFrames);
|
||||
passSources.clear();
|
||||
passSources.reserve(shaderPackage.passes.size());
|
||||
for (const ShaderPassDefinition& pass : shaderPackage.passes)
|
||||
{
|
||||
ShaderPassBuildSource passSource;
|
||||
passSource.passId = pass.id;
|
||||
passSource.inputNames = pass.inputNames;
|
||||
passSource.outputName = pass.outputName;
|
||||
if (!compiler.BuildPassFragmentShaderSource(shaderPackage, pass, passSource.fragmentShaderSource, error))
|
||||
return false;
|
||||
passSources.push_back(std::move(passSource));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (const std::exception& exception)
|
||||
{
|
||||
error = std::string("RenderSnapshotBuilder::BuildLayerPassFragmentShaderSources exception: ") + exception.what();
|
||||
return false;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
error = "RenderSnapshotBuilder::BuildLayerPassFragmentShaderSources threw a non-standard exception.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned RenderSnapshotBuilder::GetMaxTemporalHistoryFrames() const
|
||||
{
|
||||
return mRuntimeStore.GetConfiguredMaxTemporalHistoryFrames();
|
||||
}
|
||||
|
||||
RuntimeSnapshotVersions RenderSnapshotBuilder::GetVersions() const
|
||||
{
|
||||
RuntimeSnapshotVersions versions;
|
||||
versions.renderStateVersion = mRenderStateVersion.load(std::memory_order_relaxed);
|
||||
versions.parameterStateVersion = mParameterStateVersion.load(std::memory_order_relaxed);
|
||||
return versions;
|
||||
}
|
||||
|
||||
void RenderSnapshotBuilder::AdvanceFrame()
|
||||
{
|
||||
++mFrameCounter;
|
||||
}
|
||||
|
||||
void RenderSnapshotBuilder::BuildLayerRenderStates(unsigned outputWidth, unsigned outputHeight, std::vector<RuntimeRenderState>& states) const
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mRuntimeStore.mMutex);
|
||||
BuildLayerRenderStatesLocked(outputWidth, outputHeight, states);
|
||||
}
|
||||
|
||||
bool RenderSnapshotBuilder::TryBuildLayerRenderStates(unsigned outputWidth, unsigned outputHeight, std::vector<RuntimeRenderState>& states) const
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mRuntimeStore.mMutex, std::try_to_lock);
|
||||
if (!lock.owns_lock())
|
||||
return false;
|
||||
|
||||
BuildLayerRenderStatesLocked(outputWidth, outputHeight, states);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RenderSnapshotBuilder::TryRefreshLayerParameters(std::vector<RuntimeRenderState>& states) const
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mRuntimeStore.mMutex, std::try_to_lock);
|
||||
if (!lock.owns_lock())
|
||||
return false;
|
||||
|
||||
RefreshLayerParametersLocked(states);
|
||||
return true;
|
||||
}
|
||||
|
||||
void RenderSnapshotBuilder::RefreshDynamicRenderStateFields(std::vector<RuntimeRenderState>& states) const
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mRuntimeStore.mMutex);
|
||||
RefreshDynamicRenderStateFieldsLocked(states);
|
||||
}
|
||||
|
||||
void RenderSnapshotBuilder::MarkRenderStateDirty()
|
||||
{
|
||||
mRenderStateVersion.fetch_add(1, std::memory_order_relaxed);
|
||||
mParameterStateVersion.fetch_add(1, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
void RenderSnapshotBuilder::MarkParameterStateDirty()
|
||||
{
|
||||
mParameterStateVersion.fetch_add(1, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
void RenderSnapshotBuilder::BuildLayerRenderStatesLocked(unsigned outputWidth, unsigned outputHeight, std::vector<RuntimeRenderState>& states) const
|
||||
{
|
||||
states.clear();
|
||||
const HealthTelemetry::SignalStatusSnapshot signalStatus = mRuntimeStore.mHealthTelemetry.GetSignalStatusSnapshot();
|
||||
|
||||
for (const RuntimeStore::LayerPersistentState& layer : mRuntimeStore.mLayerStack.Layers())
|
||||
{
|
||||
const ShaderPackage* shaderPackage = mRuntimeStore.mShaderCatalog.FindPackage(layer.shaderId);
|
||||
if (!shaderPackage)
|
||||
continue;
|
||||
|
||||
RuntimeRenderState state;
|
||||
state.layerId = layer.id;
|
||||
state.shaderId = layer.shaderId;
|
||||
state.shaderName = shaderPackage->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 = shaderPackage->parameters;
|
||||
state.textureAssets = shaderPackage->textureAssets;
|
||||
state.fontAssets = shaderPackage->fontAssets;
|
||||
state.isTemporal = shaderPackage->temporal.enabled;
|
||||
state.temporalHistorySource = shaderPackage->temporal.historySource;
|
||||
state.requestedTemporalHistoryLength = shaderPackage->temporal.requestedHistoryLength;
|
||||
state.effectiveTemporalHistoryLength = shaderPackage->temporal.effectiveHistoryLength;
|
||||
state.feedback = shaderPackage->feedback;
|
||||
|
||||
for (const ShaderParameterDefinition& definition : shaderPackage->parameters)
|
||||
{
|
||||
ShaderParameterValue value = 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 RenderSnapshotBuilder::RefreshLayerParametersLocked(std::vector<RuntimeRenderState>& states) const
|
||||
{
|
||||
for (RuntimeRenderState& state : states)
|
||||
{
|
||||
const auto layerIt = std::find_if(mRuntimeStore.mLayerStack.Layers().begin(), mRuntimeStore.mLayerStack.Layers().end(),
|
||||
[&state](const RuntimeStore::LayerPersistentState& layer) { return layer.id == state.layerId; });
|
||||
if (layerIt == mRuntimeStore.mLayerStack.Layers().end())
|
||||
continue;
|
||||
|
||||
state.bypass = layerIt->bypass ? 1.0 : 0.0;
|
||||
state.parameterValues.clear();
|
||||
for (const ShaderParameterDefinition& definition : state.parameterDefinitions)
|
||||
{
|
||||
ShaderParameterValue value = DefaultValueForDefinition(definition);
|
||||
auto valueIt = layerIt->parameterValues.find(definition.id);
|
||||
if (valueIt != layerIt->parameterValues.end())
|
||||
value = valueIt->second;
|
||||
state.parameterValues[definition.id] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RenderSnapshotBuilder::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() - mRuntimeStore.mStartTime).count();
|
||||
const double frameCount = static_cast<double>(mFrameCounter.load(std::memory_order_relaxed));
|
||||
|
||||
for (RuntimeRenderState& state : states)
|
||||
{
|
||||
state.timeSeconds = timeSeconds;
|
||||
state.utcTimeSeconds = clock.utcTimeSeconds;
|
||||
state.utcOffsetSeconds = clock.utcOffsetSeconds;
|
||||
state.startupRandom = mRuntimeStore.mStartupRandom;
|
||||
state.frameCount = frameCount;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
#include "ShaderTypes.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class RuntimeStore;
|
||||
|
||||
struct RuntimeSnapshotVersions
|
||||
{
|
||||
uint64_t renderStateVersion = 0;
|
||||
uint64_t parameterStateVersion = 0;
|
||||
};
|
||||
|
||||
class RenderSnapshotBuilder
|
||||
{
|
||||
public:
|
||||
explicit RenderSnapshotBuilder(RuntimeStore& runtimeStore);
|
||||
|
||||
bool BuildLayerPassFragmentShaderSources(const std::string& layerId, std::vector<ShaderPassBuildSource>& passSources, std::string& error) const;
|
||||
unsigned GetMaxTemporalHistoryFrames() const;
|
||||
RuntimeSnapshotVersions GetVersions() const;
|
||||
void AdvanceFrame();
|
||||
void BuildLayerRenderStates(unsigned outputWidth, unsigned outputHeight, std::vector<RuntimeRenderState>& states) const;
|
||||
bool TryBuildLayerRenderStates(unsigned outputWidth, unsigned outputHeight, std::vector<RuntimeRenderState>& states) const;
|
||||
bool TryRefreshLayerParameters(std::vector<RuntimeRenderState>& states) const;
|
||||
void RefreshDynamicRenderStateFields(std::vector<RuntimeRenderState>& states) const;
|
||||
void MarkRenderStateDirty();
|
||||
void MarkParameterStateDirty();
|
||||
|
||||
private:
|
||||
void BuildLayerRenderStatesLocked(unsigned outputWidth, unsigned outputHeight, std::vector<RuntimeRenderState>& states) const;
|
||||
void RefreshLayerParametersLocked(std::vector<RuntimeRenderState>& states) const;
|
||||
void RefreshDynamicRenderStateFieldsLocked(std::vector<RuntimeRenderState>& states) const;
|
||||
|
||||
RuntimeStore& mRuntimeStore;
|
||||
std::atomic<uint64_t> mFrameCounter{ 0 };
|
||||
std::atomic<uint64_t> mRenderStateVersion{ 0 };
|
||||
std::atomic<uint64_t> mParameterStateVersion{ 0 };
|
||||
};
|
||||
@@ -0,0 +1,141 @@
|
||||
#include "RuntimeSnapshotProvider.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
RuntimeSnapshotProvider::RuntimeSnapshotProvider(RenderSnapshotBuilder& renderSnapshotBuilder) :
|
||||
mRenderSnapshotBuilder(renderSnapshotBuilder)
|
||||
{
|
||||
}
|
||||
|
||||
bool RuntimeSnapshotProvider::BuildLayerPassFragmentShaderSources(const std::string& layerId, std::vector<ShaderPassBuildSource>& passSources, std::string& error) const
|
||||
{
|
||||
try
|
||||
{
|
||||
return mRenderSnapshotBuilder.BuildLayerPassFragmentShaderSources(layerId, passSources, error);
|
||||
}
|
||||
catch (const std::exception& exception)
|
||||
{
|
||||
error = std::string("RuntimeSnapshotProvider::BuildLayerPassFragmentShaderSources exception: ") + exception.what();
|
||||
return false;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
error = "RuntimeSnapshotProvider::BuildLayerPassFragmentShaderSources threw a non-standard exception.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned RuntimeSnapshotProvider::GetMaxTemporalHistoryFrames() const
|
||||
{
|
||||
return mRenderSnapshotBuilder.GetMaxTemporalHistoryFrames();
|
||||
}
|
||||
|
||||
RuntimeSnapshotVersions RuntimeSnapshotProvider::GetVersions() const
|
||||
{
|
||||
return mRenderSnapshotBuilder.GetVersions();
|
||||
}
|
||||
|
||||
void RuntimeSnapshotProvider::AdvanceFrame()
|
||||
{
|
||||
mRenderSnapshotBuilder.AdvanceFrame();
|
||||
}
|
||||
|
||||
RuntimeRenderStateSnapshot RuntimeSnapshotProvider::PublishRenderStateSnapshot(unsigned outputWidth, unsigned outputHeight) const
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
const RuntimeSnapshotVersions versionsBefore = GetVersions();
|
||||
RuntimeRenderStateSnapshot publishedSnapshot;
|
||||
if (TryGetPublishedRenderStateSnapshot(outputWidth, outputHeight, versionsBefore, publishedSnapshot))
|
||||
return publishedSnapshot;
|
||||
|
||||
RuntimeRenderStateSnapshot snapshot;
|
||||
snapshot.outputWidth = outputWidth;
|
||||
snapshot.outputHeight = outputHeight;
|
||||
mRenderSnapshotBuilder.BuildLayerRenderStates(outputWidth, outputHeight, snapshot.states);
|
||||
|
||||
const RuntimeSnapshotVersions versionsAfter = GetVersions();
|
||||
if (versionsBefore.renderStateVersion == versionsAfter.renderStateVersion &&
|
||||
versionsBefore.parameterStateVersion == versionsAfter.parameterStateVersion)
|
||||
{
|
||||
snapshot.versions = versionsAfter;
|
||||
StorePublishedRenderStateSnapshot(snapshot);
|
||||
return snapshot;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool RuntimeSnapshotProvider::TryPublishRenderStateSnapshot(unsigned outputWidth, unsigned outputHeight, RuntimeRenderStateSnapshot& snapshot) const
|
||||
{
|
||||
const RuntimeSnapshotVersions versionsBefore = GetVersions();
|
||||
if (TryGetPublishedRenderStateSnapshot(outputWidth, outputHeight, versionsBefore, snapshot))
|
||||
return true;
|
||||
|
||||
std::vector<RuntimeRenderState> states;
|
||||
if (!mRenderSnapshotBuilder.TryBuildLayerRenderStates(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);
|
||||
StorePublishedRenderStateSnapshot(snapshot);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RuntimeSnapshotProvider::TryRefreshPublishedSnapshotParameters(RuntimeRenderStateSnapshot& snapshot) const
|
||||
{
|
||||
const uint64_t expectedRenderStateVersion = snapshot.versions.renderStateVersion;
|
||||
if (!mRenderSnapshotBuilder.TryRefreshLayerParameters(snapshot.states))
|
||||
return false;
|
||||
|
||||
const RuntimeSnapshotVersions versions = GetVersions();
|
||||
if (versions.renderStateVersion != expectedRenderStateVersion)
|
||||
return false;
|
||||
|
||||
snapshot.versions = versions;
|
||||
StorePublishedRenderStateSnapshot(snapshot);
|
||||
return true;
|
||||
}
|
||||
|
||||
void RuntimeSnapshotProvider::RefreshDynamicRenderStateFields(std::vector<RuntimeRenderState>& states) const
|
||||
{
|
||||
mRenderSnapshotBuilder.RefreshDynamicRenderStateFields(states);
|
||||
}
|
||||
|
||||
bool RuntimeSnapshotProvider::TryGetPublishedRenderStateSnapshot(unsigned outputWidth, unsigned outputHeight,
|
||||
const RuntimeSnapshotVersions& versions, RuntimeRenderStateSnapshot& snapshot) const
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mPublishedSnapshotMutex);
|
||||
if (!mHasPublishedRenderStateSnapshot ||
|
||||
!SnapshotMatches(mPublishedRenderStateSnapshot, outputWidth, outputHeight, versions))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
snapshot = mPublishedRenderStateSnapshot;
|
||||
return true;
|
||||
}
|
||||
|
||||
void RuntimeSnapshotProvider::StorePublishedRenderStateSnapshot(const RuntimeRenderStateSnapshot& snapshot) const
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mPublishedSnapshotMutex);
|
||||
mPublishedRenderStateSnapshot = snapshot;
|
||||
mHasPublishedRenderStateSnapshot = true;
|
||||
}
|
||||
|
||||
bool RuntimeSnapshotProvider::SnapshotMatches(const RuntimeRenderStateSnapshot& snapshot, unsigned outputWidth, unsigned outputHeight,
|
||||
const RuntimeSnapshotVersions& versions)
|
||||
{
|
||||
return snapshot.outputWidth == outputWidth &&
|
||||
snapshot.outputHeight == outputHeight &&
|
||||
snapshot.versions.renderStateVersion == versions.renderStateVersion &&
|
||||
snapshot.versions.parameterStateVersion == versions.parameterStateVersion;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
#include "RenderSnapshotBuilder.h"
|
||||
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct RuntimeRenderStateSnapshot
|
||||
{
|
||||
RuntimeSnapshotVersions versions;
|
||||
unsigned outputWidth = 0;
|
||||
unsigned outputHeight = 0;
|
||||
std::vector<RuntimeRenderState> states;
|
||||
};
|
||||
|
||||
class RuntimeSnapshotProvider
|
||||
{
|
||||
public:
|
||||
explicit RuntimeSnapshotProvider(RenderSnapshotBuilder& renderSnapshotBuilder);
|
||||
|
||||
bool BuildLayerPassFragmentShaderSources(const std::string& layerId, std::vector<ShaderPassBuildSource>& passSources, std::string& error) const;
|
||||
unsigned GetMaxTemporalHistoryFrames() const;
|
||||
RuntimeSnapshotVersions GetVersions() const;
|
||||
void AdvanceFrame();
|
||||
RuntimeRenderStateSnapshot PublishRenderStateSnapshot(unsigned outputWidth, unsigned outputHeight) const;
|
||||
bool TryPublishRenderStateSnapshot(unsigned outputWidth, unsigned outputHeight, RuntimeRenderStateSnapshot& snapshot) const;
|
||||
bool TryRefreshPublishedSnapshotParameters(RuntimeRenderStateSnapshot& snapshot) const;
|
||||
void RefreshDynamicRenderStateFields(std::vector<RuntimeRenderState>& states) const;
|
||||
|
||||
private:
|
||||
bool TryGetPublishedRenderStateSnapshot(unsigned outputWidth, unsigned outputHeight,
|
||||
const RuntimeSnapshotVersions& versions, RuntimeRenderStateSnapshot& snapshot) const;
|
||||
void StorePublishedRenderStateSnapshot(const RuntimeRenderStateSnapshot& snapshot) const;
|
||||
static bool SnapshotMatches(const RuntimeRenderStateSnapshot& snapshot, unsigned outputWidth, unsigned outputHeight,
|
||||
const RuntimeSnapshotVersions& versions);
|
||||
|
||||
RenderSnapshotBuilder& mRenderSnapshotBuilder;
|
||||
mutable std::mutex mPublishedSnapshotMutex;
|
||||
mutable bool mHasPublishedRenderStateSnapshot = false;
|
||||
mutable RuntimeRenderStateSnapshot mPublishedRenderStateSnapshot;
|
||||
};
|
||||
Reference in New Issue
Block a user