Hot reload
This commit is contained in:
@@ -8,6 +8,35 @@
|
||||
|
||||
namespace RenderCadenceCompositor
|
||||
{
|
||||
namespace
|
||||
{
|
||||
JsonValue ParameterValueToJson(const ShaderParameterDefinition& definition, const ShaderParameterValue& value)
|
||||
{
|
||||
switch (definition.type)
|
||||
{
|
||||
case ShaderParameterType::Float:
|
||||
return JsonValue(value.numberValues.empty() ? 0.0 : value.numberValues.front());
|
||||
case ShaderParameterType::Vec2:
|
||||
case ShaderParameterType::Color:
|
||||
{
|
||||
JsonValue array = JsonValue::MakeArray();
|
||||
for (double number : value.numberValues)
|
||||
array.pushBack(JsonValue(number));
|
||||
return array;
|
||||
}
|
||||
case ShaderParameterType::Boolean:
|
||||
return JsonValue(value.booleanValue);
|
||||
case ShaderParameterType::Enum:
|
||||
return JsonValue(value.enumValue);
|
||||
case ShaderParameterType::Text:
|
||||
return JsonValue(value.textValue);
|
||||
case ShaderParameterType::Trigger:
|
||||
return JsonValue(value.numberValues.empty() ? 0.0 : value.numberValues.front());
|
||||
}
|
||||
return JsonValue();
|
||||
}
|
||||
}
|
||||
|
||||
bool RuntimeLayerModel::InitializeSingleLayer(const SupportedShaderCatalog& shaderCatalog, const std::string& shaderId, std::string& error)
|
||||
{
|
||||
Clear();
|
||||
@@ -27,6 +56,7 @@ bool RuntimeLayerModel::InitializeSingleLayer(const SupportedShaderCatalog& shad
|
||||
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.";
|
||||
@@ -48,6 +78,7 @@ bool RuntimeLayerModel::AddLayer(const SupportedShaderCatalog& shaderCatalog, co
|
||||
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.";
|
||||
@@ -130,6 +161,7 @@ bool RuntimeLayerModel::SetLayerShader(const SupportedShaderCatalog& shaderCatal
|
||||
}
|
||||
|
||||
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.";
|
||||
@@ -195,6 +227,61 @@ bool RuntimeLayerModel::ResetParameters(const std::string& layerId, std::string&
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RuntimeLayerModel::ReloadFromCatalog(const SupportedShaderCatalog& shaderCatalog, std::vector<std::pair<std::string, std::string>>& buildsToStart, std::string& error)
|
||||
{
|
||||
buildsToStart.clear();
|
||||
for (Layer& layer : mLayers)
|
||||
{
|
||||
const ShaderPackage* shaderPackage = shaderCatalog.FindPackage(layer.shaderId);
|
||||
if (!shaderPackage)
|
||||
{
|
||||
layer.buildState = RuntimeLayerBuildState::Failed;
|
||||
layer.message = "Shader '" + layer.shaderId + "' is no longer available after reload.";
|
||||
continue;
|
||||
}
|
||||
|
||||
const std::string nextFingerprint = ShaderPackageFingerprint(*shaderPackage);
|
||||
if (layer.packageFingerprint == nextFingerprint)
|
||||
continue;
|
||||
|
||||
std::map<std::string, ShaderParameterDefinition> previousDefinitions;
|
||||
for (const ShaderParameterDefinition& definition : layer.parameterDefinitions)
|
||||
previousDefinitions[definition.id] = definition;
|
||||
|
||||
std::map<std::string, ShaderParameterValue> nextValues;
|
||||
for (const ShaderParameterDefinition& nextDefinition : shaderPackage->parameters)
|
||||
{
|
||||
const auto previousDefinitionIt = previousDefinitions.find(nextDefinition.id);
|
||||
const auto previousValueIt = layer.parameterValues.find(nextDefinition.id);
|
||||
if (previousDefinitionIt != previousDefinitions.end()
|
||||
&& previousValueIt != layer.parameterValues.end()
|
||||
&& previousDefinitionIt->second.type == nextDefinition.type)
|
||||
{
|
||||
ShaderParameterValue preservedValue;
|
||||
JsonValue valueJson = ParameterValueToJson(previousDefinitionIt->second, previousValueIt->second);
|
||||
std::string normalizeError;
|
||||
if (NormalizeAndValidateParameterValue(nextDefinition, valueJson, preservedValue, normalizeError))
|
||||
{
|
||||
nextValues[nextDefinition.id] = preservedValue;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
nextValues[nextDefinition.id] = DefaultValueForDefinition(nextDefinition);
|
||||
}
|
||||
|
||||
layer.shaderName = shaderPackage->displayName.empty() ? shaderPackage->id : shaderPackage->displayName;
|
||||
layer.packageFingerprint = nextFingerprint;
|
||||
layer.parameterDefinitions = shaderPackage->parameters;
|
||||
layer.parameterValues = std::move(nextValues);
|
||||
if (layer.renderReady)
|
||||
layer.artifact.parameterValues = layer.parameterValues;
|
||||
buildsToStart.push_back({ layer.id, layer.shaderId });
|
||||
}
|
||||
|
||||
error.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
void RuntimeLayerModel::Clear()
|
||||
{
|
||||
mLayers.clear();
|
||||
@@ -229,6 +316,7 @@ bool RuntimeLayerModel::MarkBuildReady(const RuntimeShaderArtifact& artifact, st
|
||||
}
|
||||
|
||||
layer->shaderName = artifact.displayName.empty() ? artifact.shaderId : artifact.displayName;
|
||||
layer->packageFingerprint = artifact.packageFingerprint;
|
||||
layer->buildState = RuntimeLayerBuildState::Ready;
|
||||
layer->message = artifact.message;
|
||||
layer->renderReady = true;
|
||||
|
||||
Reference in New Issue
Block a user