#include "RuntimeLayerModel.h" #include "RuntimeParameterUtils.h" #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.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.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->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 (!NormalizeAndValidateParameterValue(*definition, value, normalizedValue, error)) return false; layer->parameterValues[parameterId] = normalizedValue; if (layer->renderReady) layer->artifact.parameterValues = layer->parameterValues; 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; error.clear(); return true; } void RuntimeLayerModel::Clear() { mLayers.clear(); } bool RuntimeLayerModel::MarkBuildStarted(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::Pending; layer->message = message; 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; } layer->shaderName = artifact.displayName.empty() ? artifact.shaderId : artifact.displayName; layer->buildState = RuntimeLayerBuildState::Ready; layer->message = artifact.message; layer->renderReady = true; layer->artifact = artifact; layer->artifact.parameterValues = layer->parameterValues; 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; layer->renderReady = false; layer->artifact = RuntimeShaderArtifact(); error.clear(); return true; } bool RuntimeLayerModel::MarkRenderCommitFailed(const std::string& layerId, const std::string& message, std::string& error) { return MarkBuildFailed(layerId, message, error); } RuntimeLayerModelSnapshot RuntimeLayerModel::Snapshot() const { RuntimeLayerModelSnapshot snapshot; snapshot.compileSucceeded = true; for (const Layer& layer : mLayers) { snapshot.displayLayers.push_back(ToReadModel(layer)); if (!layer.message.empty() && snapshot.compileMessage.empty()) snapshot.compileMessage = layer.message; if (layer.buildState == RuntimeLayerBuildState::Failed) snapshot.compileSucceeded = false; if (layer.renderReady) { RuntimeRenderLayerModel renderLayer; renderLayer.id = layer.id; renderLayer.shaderId = layer.shaderId; renderLayer.bypass = layer.bypass; renderLayer.artifact = layer.artifact; renderLayer.artifact.parameterValues = layer.parameterValues; snapshot.renderLayers.push_back(std::move(renderLayer)); } } if (snapshot.compileMessage.empty()) snapshot.compileMessage = mLayers.empty() ? "Runtime shader build disabled." : "Runtime shader build has not completed yet."; return snapshot; } std::string RuntimeLayerModel::FirstLayerId() const { return mLayers.empty() ? std::string() : mLayers.front().id; } 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++); } RuntimeLayerReadModel RuntimeLayerModel::ToReadModel(const Layer& layer) { RuntimeLayerReadModel readModel; readModel.id = layer.id; readModel.shaderId = layer.shaderId; readModel.shaderName = layer.shaderName; readModel.bypass = layer.bypass; readModel.buildState = layer.buildState; readModel.message = layer.message; readModel.renderReady = layer.renderReady; readModel.parameterDefinitions = layer.parameterDefinitions; readModel.parameterValues = layer.parameterValues; return readModel; } }