#include "RuntimeLayerModel.h" #include "RuntimeParameterUtils.h" #include #include #include #include namespace RenderCadenceCompositor { namespace { bool ParseRuntimeLayerNumber(const std::string& layerId, uint64_t& number) { const std::string prefix = "runtime-layer-"; if (layerId.compare(0, prefix.size(), prefix) != 0) return false; const std::string suffix = layerId.substr(prefix.size()); if (suffix.empty()) return false; uint64_t parsed = 0; for (char character : suffix) { if (!std::isdigit(static_cast(character))) return false; parsed = parsed * 10 + static_cast(character - '0'); } number = parsed; return true; } std::string AllocateRestoredLayerId(std::set& usedLayerIds, uint64_t& nextLayerNumber) { for (;;) { std::string candidate = "runtime-layer-" + std::to_string(nextLayerNumber++); if (usedLayerIds.insert(candidate).second) return candidate; } } } bool RuntimeLayerModel::InitializeFromRuntimeState(const SupportedShaderCatalog& shaderCatalog, const JsonValue& runtimeState, std::string& error) { if (!runtimeState.isObject()) { error = "Runtime state root must be a JSON object."; return false; } const JsonValue* layersValue = runtimeState.find("layers"); if (!layersValue || !layersValue->isArray()) { error = "Runtime state must contain a layers array."; return false; } std::vector restoredLayers; std::set usedLayerIds; uint64_t nextLayerNumber = 1; for (const JsonValue& layerValue : layersValue->asArray()) { if (!layerValue.isObject()) continue; const JsonValue* shaderIdValue = layerValue.find("shaderId"); if (!shaderIdValue || !shaderIdValue->isString() || shaderIdValue->asString().empty()) continue; const ShaderPackage* shaderPackage = shaderCatalog.FindPackage(shaderIdValue->asString()); if (!shaderPackage) continue; Layer layer; const JsonValue* layerIdValue = layerValue.find("id"); if (layerIdValue && layerIdValue->isString() && !layerIdValue->asString().empty() && usedLayerIds.insert(layerIdValue->asString()).second) layer.id = layerIdValue->asString(); else layer.id = AllocateRestoredLayerId(usedLayerIds, nextLayerNumber); uint64_t restoredLayerNumber = 0; if (ParseRuntimeLayerNumber(layer.id, restoredLayerNumber) && restoredLayerNumber >= nextLayerNumber) nextLayerNumber = restoredLayerNumber + 1; layer.shaderId = shaderPackage->id; layer.packageFingerprint = ShaderPackageFingerprint(*shaderPackage); layer.shaderName = shaderPackage->displayName.empty() ? shaderPackage->id : shaderPackage->displayName; const JsonValue* bypassValue = layerValue.find("bypass"); layer.bypass = bypassValue && bypassValue->isBoolean() ? bypassValue->asBoolean() : false; layer.buildState = RuntimeLayerBuildState::Pending; layer.message = "Runtime Slang build is waiting to start."; InitializeDefaultParameterValues(layer, *shaderPackage); const JsonValue* parameterValues = layerValue.find("parameterValues"); if (parameterValues && parameterValues->isObject()) { for (const ShaderParameterDefinition& definition : layer.parameterDefinitions) { const JsonValue* value = parameterValues->find(definition.id); if (!value) continue; ShaderParameterValue normalizedValue; std::string normalizeError; if (NormalizeAndValidateParameterValue(definition, *value, normalizedValue, normalizeError)) layer.parameterValues[definition.id] = normalizedValue; } } restoredLayers.push_back(std::move(layer)); } if (restoredLayers.empty()) { error = "Runtime state did not contain any supported layers."; return false; } mLayers = std::move(restoredLayers); mNextLayerNumber = nextLayerNumber; error.clear(); return true; } }