194 lines
6.7 KiB
C++
194 lines
6.7 KiB
C++
#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;
|
|
|
|
const ShaderCompilerInputs inputs = mRuntimeStore.GetShaderCompilerInputs();
|
|
|
|
ShaderCompiler compiler(
|
|
inputs.repoRoot,
|
|
inputs.wrapperPath,
|
|
inputs.generatedGlslPath,
|
|
inputs.patchedGlslPath,
|
|
inputs.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
|
|
{
|
|
BuildLayerRenderStates(outputWidth, outputHeight, mRuntimeStore.BuildRenderSnapshotReadModel(), states);
|
|
}
|
|
|
|
bool RenderSnapshotBuilder::TryBuildLayerRenderStates(unsigned outputWidth, unsigned outputHeight, std::vector<RuntimeRenderState>& states) const
|
|
{
|
|
BuildLayerRenderStates(outputWidth, outputHeight, mRuntimeStore.BuildRenderSnapshotReadModel(), states);
|
|
return true;
|
|
}
|
|
|
|
bool RenderSnapshotBuilder::TryRefreshLayerParameters(std::vector<RuntimeRenderState>& states) const
|
|
{
|
|
RefreshLayerParameters(mRuntimeStore.CopyCommittedLiveLayerStates(), states);
|
|
return true;
|
|
}
|
|
|
|
void RenderSnapshotBuilder::RefreshDynamicRenderStateFields(std::vector<RuntimeRenderState>& states) const
|
|
{
|
|
RefreshDynamicRenderStateFields(mRuntimeStore.GetRenderTimingSnapshot(), 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::BuildLayerRenderStates(unsigned outputWidth, unsigned outputHeight, const RenderSnapshotReadModel& readModel, std::vector<RuntimeRenderState>& states) const
|
|
{
|
|
states.clear();
|
|
|
|
for (const LayerStackStore::LayerPersistentState& layer : readModel.committedLiveState.layers)
|
|
{
|
|
auto shaderIt = readModel.committedLiveState.packagesById.find(layer.shaderId);
|
|
if (shaderIt == readModel.committedLiveState.packagesById.end())
|
|
continue;
|
|
const ShaderPackage& shaderPackage = shaderIt->second;
|
|
|
|
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 = readModel.signalStatus.width;
|
|
state.inputHeight = readModel.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);
|
|
}
|
|
|
|
RefreshDynamicRenderStateFields(readModel.timing, states);
|
|
}
|
|
|
|
void RenderSnapshotBuilder::RefreshLayerParameters(const std::vector<LayerStackStore::LayerPersistentState>& layers, std::vector<RuntimeRenderState>& states) const
|
|
{
|
|
for (RuntimeRenderState& state : states)
|
|
{
|
|
const auto layerIt = std::find_if(layers.begin(), layers.end(),
|
|
[&state](const LayerStackStore::LayerPersistentState& layer) { return layer.id == state.layerId; });
|
|
if (layerIt == 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::RefreshDynamicRenderStateFields(const RenderTimingSnapshot& timing, 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() - timing.startTime).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 = timing.startupRandom;
|
|
state.frameCount = frameCount;
|
|
}
|
|
}
|