Shader: Replace indices-based option keys by CRC32

This commit is contained in:
Jérôme Leclercq 2022-03-06 19:13:38 +01:00
parent 505d996c88
commit a7acf32886
18 changed files with 92 additions and 152 deletions

View File

@ -22,12 +22,19 @@ namespace Nz
struct MaterialPipelineInfo : RenderStates struct MaterialPipelineInfo : RenderStates
{ {
struct Option
{
UInt32 hash;
ShaderAst::ConstantValue value;
};
struct Shader struct Shader
{ {
std::array<ShaderAst::ConstantValue, 32> optionValues;
std::shared_ptr<UberShader> uberShader; std::shared_ptr<UberShader> uberShader;
}; };
std::array<Option, 32> optionValues;
std::size_t optionCount = 0;
std::vector<Shader> shaders; std::vector<Shader> shaders;
std::shared_ptr<const MaterialSettings> settings; std::shared_ptr<const MaterialSettings> settings;
}; };

View File

@ -32,13 +32,20 @@ namespace Nz
#define NazaraPipelineMember(field) if (lhs.field != rhs.field) return false #define NazaraPipelineMember(field) if (lhs.field != rhs.field) return false
NazaraPipelineMember(settings); NazaraPipelineMember(settings);
NazaraPipelineMember(optionCount);
for (std::size_t i = 0; i < lhs.shaders.size(); ++i) for (std::size_t i = 0; i < lhs.shaders.size(); ++i)
{ {
if (lhs.shaders[i].optionValues != rhs.shaders[i].optionValues) if (lhs.shaders[i].uberShader != rhs.shaders[i].uberShader)
return false;
}
for (std::size_t i = 0; i < lhs.optionCount; ++i)
{
if (lhs.optionValues[i].hash != rhs.optionValues[i].hash)
return false; return false;
if (lhs.shaders[i].uberShader != rhs.shaders[i].uberShader) if (lhs.optionValues[i].value != rhs.optionValues[i].value)
return false; return false;
} }
@ -72,14 +79,15 @@ namespace std
NazaraPipelineMember(settings.get()); //< Hash pointer NazaraPipelineMember(settings.get()); //< Hash pointer
for (const auto& shader : pipelineInfo.shaders) for (std::size_t i = 0; i < pipelineInfo.optionCount; ++i)
{ {
for (const auto& value : shader.optionValues) Nz::HashCombine(seed, pipelineInfo.optionValues[i].hash);
Nz::HashCombine(seed, value); Nz::HashCombine(seed, pipelineInfo.optionValues[i].value);
Nz::HashCombine(seed, shader.uberShader.get());
} }
for (const auto& shader : pipelineInfo.shaders)
Nz::HashCombine(seed, shader.uberShader.get());
NazaraUnused(parameterIndex); NazaraUnused(parameterIndex);
#undef NazaraPipelineMember #undef NazaraPipelineMember

View File

@ -57,7 +57,7 @@ namespace Nz
static constexpr std::size_t InvalidIndex = std::numeric_limits<std::size_t>::max(); static constexpr std::size_t InvalidIndex = std::numeric_limits<std::size_t>::max();
static inline void BuildOption(std::vector<Option>& options, const std::vector<std::shared_ptr<UberShader>>& uberShaders, std::string optionName, const std::string& shaderOptionName); static inline void BuildOption(std::vector<Option>& options, std::string optionName, const std::string& shaderOptionName);
struct Builder struct Builder
{ {
@ -74,7 +74,7 @@ namespace Nz
struct Option struct Option
{ {
std::string name; std::string name;
std::vector<std::optional<std::size_t>> optionIndexByShader; UInt32 hash;
}; };
struct UniformVariable struct UniformVariable

View File

@ -3,6 +3,7 @@
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Graphics/MaterialSettings.hpp> #include <Nazara/Graphics/MaterialSettings.hpp>
#include <Nazara/Core/Algorithm.hpp>
#include <Nazara/Graphics/Graphics.hpp> #include <Nazara/Graphics/Graphics.hpp>
#include <cassert> #include <cassert>
#include <Nazara/Graphics/Debug.hpp> #include <Nazara/Graphics/Debug.hpp>
@ -169,32 +170,15 @@ namespace Nz
return InvalidIndex; return InvalidIndex;
} }
inline void MaterialSettings::BuildOption(std::vector<Option>& options, const std::vector<std::shared_ptr<UberShader>>& uberShaders, std::string optionName, const std::string& shaderOptionName) inline void MaterialSettings::BuildOption(std::vector<Option>& options, std::string optionName, const std::string& shaderOptionName)
{ {
std::vector<std::optional<std::size_t>> shaderOptions; UInt32 optionHash = CRC32(shaderOptionName);
for (std::size_t shaderIndex = 0; shaderIndex < uberShaders.size(); ++shaderIndex)
{
const auto& uberShader = uberShaders[shaderIndex];
const UberShader::Option* optionData;
if (uberShader->HasOption(shaderOptionName, &optionData))
{
if (shaderIndex >= shaderOptions.size())
shaderOptions.resize(shaderIndex + 1);
shaderOptions[shaderIndex] = optionData->index;
}
}
if (std::any_of(shaderOptions.begin(), shaderOptions.end(), [&](std::optional<std::size_t> optionIndex) { return optionIndex.has_value(); }))
{
options.push_back({ options.push_back({
std::move(optionName), std::move(optionName),
shaderOptions optionHash
}); });
} }
}
inline MaterialSettings::Builder::Builder() inline MaterialSettings::Builder::Builder()
{ {

View File

@ -38,11 +38,9 @@ namespace Nz
inline void UpdateConfig(Config& config, const std::vector<RenderPipelineInfo::VertexBufferData>& vertexBuffers); inline void UpdateConfig(Config& config, const std::vector<RenderPipelineInfo::VertexBufferData>& vertexBuffers);
inline void UpdateConfigCallback(ConfigCallback callback); inline void UpdateConfigCallback(ConfigCallback callback);
static constexpr std::size_t MaximumOptionValue = 32;
struct Config struct Config
{ {
std::array<ShaderAst::ConstantValue, MaximumOptionValue> optionValues; std::unordered_map<UInt32, ShaderAst::ConstantValue> optionValues;
}; };
struct ConfigEqual struct ConfigEqual
@ -57,7 +55,7 @@ namespace Nz
struct Option struct Option
{ {
std::size_t index; UInt32 hash;
}; };
private: private:

View File

@ -37,20 +37,17 @@ namespace Nz
inline bool UberShader::ConfigEqual::operator()(const Config& lhs, const Config& rhs) const inline bool UberShader::ConfigEqual::operator()(const Config& lhs, const Config& rhs) const
{ {
for (std::size_t i = 0; i < lhs.optionValues.size(); ++i) return lhs.optionValues == rhs.optionValues;
{
if (lhs.optionValues[i] != rhs.optionValues[i])
return false;
}
return true;
} }
inline std::size_t UberShader::ConfigHasher::operator()(const Config& config) const inline std::size_t UberShader::ConfigHasher::operator()(const Config& config) const
{ {
std::size_t hash = 0; std::size_t hash = 0;
for (std::size_t i = 0; i < config.optionValues.size(); ++i) for (auto&& [key, value] : config.optionValues)
HashCombine(hash, config.optionValues[i]); {
HashCombine(hash, key);
HashCombine(hash, value);
}
return hash; return hash;
} }

View File

@ -44,7 +44,7 @@ namespace Nz::ShaderAst
{ {
std::function<ModulePtr(const std::vector<std::string>& /*modulePath*/)> moduleCallback; std::function<ModulePtr(const std::vector<std::string>& /*modulePath*/)> moduleCallback;
std::unordered_set<std::string> reservedIdentifiers; std::unordered_set<std::string> reservedIdentifiers;
std::unordered_map<std::size_t, ConstantValue> optionValues; std::unordered_map<UInt32, ConstantValue> optionValues;
bool makeVariableNameUnique = false; bool makeVariableNameUnique = false;
bool reduceLoopsToWhile = false; bool reduceLoopsToWhile = false;
bool removeConstDeclaration = false; bool removeConstDeclaration = false;

View File

@ -48,7 +48,7 @@ namespace Nz
}; };
static const char* GetFlipYUniformName(); static const char* GetFlipYUniformName();
static ShaderAst::ModulePtr Sanitize(const ShaderAst::Module& module, std::unordered_map<std::size_t, ShaderAst::ConstantValue> optionValues, std::string* error = nullptr); static ShaderAst::ModulePtr Sanitize(const ShaderAst::Module& module, std::unordered_map<UInt32, ShaderAst::ConstantValue> optionValues, std::string* error = nullptr);
private: private:
void Append(const ShaderAst::ArrayType& type); void Append(const ShaderAst::ArrayType& type);

View File

@ -27,7 +27,7 @@ namespace Nz
struct States struct States
{ {
std::unordered_map<std::size_t, ShaderAst::ConstantValue> optionValues; std::unordered_map<UInt32, ShaderAst::ConstantValue> optionValues;
bool optimize = false; bool optimize = false;
bool sanitized = false; bool sanitized = false;
}; };

View File

@ -174,26 +174,8 @@ namespace Nz
settings.shaders = options.shaders; settings.shaders = options.shaders;
for (std::shared_ptr<UberShader> uberShader : settings.shaders) for (const std::shared_ptr<UberShader>& uberShader : settings.shaders)
{ {
constexpr std::size_t InvalidOption = std::numeric_limits<std::size_t>::max();
auto FetchLocationOption = [&](const std::string& optionName)
{
const UberShader::Option* optionPtr;
if (!uberShader->HasOption(optionName, &optionPtr))
return InvalidOption;
//if (optionPtr->type != ShaderAst::ExpressionType{ ShaderAst::PrimitiveType::Int32 })
// throw std::runtime_error("Location options must be of type i32");
return optionPtr->index;
};
std::size_t positionLocationIndex = FetchLocationOption("PosLocation");
std::size_t colorLocationIndex = FetchLocationOption("ColorLocation");
std::size_t uvLocationIndex = FetchLocationOption("UvLocation");
uberShader->UpdateConfigCallback([=](UberShader::Config& config, const std::vector<RenderPipelineInfo::VertexBufferData>& vertexBuffers) uberShader->UpdateConfigCallback([=](UberShader::Config& config, const std::vector<RenderPipelineInfo::VertexBufferData>& vertexBuffers)
{ {
if (vertexBuffers.empty()) if (vertexBuffers.empty())
@ -202,27 +184,21 @@ namespace Nz
const VertexDeclaration& vertexDeclaration = *vertexBuffers.front().declaration; const VertexDeclaration& vertexDeclaration = *vertexBuffers.front().declaration;
const auto& components = vertexDeclaration.GetComponents(); const auto& components = vertexDeclaration.GetComponents();
std::size_t locationIndex = 0; Int32 locationIndex = 0;
for (const auto& component : components) for (const auto& component : components)
{ {
switch (component.component) switch (component.component)
{ {
case VertexComponent::Position: case VertexComponent::Position:
if (positionLocationIndex != InvalidOption) config.optionValues[CRC32("PosLocation")] = locationIndex;
config.optionValues[positionLocationIndex] = static_cast<Int32>(locationIndex);
break; break;
case VertexComponent::Color: case VertexComponent::Color:
if (colorLocationIndex != InvalidOption) config.optionValues[CRC32("ColorLocation")] = locationIndex;
config.optionValues[colorLocationIndex] = static_cast<Int32>(locationIndex);
break; break;
case VertexComponent::TexCoord: case VertexComponent::TexCoord:
if (uvLocationIndex != InvalidOption) config.optionValues[CRC32("UvLocation")] = locationIndex;
config.optionValues[uvLocationIndex] = static_cast<Int32>(locationIndex);
break; break;
case VertexComponent::Unused: case VertexComponent::Unused:
@ -241,19 +217,19 @@ namespace Nz
if (options.basicOptionIndexes) if (options.basicOptionIndexes)
options.basicOptionIndexes->hasDiffuseMap = settings.options.size(); options.basicOptionIndexes->hasDiffuseMap = settings.options.size();
MaterialSettings::BuildOption(settings.options, settings.shaders, "HasDiffuseMap", "HasDiffuseTexture"); MaterialSettings::BuildOption(settings.options, "HasDiffuseMap", "HasDiffuseTexture");
// HasAlphaMap // HasAlphaMap
if (options.basicOptionIndexes) if (options.basicOptionIndexes)
options.basicOptionIndexes->hasAlphaMap = settings.options.size(); options.basicOptionIndexes->hasAlphaMap = settings.options.size();
MaterialSettings::BuildOption(settings.options, settings.shaders, "HasAlphaMap", "HasAlphaTexture"); MaterialSettings::BuildOption(settings.options, "HasAlphaMap", "HasAlphaTexture");
// AlphaTest // AlphaTest
if (options.basicOptionIndexes) if (options.basicOptionIndexes)
options.basicOptionIndexes->alphaTest = settings.options.size(); options.basicOptionIndexes->alphaTest = settings.options.size();
MaterialSettings::BuildOption(settings.options, settings.shaders, "AlphaTest", "AlphaTest"); MaterialSettings::BuildOption(settings.options, "AlphaTest", "AlphaTest");
return settings; return settings;
} }

View File

@ -128,25 +128,24 @@ namespace Nz
void MaterialPass::UpdatePipeline() const void MaterialPass::UpdatePipeline() const
{ {
for (auto& shader : m_pipelineInfo.shaders) m_pipelineInfo.optionCount = 0;
shader.optionValues.fill(ShaderAst::NoValue{});
const auto& options = m_settings->GetOptions(); const auto& options = m_settings->GetOptions();
for (std::size_t optionIndex = 0; optionIndex < options.size(); ++optionIndex) for (std::size_t optionIndex = 0; optionIndex < options.size(); ++optionIndex)
{ {
const auto& option = options[optionIndex]; if (!std::holds_alternative<ShaderAst::NoValue>(m_optionValues[optionIndex]))
assert(option.optionIndexByShader.size() <= m_pipelineInfo.shaders.size());
for (std::size_t shaderIndex = 0; shaderIndex < option.optionIndexByShader.size(); ++shaderIndex)
{ {
if (!option.optionIndexByShader[shaderIndex].has_value()) auto& optionValue = m_pipelineInfo.optionValues[m_pipelineInfo.optionCount];
continue; optionValue.hash = options[optionIndex].hash;
optionValue.value = m_optionValues[optionIndex];
std::size_t shaderOptionIndex = *option.optionIndexByShader[shaderIndex]; m_pipelineInfo.optionCount++;
m_pipelineInfo.shaders[shaderIndex].optionValues[shaderOptionIndex] = m_optionValues[optionIndex];
} }
} }
// make option values consistent (required for hash/equality)
std::sort(m_pipelineInfo.optionValues.begin(), m_pipelineInfo.optionValues.end(), [](const auto& lhs, const auto& rhs) { return lhs.hash < rhs.hash; });
m_pipeline = MaterialPipeline::Get(m_pipelineInfo); m_pipeline = MaterialPipeline::Get(m_pipelineInfo);
m_pipelineUpdated = true; m_pipelineUpdated = true;
} }

View File

@ -49,11 +49,18 @@ namespace Nz
renderPipelineInfo.pipelineLayout = m_pipelineInfo.settings->GetRenderPipelineLayout(); renderPipelineInfo.pipelineLayout = m_pipelineInfo.settings->GetRenderPipelineLayout();
std::unordered_map<UInt32, ShaderAst::ConstantValue> optionValues;
for (std::size_t i = 0; i < m_pipelineInfo.optionCount; ++i)
{
const auto& option = m_pipelineInfo.optionValues[i];
optionValues[option.hash] = option.value;
}
for (const auto& shader : m_pipelineInfo.shaders) for (const auto& shader : m_pipelineInfo.shaders)
{ {
if (shader.uberShader) if (shader.uberShader)
{ {
UberShader::Config config{ shader.optionValues }; UberShader::Config config{ optionValues };
shader.uberShader->UpdateConfig(config, vertexBuffers); shader.uberShader->UpdateConfig(config, vertexBuffers);
renderPipelineInfo.shaderModules.push_back(shader.uberShader->Get(config)); renderPipelineInfo.shaderModules.push_back(shader.uberShader->Get(config));

View File

@ -241,28 +241,8 @@ namespace Nz
settings.shaders = options.shaders; settings.shaders = options.shaders;
for (std::shared_ptr<UberShader> uberShader : settings.shaders) for (const std::shared_ptr<UberShader>& uberShader : settings.shaders)
{ {
constexpr std::size_t InvalidOption = std::numeric_limits<std::size_t>::max();
auto FetchLocationOption = [&](const std::string& optionName)
{
const UberShader::Option* optionPtr;
if (!uberShader->HasOption(optionName, &optionPtr))
return InvalidOption;
//if (optionPtr->type != ShaderAst::ExpressionType{ ShaderAst::PrimitiveType::Int32 })
// throw std::runtime_error("Location options must be of type i32");
return optionPtr->index;
};
std::size_t positionLocationIndex = FetchLocationOption("PosLocation");
std::size_t colorLocationIndex = FetchLocationOption("ColorLocation");
std::size_t normalLocationIndex = FetchLocationOption("NormalLocation");
std::size_t tangentLocationIndex = FetchLocationOption("TangentLocation");
std::size_t uvLocationIndex = FetchLocationOption("UvLocation");
uberShader->UpdateConfigCallback([=](UberShader::Config& config, const std::vector<RenderPipelineInfo::VertexBufferData>& vertexBuffers) uberShader->UpdateConfigCallback([=](UberShader::Config& config, const std::vector<RenderPipelineInfo::VertexBufferData>& vertexBuffers)
{ {
if (vertexBuffers.empty()) if (vertexBuffers.empty())
@ -271,39 +251,29 @@ namespace Nz
const VertexDeclaration& vertexDeclaration = *vertexBuffers.front().declaration; const VertexDeclaration& vertexDeclaration = *vertexBuffers.front().declaration;
const auto& components = vertexDeclaration.GetComponents(); const auto& components = vertexDeclaration.GetComponents();
std::size_t locationIndex = 0; Int32 locationIndex = 0;
for (const auto& component : components) for (const auto& component : components)
{ {
switch (component.component) switch (component.component)
{ {
case VertexComponent::Position: case VertexComponent::Position:
if (positionLocationIndex != InvalidOption) config.optionValues[CRC32("PosLocation")] = locationIndex;
config.optionValues[positionLocationIndex] = static_cast<Int32>(locationIndex);
break; break;
case VertexComponent::Color: case VertexComponent::Color:
if (colorLocationIndex != InvalidOption) config.optionValues[CRC32("ColorLocation")] = locationIndex;
config.optionValues[colorLocationIndex] = static_cast<Int32>(locationIndex);
break; break;
case VertexComponent::Normal: case VertexComponent::Normal:
if (normalLocationIndex != InvalidOption) config.optionValues[CRC32("NormalLocation")] = locationIndex;
config.optionValues[normalLocationIndex] = static_cast<Int32>(locationIndex);
break; break;
case VertexComponent::Tangent: case VertexComponent::Tangent:
if (tangentLocationIndex != InvalidOption) config.optionValues[CRC32("TangentLocation")] = locationIndex;
config.optionValues[tangentLocationIndex] = static_cast<Int32>(locationIndex);
break; break;
case VertexComponent::TexCoord: case VertexComponent::TexCoord:
if (uvLocationIndex != InvalidOption) config.optionValues[CRC32("UvLocation")] = locationIndex;
config.optionValues[uvLocationIndex] = static_cast<Int32>(locationIndex);
break; break;
case VertexComponent::Unused: case VertexComponent::Unused:
@ -322,25 +292,25 @@ namespace Nz
if (options.phongOptionIndexes) if (options.phongOptionIndexes)
options.phongOptionIndexes->hasEmissiveMap = settings.options.size(); options.phongOptionIndexes->hasEmissiveMap = settings.options.size();
MaterialSettings::BuildOption(settings.options, settings.shaders, "HasEmissiveMap", "HasEmissiveTexture"); MaterialSettings::BuildOption(settings.options, "HasEmissiveMap", "HasEmissiveTexture");
// HasHeightMap // HasHeightMap
if (options.phongOptionIndexes) if (options.phongOptionIndexes)
options.phongOptionIndexes->hasHeightMap = settings.options.size(); options.phongOptionIndexes->hasHeightMap = settings.options.size();
MaterialSettings::BuildOption(settings.options, settings.shaders, "HasHeightMap", "HasHeightTexture"); MaterialSettings::BuildOption(settings.options, "HasHeightMap", "HasHeightTexture");
// HasNormalMap // HasNormalMap
if (options.phongOptionIndexes) if (options.phongOptionIndexes)
options.phongOptionIndexes->hasNormalMap = settings.options.size(); options.phongOptionIndexes->hasNormalMap = settings.options.size();
MaterialSettings::BuildOption(settings.options, settings.shaders, "HasNormalMap", "HasNormalTexture"); MaterialSettings::BuildOption(settings.options, "HasNormalMap", "HasNormalTexture");
// HasSpecularMap // HasSpecularMap
if (options.phongOptionIndexes) if (options.phongOptionIndexes)
options.phongOptionIndexes->hasSpecularMap = settings.options.size(); options.phongOptionIndexes->hasSpecularMap = settings.options.size();
MaterialSettings::BuildOption(settings.options, settings.shaders, "HasSpecularMap", "HasSpecularTexture"); MaterialSettings::BuildOption(settings.options, "HasSpecularMap", "HasSpecularTexture");
return settings; return settings;
} }

View File

@ -37,7 +37,7 @@ namespace Nz
//TODO: Check optionType //TODO: Check optionType
m_optionIndexByName[optionName] = Option{ m_optionIndexByName[optionName] = Option{
optionCount CRC32(optionName)
}; };
optionCount++; optionCount++;
@ -48,9 +48,6 @@ namespace Nz
if ((m_shaderStages & supportedStageType) != m_shaderStages) if ((m_shaderStages & supportedStageType) != m_shaderStages)
throw std::runtime_error("shader doesn't support all required shader stages"); throw std::runtime_error("shader doesn't support all required shader stages");
if (optionCount >= MaximumOptionValue)
throw std::runtime_error("Too many shader options (at most " + std::to_string(MaximumOptionValue) + " are supported)");
} }
const std::shared_ptr<ShaderModule>& UberShader::Get(const Config& config) const std::shared_ptr<ShaderModule>& UberShader::Get(const Config& config)
@ -59,12 +56,7 @@ namespace Nz
if (it == m_combinations.end()) if (it == m_combinations.end())
{ {
ShaderWriter::States states; ShaderWriter::States states;
states.optionValues = config.optionValues;
for (std::size_t i = 0; i < MaximumOptionValue; ++i)
{
if (!std::holds_alternative<ShaderAst::NoValue>(config.optionValues[i]))
states.optionValues[i] = config.optionValues[i];
}
std::shared_ptr<ShaderModule> stage = Graphics::Instance()->GetRenderDevice()->InstantiateShaderModule(m_shaderStages, *m_shaderModule, std::move(states)); std::shared_ptr<ShaderModule> stage = Graphics::Instance()->GetRenderDevice()->InstantiateShaderModule(m_shaderStages, *m_shaderModule, std::move(states));

View File

@ -122,7 +122,6 @@ namespace Nz::ShaderAst
std::array<DeclareFunctionStatement*, ShaderStageTypeCount> entryFunctions = {}; std::array<DeclareFunctionStatement*, ShaderStageTypeCount> entryFunctions = {};
std::optional<DependencyCheckerVisitor::UsageSet> importUsage; std::optional<DependencyCheckerVisitor::UsageSet> importUsage;
std::size_t nextOptionIndex = 0;
std::vector<Identifier> identifiersInScope; std::vector<Identifier> identifiersInScope;
std::vector<PendingFunction> pendingFunctions; std::vector<PendingFunction> pendingFunctions;
std::vector<Scope> scopes; std::vector<Scope> scopes;
@ -951,6 +950,8 @@ namespace Nz::ShaderAst
throw AstError{ "options must be declared outside of functions" }; throw AstError{ "options must be declared outside of functions" };
auto clone = static_unique_pointer_cast<DeclareOptionStatement>(AstCloner::Clone(node)); auto clone = static_unique_pointer_cast<DeclareOptionStatement>(AstCloner::Clone(node));
if (clone->optName.empty())
throw AstError{ "empty option name" };
ExpressionType resolvedType = ResolveType(clone->optType); ExpressionType resolvedType = ResolveType(clone->optType);
@ -959,12 +960,12 @@ namespace Nz::ShaderAst
clone->optType = std::move(resolvedType); clone->optType = std::move(resolvedType);
std::size_t optionIndex = m_context->nextOptionIndex++; UInt32 optionHash = CRC32(reinterpret_cast<const UInt8*>(clone->optName.data()), clone->optName.size());
if (m_context->importUsage.has_value()) if (m_context->importUsage.has_value())
clone->hidden = true; clone->hidden = true;
if (auto optionValueIt = m_context->options.optionValues.find(optionIndex); optionValueIt != m_context->options.optionValues.end()) if (auto optionValueIt = m_context->options.optionValues.find(optionHash); optionValueIt != m_context->options.optionValues.end())
clone->optIndex = RegisterConstant(clone->optName, optionValueIt->second, clone->hidden.value_or(false), clone->optIndex); clone->optIndex = RegisterConstant(clone->optName, optionValueIt->second, clone->hidden.value_or(false), clone->optIndex);
else if (clone->defaultValue) else if (clone->defaultValue)
clone->optIndex = RegisterConstant(clone->optName, ComputeConstantValue(*clone->defaultValue), clone->hidden.value_or(false), clone->optIndex); clone->optIndex = RegisterConstant(clone->optName, ComputeConstantValue(*clone->defaultValue), clone->hidden.value_or(false), clone->optIndex);

View File

@ -139,7 +139,6 @@ namespace Nz
std::optional<ShaderStageType> stage; std::optional<ShaderStageType> stage;
std::stringstream stream; std::stringstream stream;
std::unordered_map<std::size_t, ShaderAst::ConstantValue> optionValues;
std::unordered_map<std::size_t, ShaderAst::StructDescription*> structs; std::unordered_map<std::size_t, ShaderAst::StructDescription*> structs;
std::unordered_map<std::size_t, std::string> variableNames; std::unordered_map<std::size_t, std::string> variableNames;
std::vector<InOutField> inputFields; std::vector<InOutField> inputFields;
@ -155,7 +154,6 @@ namespace Nz
std::string GlslWriter::Generate(std::optional<ShaderStageType> shaderStage, const ShaderAst::Module& module, const BindingMapping& bindingMapping, const States& states) std::string GlslWriter::Generate(std::optional<ShaderStageType> shaderStage, const ShaderAst::Module& module, const BindingMapping& bindingMapping, const States& states)
{ {
State state(bindingMapping); State state(bindingMapping);
state.optionValues = states.optionValues;
state.stage = shaderStage; state.stage = shaderStage;
m_currentState = &state; m_currentState = &state;
@ -210,7 +208,7 @@ namespace Nz
return s_flipYUniformName; return s_flipYUniformName;
} }
ShaderAst::ModulePtr GlslWriter::Sanitize(const ShaderAst::Module& module, std::unordered_map<std::size_t, ShaderAst::ConstantValue> optionValues, std::string* error) ShaderAst::ModulePtr GlslWriter::Sanitize(const ShaderAst::Module& module, std::unordered_map<UInt32, ShaderAst::ConstantValue> optionValues, std::string* error)
{ {
// Always sanitize for reserved identifiers // Always sanitize for reserved identifiers
ShaderAst::SanitizeVisitor::Options options; ShaderAst::SanitizeVisitor::Options options;

View File

@ -59,7 +59,10 @@ void CodeOutputWidget::Refresh()
Nz::ShaderWriter::States states; Nz::ShaderWriter::States states;
for (std::size_t i = 0; i < m_shaderGraph.GetOptionCount(); ++i) for (std::size_t i = 0; i < m_shaderGraph.GetOptionCount(); ++i)
states.optionValues[i] = m_shaderGraph.IsOptionEnabled(i); {
const auto& option = m_shaderGraph.GetOption(i);
states.optionValues[Nz::CRC32(option.name)] = m_shaderGraph.IsOptionEnabled(i);
}
Nz::ShaderAst::ModulePtr shaderModule = m_shaderGraph.ToModule(); Nz::ShaderAst::ModulePtr shaderModule = m_shaderGraph.ToModule();

View File

@ -66,7 +66,7 @@ fn main()
WHEN("Enabling option") WHEN("Enabling option")
{ {
options.optionValues[0] = true; options.optionValues[Nz::CRC32("UseInt")] = true;
ExpectOutput(*shaderModule, options, R"( ExpectOutput(*shaderModule, options, R"(
struct inputStruct struct inputStruct
@ -90,7 +90,7 @@ fn main()
WHEN("Disabling option") WHEN("Disabling option")
{ {
options.optionValues[0] = false; options.optionValues[Nz::CRC32("UseInt")] = false;
ExpectOutput(*shaderModule, options, R"( ExpectOutput(*shaderModule, options, R"(
struct inputStruct struct inputStruct