#include "RenderSnapshotBuilder.h" #include "RuntimeClock.h" #include "RuntimeParameterUtils.h" #include "RuntimeStore.h" #include "ShaderCompiler.h" #include #include #include #include #include RenderSnapshotBuilder::RenderSnapshotBuilder(RuntimeStore& runtimeStore) : mRuntimeStore(runtimeStore) { } bool RenderSnapshotBuilder::BuildLayerPassFragmentShaderSources(const std::string& layerId, std::vector& 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& states) const { BuildLayerRenderStates(outputWidth, outputHeight, mRuntimeStore.BuildRenderSnapshotReadModel(), states); } bool RenderSnapshotBuilder::TryBuildLayerRenderStates(unsigned outputWidth, unsigned outputHeight, std::vector& states) const { BuildLayerRenderStates(outputWidth, outputHeight, mRuntimeStore.BuildRenderSnapshotReadModel(), states); return true; } bool RenderSnapshotBuilder::TryRefreshLayerParameters(std::vector& states) const { RefreshLayerParameters(mRuntimeStore.CopyCommittedLiveLayerStates(), states); return true; } void RenderSnapshotBuilder::RefreshDynamicRenderStateFields(std::vector& 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& 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& layers, std::vector& 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& states) const { const RuntimeClockSnapshot clock = GetRuntimeClockSnapshot(); const double timeSeconds = std::chrono::duration_cast>(std::chrono::steady_clock::now() - timing.startTime).count(); const double frameCount = static_cast(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; } }