Shader: Add support for partial sanitization

This commit is contained in:
SirLynix
2022-03-25 12:54:51 +01:00
parent a54f70fd24
commit 8146ec251a
31 changed files with 1105 additions and 521 deletions

View File

@@ -249,7 +249,7 @@ struct VertIn
}
[entry(vert), cond(Billboard)]
fn billboardMain(input: VertIn) -> VertOut
fn billboardMain(input: VertIn) -> VertToFrag
{
let size = input.billboardSizeRot.xy;
let sinCos = input.billboardSizeRot.zw;

View File

@@ -25,7 +25,7 @@ namespace Nz
m_shaderModule = moduleResolver.Resolve(moduleName);
NazaraAssert(m_shaderModule, "invalid shader module");
Validate(*m_shaderModule);
m_shaderModule = Validate(*m_shaderModule, &m_optionIndexByName);
m_onShaderModuleUpdated.Connect(moduleResolver.OnModuleUpdated, [this, name = std::move(moduleName)](ShaderModuleResolver* resolver, const std::string& updatedModuleName)
{
@@ -41,8 +41,7 @@ namespace Nz
try
{
// FIXME: Validate is destructive, in case of failure it can invalidate the shader
Validate(*newShaderModule);
m_shaderModule = Validate(*newShaderModule, &m_optionIndexByName);
}
catch (const std::exception& e)
{
@@ -50,8 +49,6 @@ namespace Nz
return;
}
m_shaderModule = std::move(newShaderModule);
// Clear cache
m_combinations.clear();
@@ -65,7 +62,7 @@ namespace Nz
{
NazaraAssert(m_shaderModule, "invalid shader module");
Validate(*m_shaderModule);
Validate(*m_shaderModule, &m_optionIndexByName);
}
const std::shared_ptr<ShaderModule>& UberShader::Get(const Config& config)
@@ -85,13 +82,17 @@ namespace Nz
return it->second;
}
void UberShader::Validate(ShaderAst::Module& module)
ShaderAst::ModulePtr UberShader::Validate(const ShaderAst::Module& module, std::unordered_map<std::string, Option>* options)
{
NazaraAssert(m_shaderStages != 0, "there must be at least one shader stage");
assert(options);
//TODO: Try to partially sanitize shader?
// Try to partially sanitize shader
std::size_t optionCount = 0;
ShaderAst::SanitizeVisitor::Options sanitizeOptions;
sanitizeOptions.allowPartialSanitization = true;
ShaderAst::ModulePtr sanitizedModule = ShaderAst::Sanitize(module, sanitizeOptions);
ShaderStageTypeFlags supportedStageType;
@@ -101,21 +102,24 @@ namespace Nz
supportedStageType |= stageType;
};
std::unordered_map<std::string, Option> optionByName;
callbacks.onOptionDeclaration = [&](const ShaderAst::DeclareOptionStatement& option)
{
//TODO: Check optionType
m_optionIndexByName[option.optName] = Option{
optionByName[option.optName] = Option{
CRC32(option.optName)
};
optionCount++;
};
ShaderAst::AstReflect reflect;
reflect.Reflect(*module.rootNode, callbacks);
reflect.Reflect(*sanitizedModule->rootNode, callbacks);
if ((m_shaderStages & supportedStageType) != m_shaderStages)
throw std::runtime_error("shader doesn't support all required shader stages");
*options = std::move(optionByName);
return sanitizedModule;
}
}