#include "RuntimeLayerModel.h" #include "RuntimeParameterUtils.h" #include "RuntimeTextTextureComposer.h" #include #include #include namespace RenderCadenceCompositor { bool RuntimeLayerModel::InitializeSingleLayer(const SupportedShaderCatalog& shaderCatalog, const std::string& shaderId, std::string& error) { Clear(); if (shaderId.empty()) { error.clear(); return true; } const ShaderPackage* shaderPackage = shaderCatalog.FindPackage(shaderId); if (!shaderPackage) { error = "Shader '" + shaderId + "' is not in the supported shader catalog."; return false; } Layer layer; layer.id = AllocateLayerId(); layer.shaderId = shaderPackage->id; layer.packageFingerprint = ShaderPackageFingerprint(*shaderPackage); layer.shaderName = shaderPackage->displayName.empty() ? shaderPackage->id : shaderPackage->displayName; layer.buildState = RuntimeLayerBuildState::Pending; layer.message = "Runtime Slang build is waiting to start."; InitializeDefaultParameterValues(layer, *shaderPackage); mLayers.push_back(std::move(layer)); error.clear(); return true; } bool RuntimeLayerModel::AddLayer(const SupportedShaderCatalog& shaderCatalog, const std::string& shaderId, std::string& layerId, std::string& error) { const ShaderPackage* shaderPackage = shaderCatalog.FindPackage(shaderId); if (!shaderPackage) { error = "Shader '" + shaderId + "' is not in the supported shader catalog."; return false; } Layer layer; layer.id = AllocateLayerId(); layer.shaderId = shaderPackage->id; layer.packageFingerprint = ShaderPackageFingerprint(*shaderPackage); layer.shaderName = shaderPackage->displayName.empty() ? shaderPackage->id : shaderPackage->displayName; layer.buildState = RuntimeLayerBuildState::Pending; layer.message = "Runtime Slang build is waiting to start."; InitializeDefaultParameterValues(layer, *shaderPackage); layerId = layer.id; mLayers.push_back(std::move(layer)); error.clear(); return true; } bool RuntimeLayerModel::RemoveLayer(const std::string& layerId, std::string& error) { for (auto layerIt = mLayers.begin(); layerIt != mLayers.end(); ++layerIt) { if (layerIt->id != layerId) continue; mLayers.erase(layerIt); error.clear(); return true; } error = "Unknown runtime layer id: " + layerId; return false; } bool RuntimeLayerModel::ReorderLayer(const std::string& layerId, int targetIndex, std::string& error) { auto layerIt = std::find_if(mLayers.begin(), mLayers.end(), [&layerId](const Layer& layer) { return layer.id == layerId; }); if (layerIt == mLayers.end()) { error = "Unknown runtime layer id: " + layerId; return false; } if (targetIndex < 0) targetIndex = 0; if (targetIndex >= static_cast(mLayers.size())) targetIndex = static_cast(mLayers.size()) - 1; Layer layer = std::move(*layerIt); mLayers.erase(layerIt); std::size_t destinationIndex = static_cast(targetIndex); if (destinationIndex > mLayers.size()) destinationIndex = mLayers.size(); mLayers.insert(mLayers.begin() + static_cast(destinationIndex), std::move(layer)); error.clear(); return true; } bool RuntimeLayerModel::SetLayerBypass(const std::string& layerId, bool bypass, std::string& error) { Layer* layer = FindLayer(layerId); if (!layer) { error = "Unknown runtime layer id: " + layerId; return false; } layer->bypass = bypass; error.clear(); return true; } bool RuntimeLayerModel::SetLayerShader(const SupportedShaderCatalog& shaderCatalog, const std::string& layerId, const std::string& shaderId, std::string& error) { Layer* layer = FindLayer(layerId); if (!layer) { error = "Unknown runtime layer id: " + layerId; return false; } const ShaderPackage* shaderPackage = shaderCatalog.FindPackage(shaderId); if (!shaderPackage) { error = "Shader '" + shaderId + "' is not in the supported shader catalog."; return false; } layer->shaderId = shaderPackage->id; layer->packageFingerprint = ShaderPackageFingerprint(*shaderPackage); layer->shaderName = shaderPackage->displayName.empty() ? shaderPackage->id : shaderPackage->displayName; layer->buildState = RuntimeLayerBuildState::Pending; layer->message = "Runtime Slang build is waiting to start."; layer->renderReady = false; layer->artifact = RuntimeShaderArtifact(); InitializeDefaultParameterValues(*layer, *shaderPackage); error.clear(); return true; } bool RuntimeLayerModel::UpdateParameter(const std::string& layerId, const std::string& parameterId, const JsonValue& value, std::string& error) { Layer* layer = FindLayer(layerId); if (!layer) { error = "Unknown runtime layer id: " + layerId; return false; } const ShaderParameterDefinition* definition = FindParameterDefinition(*layer, parameterId); if (!definition) { error = "Unknown parameter id '" + parameterId + "' for layer " + layerId + "."; return false; } ShaderParameterValue normalizedValue; if (definition->type == ShaderParameterType::Trigger) { const auto currentIt = layer->parameterValues.find(parameterId); const double previousCount = currentIt == layer->parameterValues.end() || currentIt->second.numberValues.empty() ? 0.0 : currentIt->second.numberValues.front(); normalizedValue.numberValues = { previousCount + 1.0, RuntimeElapsedSeconds() }; } else if (!NormalizeAndValidateParameterValue(*definition, value, normalizedValue, error)) { return false; } layer->parameterValues[parameterId] = normalizedValue; if (layer->renderReady) { layer->artifact.parameterValues = layer->parameterValues; bool textTexturesDependOnParameter = false; for (const ShaderParameterDefinition& textDefinition : layer->parameterDefinitions) { if (textDefinition.type == ShaderParameterType::Text && (textDefinition.id == parameterId || textDefinition.fontParameterId == parameterId)) { textTexturesDependOnParameter = true; break; } } if (textTexturesDependOnParameter && !PrepareRuntimeTextTextures(layer->artifact, error)) return false; } error.clear(); return true; } bool RuntimeLayerModel::ResetParameters(const std::string& layerId, std::string& error) { Layer* layer = FindLayer(layerId); if (!layer) { error = "Unknown runtime layer id: " + layerId; return false; } layer->parameterValues.clear(); for (const ShaderParameterDefinition& definition : layer->parameterDefinitions) layer->parameterValues[definition.id] = DefaultValueForDefinition(definition); if (layer->renderReady) { layer->artifact.parameterValues = layer->parameterValues; if (!PrepareRuntimeTextTextures(layer->artifact, error)) return false; } error.clear(); return true; } void RuntimeLayerModel::Clear() { mLayers.clear(); } bool RuntimeLayerModel::MarkBuildStarted(const std::string& layerId, const std::string& message, std::string& error, bool preserveExistingRenderArtifact) { Layer* layer = FindLayer(layerId); if (!layer) { error = "Unknown runtime layer id: " + layerId; return false; } layer->buildState = RuntimeLayerBuildState::Pending; layer->message = message; layer->preserveRenderDuringBuild = preserveExistingRenderArtifact && layer->renderReady; if (!layer->preserveRenderDuringBuild) { layer->renderReady = false; layer->artifact = RuntimeShaderArtifact(); } error.clear(); return true; } bool RuntimeLayerModel::MarkBuildReady(const RuntimeShaderArtifact& artifact, std::string& error) { Layer* layer = artifact.layerId.empty() ? FindFirstLayerForShader(artifact.shaderId) : FindLayer(artifact.layerId); if (!layer) { error = artifact.layerId.empty() ? "No runtime layer is waiting for shader artifact: " + artifact.shaderId : "No runtime layer is waiting for shader artifact on layer: " + artifact.layerId; return false; } RuntimeShaderArtifact nextArtifact = artifact; nextArtifact.parameterValues = layer->parameterValues; if (!PrepareRuntimeTextTextures(nextArtifact, error)) { layer->buildState = RuntimeLayerBuildState::Failed; layer->message = error; if (!layer->preserveRenderDuringBuild) { layer->renderReady = false; layer->artifact = RuntimeShaderArtifact(); } layer->preserveRenderDuringBuild = false; return false; } layer->shaderName = artifact.displayName.empty() ? artifact.shaderId : artifact.displayName; layer->packageFingerprint = artifact.packageFingerprint; layer->buildState = RuntimeLayerBuildState::Ready; layer->message = artifact.message; layer->renderReady = true; layer->preserveRenderDuringBuild = false; layer->artifact = std::move(nextArtifact); error.clear(); return true; } bool RuntimeLayerModel::MarkBuildFailedForShader(const std::string& shaderId, const std::string& message) { Layer* layer = FindFirstLayerForShader(shaderId); if (!layer) return false; std::string error; return MarkBuildFailed(layer->id, message, error); } bool RuntimeLayerModel::MarkBuildFailed(const std::string& layerId, const std::string& message, std::string& error) { Layer* layer = FindLayer(layerId); if (!layer) { error = "Unknown runtime layer id: " + layerId; return false; } layer->buildState = RuntimeLayerBuildState::Failed; layer->message = message; if (!layer->preserveRenderDuringBuild) { layer->renderReady = false; layer->artifact = RuntimeShaderArtifact(); } layer->preserveRenderDuringBuild = false; error.clear(); return true; } bool RuntimeLayerModel::MarkRenderCommitFailed(const std::string& layerId, const std::string& message, std::string& error) { return MarkBuildFailed(layerId, message, error); } std::string RuntimeLayerModel::FirstLayerId() const { return mLayers.empty() ? std::string() : mLayers.front().id; } std::vector> RuntimeLayerModel::PendingLayerBuilds() const { std::vector> builds; for (const Layer& layer : mLayers) { if (layer.buildState == RuntimeLayerBuildState::Pending) builds.push_back({ layer.id, layer.shaderId }); } return builds; } RuntimeLayerModel::Layer* RuntimeLayerModel::FindLayer(const std::string& layerId) { for (Layer& layer : mLayers) { if (layer.id == layerId) return &layer; } return nullptr; } const RuntimeLayerModel::Layer* RuntimeLayerModel::FindLayer(const std::string& layerId) const { for (const Layer& layer : mLayers) { if (layer.id == layerId) return &layer; } return nullptr; } RuntimeLayerModel::Layer* RuntimeLayerModel::FindFirstLayerForShader(const std::string& shaderId) { for (Layer& layer : mLayers) { if (layer.shaderId == shaderId) return &layer; } return nullptr; } void RuntimeLayerModel::InitializeDefaultParameterValues(Layer& layer, const ShaderPackage& shaderPackage) { layer.parameterDefinitions = shaderPackage.parameters; layer.parameterValues.clear(); for (const ShaderParameterDefinition& definition : layer.parameterDefinitions) layer.parameterValues[definition.id] = DefaultValueForDefinition(definition); } const ShaderParameterDefinition* RuntimeLayerModel::FindParameterDefinition(const Layer& layer, const std::string& parameterId) { for (const ShaderParameterDefinition& definition : layer.parameterDefinitions) { if (definition.id == parameterId) return &definition; } return nullptr; } std::string RuntimeLayerModel::AllocateLayerId() { return "runtime-layer-" + std::to_string(mNextLayerNumber++); } double RuntimeLayerModel::RuntimeElapsedSeconds() const { return std::chrono::duration_cast>(std::chrono::steady_clock::now() - mStartTime).count(); } }