#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; 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& states) const { std::lock_guard lock(mRuntimeStore.mMutex); BuildLayerRenderStatesLocked(outputWidth, outputHeight, states); } bool RenderSnapshotBuilder::TryBuildLayerRenderStates(unsigned outputWidth, unsigned outputHeight, std::vector& states) const { std::unique_lock lock(mRuntimeStore.mMutex, std::try_to_lock); if (!lock.owns_lock()) return false; BuildLayerRenderStatesLocked(outputWidth, outputHeight, states); return true; } bool RenderSnapshotBuilder::TryRefreshLayerParameters(std::vector& states) const { std::unique_lock lock(mRuntimeStore.mMutex, std::try_to_lock); if (!lock.owns_lock()) return false; RefreshLayerParametersLocked(states); return true; } void RenderSnapshotBuilder::RefreshDynamicRenderStateFields(std::vector& states) const { std::lock_guard 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& 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& 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& states) const { const RuntimeClockSnapshot clock = GetRuntimeClockSnapshot(); const double timeSeconds = std::chrono::duration_cast>(std::chrono::steady_clock::now() - mRuntimeStore.mStartTime).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 = mRuntimeStore.mStartupRandom; state.frameCount = frameCount; } }