Handle shader options of any type
This commit is contained in:
@@ -160,19 +160,19 @@ namespace Nz
|
||||
if (optionIndexes)
|
||||
optionIndexes->hasDiffuseMap = settings.options.size();
|
||||
|
||||
MaterialSettings::BuildOption(settings.options, settings.shaders, "HasDiffuseMap", "HAS_DIFFUSE_TEXTURE");
|
||||
MaterialSettings::BuildOption(settings.options, settings.shaders, "HasDiffuseMap", "HasDiffuseTexture");
|
||||
|
||||
// HasAlphaMap
|
||||
if (optionIndexes)
|
||||
optionIndexes->hasAlphaMap = settings.options.size();
|
||||
|
||||
MaterialSettings::BuildOption(settings.options, settings.shaders, "HasAlphaMap", "HAS_ALPHA_TEXTURE");
|
||||
MaterialSettings::BuildOption(settings.options, settings.shaders, "HasAlphaMap", "HasAlphaTexture");
|
||||
|
||||
// AlphaTest
|
||||
if (optionIndexes)
|
||||
optionIndexes->alphaTest = settings.options.size();
|
||||
|
||||
MaterialSettings::BuildOption(settings.options, settings.shaders, "AlphaTest", "ALPHA_TEST");
|
||||
MaterialSettings::BuildOption(settings.options, settings.shaders, "AlphaTest", "AlphaTest");
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ namespace Nz
|
||||
*/
|
||||
MaterialPass::MaterialPass(std::shared_ptr<const MaterialSettings> settings) :
|
||||
m_settings(std::move(settings)),
|
||||
m_enabledOptions(0),
|
||||
m_forceCommandBufferRegeneration(false),
|
||||
m_pipelineUpdated(false),
|
||||
m_shaderBindingUpdated(false)
|
||||
@@ -99,23 +98,20 @@ namespace Nz
|
||||
void MaterialPass::UpdatePipeline() const
|
||||
{
|
||||
for (auto& shader : m_pipelineInfo.shaders)
|
||||
shader.enabledOptions = 0;
|
||||
shader.optionValues.fill(ShaderAst::NoValue{});
|
||||
|
||||
const auto& options = m_settings->GetOptions();
|
||||
for (std::size_t optionIndex = 0; optionIndex < options.size(); ++optionIndex)
|
||||
{
|
||||
if (TestBit<UInt64>(m_enabledOptions, optionIndex))
|
||||
const auto& option = options[optionIndex];
|
||||
assert(option.optionIndexByShader.size() <= m_pipelineInfo.shaders.size());
|
||||
|
||||
for (std::size_t shaderIndex = 0; shaderIndex < option.optionIndexByShader.size(); ++shaderIndex)
|
||||
{
|
||||
for (auto& shader : m_pipelineInfo.shaders)
|
||||
{
|
||||
ShaderStageTypeFlags supportedStages = shader.uberShader->GetSupportedStages();
|
||||
for (std::size_t i = 0; i < ShaderStageTypeCount; ++i)
|
||||
{
|
||||
ShaderStageType shaderStage = static_cast<ShaderStageType>(i);
|
||||
if (supportedStages & shaderStage)
|
||||
shader.enabledOptions |= options[optionIndex].enabledOptions[i];
|
||||
}
|
||||
}
|
||||
if (!option.optionIndexByShader[shaderIndex].has_value())
|
||||
continue;
|
||||
|
||||
m_pipelineInfo.shaders[shaderIndex].optionValues[optionIndex] = m_optionValues[optionIndex];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,14 +45,18 @@ namespace Nz
|
||||
}
|
||||
|
||||
RenderPipelineInfo renderPipelineInfo;
|
||||
static_cast<RenderStates&>(renderPipelineInfo).operator=(m_pipelineInfo); // Not the line I4m the most proud of
|
||||
static_cast<RenderStates&>(renderPipelineInfo).operator=(m_pipelineInfo); // Not the line I'm the most proud of
|
||||
|
||||
renderPipelineInfo.pipelineLayout = m_pipelineInfo.settings->GetRenderPipelineLayout();
|
||||
|
||||
for (const auto& shader : m_pipelineInfo.shaders)
|
||||
{
|
||||
if (shader.uberShader)
|
||||
renderPipelineInfo.shaderModules.push_back(shader.uberShader->Get(shader.enabledOptions));
|
||||
{
|
||||
UberShader::Config config{ shader.optionValues };
|
||||
|
||||
renderPipelineInfo.shaderModules.push_back(shader.uberShader->Get(config));
|
||||
}
|
||||
}
|
||||
|
||||
renderPipelineInfo.vertexBuffers = vertexBuffers;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
option HAS_DIFFUSE_TEXTURE: bool;
|
||||
option HAS_ALPHA_TEXTURE: bool;
|
||||
option ALPHA_TEST: bool;
|
||||
option HasDiffuseTexture: bool = false;
|
||||
option HasAlphaTexture: bool = false;
|
||||
option AlphaTest: bool = false;
|
||||
|
||||
const HasUV = HAS_DIFFUSE_TEXTURE || HAS_ALPHA_TEXTURE;
|
||||
const HasUV = HasDiffuseTexture || HasAlphaTexture;
|
||||
|
||||
[layout(std140)]
|
||||
struct BasicSettings
|
||||
@@ -56,15 +56,15 @@ struct FragOut
|
||||
fn main(input: FragIn) -> FragOut
|
||||
{
|
||||
let diffuseColor = settings.DiffuseColor;
|
||||
const if (HAS_DIFFUSE_TEXTURE)
|
||||
const if (HasDiffuseTexture)
|
||||
// TODO: diffuseColor *= MaterialDiffuseMap.Sample(input.uv)
|
||||
diffuseColor = diffuseColor * MaterialDiffuseMap.Sample(input.uv);
|
||||
|
||||
const if (HAS_ALPHA_TEXTURE)
|
||||
const if (HasAlphaTexture)
|
||||
// TODO: diffuseColor.w *= MaterialAlphaMap.Sample(input.uv)).x
|
||||
diffuseColor = vec4<f32>(diffuseColor.x, diffuseColor.y, diffuseColor.z, MaterialAlphaMap.Sample(input.uv).x * diffuseColor.w);
|
||||
|
||||
const if (ALPHA_TEST)
|
||||
const if (AlphaTest)
|
||||
{
|
||||
if (diffuseColor.w < settings.AlphaThreshold)
|
||||
discard;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
option HAS_DIFFUSE_TEXTURE: bool;
|
||||
option HAS_ALPHA_TEXTURE: bool;
|
||||
option ALPHA_TEST: bool;
|
||||
option HasDiffuseTexture: bool = false;
|
||||
option HasAlphaTexture: bool = false;
|
||||
option AlphaTest: bool = false;
|
||||
|
||||
const HasUV = ALPHA_TEST && (HAS_DIFFUSE_TEXTURE || HAS_ALPHA_TEXTURE);
|
||||
const HasUV = AlphaTest && (HasDiffuseTexture || HasAlphaTexture);
|
||||
|
||||
[layout(std140)]
|
||||
struct BasicSettings
|
||||
@@ -47,15 +47,15 @@ struct FragIn
|
||||
[location(0), cond(HasUV)] uv: vec2<f32>
|
||||
}
|
||||
|
||||
[entry(frag), cond(ALPHA_TEST)]
|
||||
[entry(frag), cond(AlphaTest)]
|
||||
fn main(input: FragIn)
|
||||
{
|
||||
let alpha = settings.DiffuseColor.a;
|
||||
const if (HAS_DIFFUSE_TEXTURE)
|
||||
const if (HasDiffuseTexture)
|
||||
// TODO: alpha *= MaterialDiffuseMap.Sample(input.uv).a;
|
||||
alpha = alpha * MaterialDiffuseMap.Sample(input.uv).a;
|
||||
|
||||
const if (HAS_ALPHA_TEXTURE)
|
||||
const if (HasAlphaTexture)
|
||||
// TODO: alpha *= MaterialAlphaMap.Sample(input.uv).x
|
||||
alpha = alpha * MaterialAlphaMap.Sample(input.uv).x;
|
||||
|
||||
@@ -64,7 +64,7 @@ fn main(input: FragIn)
|
||||
}
|
||||
|
||||
// Dummy fragment shader (TODO: Add a way to delete stage?)
|
||||
[entry(frag), cond(!ALPHA_TEST)]
|
||||
[entry(frag), cond(!AlphaTest)]
|
||||
fn main() {}
|
||||
|
||||
// Vertex stage
|
||||
|
||||
@@ -33,7 +33,11 @@ namespace Nz
|
||||
|
||||
callbacks.onOptionDeclaration = [&](const std::string& optionName, const ShaderAst::ExpressionType& optionType)
|
||||
{
|
||||
m_optionIndexByName[optionName] = optionCount;
|
||||
m_optionIndexByName[optionName] = Option{
|
||||
optionCount,
|
||||
optionType
|
||||
};
|
||||
|
||||
optionCount++;
|
||||
};
|
||||
|
||||
@@ -43,36 +47,26 @@ namespace Nz
|
||||
if (m_shaderStages & supportedStageType != m_shaderStages)
|
||||
throw std::runtime_error("shader doesn't support all required shader stages");
|
||||
|
||||
if (optionCount >= 64)
|
||||
throw std::runtime_error("Too many conditions");
|
||||
|
||||
m_combinationMask = std::numeric_limits<UInt64>::max();
|
||||
m_combinationMask <<= optionCount;
|
||||
m_combinationMask = ~m_combinationMask;
|
||||
if (optionCount >= MaximumOptionValue)
|
||||
throw std::runtime_error("Too many shader options (at most " + std::to_string(MaximumOptionValue) + " are supported)");
|
||||
}
|
||||
|
||||
UInt64 UberShader::GetOptionFlagByName(const std::string& optionName) const
|
||||
const std::shared_ptr<ShaderModule>& UberShader::Get(const Config& config)
|
||||
{
|
||||
auto it = m_optionIndexByName.find(optionName);
|
||||
if (it == m_optionIndexByName.end())
|
||||
return 0;
|
||||
|
||||
return SetBit<UInt64>(0, it->second);
|
||||
}
|
||||
|
||||
const std::shared_ptr<ShaderModule>& UberShader::Get(UInt64 combination)
|
||||
{
|
||||
combination &= m_combinationMask;
|
||||
|
||||
auto it = m_combinations.find(combination);
|
||||
auto it = m_combinations.find(config);
|
||||
if (it == m_combinations.end())
|
||||
{
|
||||
ShaderWriter::States states;
|
||||
states.enabledOptions = combination;
|
||||
|
||||
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_shaderAst, std::move(states));
|
||||
|
||||
it = m_combinations.emplace(combination, std::move(stage)).first;
|
||||
it = m_combinations.emplace(config, std::move(stage)).first;
|
||||
}
|
||||
|
||||
return it->second;
|
||||
|
||||
@@ -116,7 +116,7 @@ namespace Nz::ShaderAst
|
||||
StatementPtr AstCloner::Clone(DeclareOptionStatement& node)
|
||||
{
|
||||
auto clone = std::make_unique<DeclareOptionStatement>();
|
||||
clone->initialValue = CloneExpression(node.initialValue);
|
||||
clone->defaultValue = CloneExpression(node.defaultValue);
|
||||
clone->optIndex = node.optIndex;
|
||||
clone->optName = node.optName;
|
||||
clone->optType = node.optType;
|
||||
|
||||
@@ -697,7 +697,9 @@ namespace Nz::ShaderAst
|
||||
{
|
||||
using T = std::decay_t<decltype(arg)>;
|
||||
|
||||
if constexpr (std::is_same_v<T, bool> || std::is_same_v<T, float> || std::is_same_v<T, Int32> || std::is_same_v<T, UInt32>)
|
||||
if constexpr (std::is_same_v<T, NoValue>)
|
||||
throw std::runtime_error("invalid type (value expected)");
|
||||
else if constexpr (std::is_same_v<T, bool> || std::is_same_v<T, float> || std::is_same_v<T, Int32> || std::is_same_v<T, UInt32>)
|
||||
constantValues.push_back(arg);
|
||||
else if constexpr (std::is_same_v<T, Vector2f> || std::is_same_v<T, Vector2i32>)
|
||||
{
|
||||
@@ -815,9 +817,6 @@ namespace Nz::ShaderAst
|
||||
|
||||
ExpressionPtr AstOptimizer::Clone(ConditionalExpression& node)
|
||||
{
|
||||
if (!m_options.enabledOptions)
|
||||
return AstCloner::Clone(node);
|
||||
|
||||
auto cond = CloneExpression(node.condition);
|
||||
if (cond->GetType() != NodeType::ConstantValueExpression)
|
||||
throw std::runtime_error("conditional expression condition must be a constant expression");
|
||||
@@ -884,9 +883,6 @@ namespace Nz::ShaderAst
|
||||
|
||||
StatementPtr AstOptimizer::Clone(ConditionalStatement& node)
|
||||
{
|
||||
if (!m_options.enabledOptions)
|
||||
return AstCloner::Clone(node);
|
||||
|
||||
auto cond = CloneExpression(node.condition);
|
||||
if (cond->GetType() != NodeType::ConstantValueExpression)
|
||||
throw std::runtime_error("conditional expression condition must be a constant expression");
|
||||
|
||||
@@ -134,8 +134,8 @@ namespace Nz::ShaderAst
|
||||
|
||||
void AstRecursiveVisitor::Visit(DeclareOptionStatement& node)
|
||||
{
|
||||
if (node.initialValue)
|
||||
node.initialValue->Visit(*this);
|
||||
if (node.defaultValue)
|
||||
node.defaultValue->Visit(*this);
|
||||
}
|
||||
|
||||
void AstRecursiveVisitor::Visit(DeclareStructStatement& /*node*/)
|
||||
|
||||
@@ -140,19 +140,20 @@ namespace Nz::ShaderAst
|
||||
Value(value);
|
||||
};
|
||||
|
||||
static_assert(std::variant_size_v<decltype(node.value)> == 10);
|
||||
static_assert(std::variant_size_v<decltype(node.value)> == 11);
|
||||
switch (typeIndex)
|
||||
{
|
||||
case 0: SerializeValue(bool()); break;
|
||||
case 1: SerializeValue(float()); break;
|
||||
case 2: SerializeValue(Int32()); break;
|
||||
case 3: SerializeValue(UInt32()); break;
|
||||
case 4: SerializeValue(Vector2f()); break;
|
||||
case 5: SerializeValue(Vector3f()); break;
|
||||
case 6: SerializeValue(Vector4f()); break;
|
||||
case 7: SerializeValue(Vector2i32()); break;
|
||||
case 8: SerializeValue(Vector3i32()); break;
|
||||
case 9: SerializeValue(Vector4i32()); break;
|
||||
case 0: break;
|
||||
case 1: SerializeValue(bool()); break;
|
||||
case 2: SerializeValue(float()); break;
|
||||
case 3: SerializeValue(Int32()); break;
|
||||
case 4: SerializeValue(UInt32()); break;
|
||||
case 5: SerializeValue(Vector2f()); break;
|
||||
case 6: SerializeValue(Vector3f()); break;
|
||||
case 7: SerializeValue(Vector4f()); break;
|
||||
case 8: SerializeValue(Vector2i32()); break;
|
||||
case 9: SerializeValue(Vector3i32()); break;
|
||||
case 10: SerializeValue(Vector4i32()); break;
|
||||
default: throw std::runtime_error("unexpected data type");
|
||||
}
|
||||
}
|
||||
@@ -261,7 +262,7 @@ namespace Nz::ShaderAst
|
||||
OptVal(node.optIndex);
|
||||
Value(node.optName);
|
||||
Type(node.optType);
|
||||
Node(node.initialValue);
|
||||
Node(node.defaultValue);
|
||||
}
|
||||
|
||||
void AstSerializerBase::Serialize(DeclareStructStatement& node)
|
||||
|
||||
@@ -13,7 +13,9 @@ namespace Nz::ShaderAst
|
||||
{
|
||||
using T = std::decay_t<decltype(arg)>;
|
||||
|
||||
if constexpr (std::is_same_v<T, bool>)
|
||||
if constexpr (std::is_same_v<T, NoValue>)
|
||||
return NoType{};
|
||||
else if constexpr (std::is_same_v<T, bool>)
|
||||
return PrimitiveType::Boolean;
|
||||
else if constexpr (std::is_same_v<T, float>)
|
||||
return PrimitiveType::Float32;
|
||||
|
||||
@@ -583,6 +583,9 @@ namespace Nz::ShaderAst
|
||||
|
||||
ExpressionPtr SanitizeVisitor::Clone(ConstantValueExpression& node)
|
||||
{
|
||||
if (std::holds_alternative<NoValue>(node.value))
|
||||
throw std::runtime_error("expected a value");
|
||||
|
||||
auto clone = static_unique_pointer_cast<ConstantValueExpression>(AstCloner::Clone(node));
|
||||
clone->cachedExpressionType = GetExpressionType(clone->value);
|
||||
|
||||
@@ -980,12 +983,17 @@ namespace Nz::ShaderAst
|
||||
auto clone = static_unique_pointer_cast<DeclareOptionStatement>(AstCloner::Clone(node));
|
||||
clone->optType = ResolveType(clone->optType);
|
||||
|
||||
if (clone->initialValue && clone->optType != GetExpressionType(*clone->initialValue))
|
||||
throw AstError{ "option " + clone->optName + " initial expression must be of the same type than the option" };
|
||||
if (clone->defaultValue && clone->optType != GetExpressionType(*clone->defaultValue))
|
||||
throw AstError{ "option " + clone->optName + " default expression must be of the same type than the option" };
|
||||
|
||||
std::size_t optionIndex = m_context->nextOptionIndex++;
|
||||
|
||||
clone->optIndex = RegisterConstant(clone->optName, TestBit(m_context->options.enabledOptions, optionIndex));
|
||||
if (auto optionValueIt = m_context->options.optionValues.find(optionIndex); optionValueIt != m_context->options.optionValues.end())
|
||||
clone->optIndex = RegisterConstant(clone->optName, optionValueIt->second);
|
||||
else if (clone->defaultValue)
|
||||
clone->optIndex = RegisterConstant(clone->optName, ComputeConstantValue(*clone->defaultValue));
|
||||
else
|
||||
throw AstError{ "missing option " + clone->optName + " value (has no default value)" };
|
||||
|
||||
if (m_context->options.removeOptionDeclaration)
|
||||
return ShaderBuilder::NoOp();
|
||||
@@ -1186,8 +1194,6 @@ namespace Nz::ShaderAst
|
||||
return m_context->constantValues[constantId];
|
||||
};
|
||||
|
||||
optimizerOptions.enabledOptions = m_context->options.enabledOptions;
|
||||
|
||||
// Run optimizer on constant value to hopefully retrieve a single constant value
|
||||
return static_unique_pointer_cast<T>(ShaderAst::Optimize(node, optimizerOptions));
|
||||
}
|
||||
|
||||
@@ -107,7 +107,6 @@ namespace Nz
|
||||
std::optional<ShaderStageType> selectedStage;
|
||||
std::unordered_map<std::size_t, FunctionData> functions;
|
||||
ShaderAst::DeclareFunctionStatement* entryPoint = nullptr;
|
||||
UInt64 enabledOptions = 0;
|
||||
};
|
||||
|
||||
struct Builtin
|
||||
@@ -139,6 +138,7 @@ namespace Nz
|
||||
|
||||
std::optional<ShaderStageType> stage;
|
||||
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, std::string> variableNames;
|
||||
std::vector<InOutField> inputFields;
|
||||
@@ -147,7 +147,6 @@ namespace Nz
|
||||
const GlslWriter::BindingMapping& bindingMapping;
|
||||
PreVisitor previsitor;
|
||||
const States* states = nullptr;
|
||||
UInt64 enabledOptions = 0;
|
||||
bool isInEntryPoint = false;
|
||||
unsigned int indentLevel = 0;
|
||||
};
|
||||
@@ -155,7 +154,7 @@ namespace Nz
|
||||
std::string GlslWriter::Generate(std::optional<ShaderStageType> shaderStage, ShaderAst::Statement& shader, const BindingMapping& bindingMapping, const States& states)
|
||||
{
|
||||
State state(bindingMapping);
|
||||
state.enabledOptions = states.enabledOptions;
|
||||
state.optionValues = states.optionValues;
|
||||
state.stage = shaderStage;
|
||||
|
||||
m_currentState = &state;
|
||||
@@ -168,7 +167,7 @@ namespace Nz
|
||||
ShaderAst::Statement* targetAst;
|
||||
if (!states.sanitized)
|
||||
{
|
||||
sanitizedAst = Sanitize(shader, states.enabledOptions);
|
||||
sanitizedAst = Sanitize(shader, states.optionValues);
|
||||
targetAst = sanitizedAst.get();
|
||||
}
|
||||
else
|
||||
@@ -182,7 +181,6 @@ namespace Nz
|
||||
targetAst = optimizedAst.get();
|
||||
}
|
||||
|
||||
state.previsitor.enabledOptions = states.enabledOptions;
|
||||
state.previsitor.selectedStage = shaderStage;
|
||||
targetAst->Visit(state.previsitor);
|
||||
|
||||
@@ -203,11 +201,11 @@ namespace Nz
|
||||
return s_flipYUniformName;
|
||||
}
|
||||
|
||||
ShaderAst::StatementPtr GlslWriter::Sanitize(ShaderAst::Statement& ast, UInt64 enabledOptions, std::string* error)
|
||||
ShaderAst::StatementPtr GlslWriter::Sanitize(ShaderAst::Statement& ast, std::unordered_map<std::size_t, ShaderAst::ConstantValue> optionValues, std::string* error)
|
||||
{
|
||||
// Always sanitize for reserved identifiers
|
||||
ShaderAst::SanitizeVisitor::Options options;
|
||||
options.enabledOptions = enabledOptions;
|
||||
options.optionValues = std::move(optionValues);
|
||||
options.makeVariableNameUnique = true;
|
||||
options.reservedIdentifiers = {
|
||||
// All reserved GLSL keywords as of GLSL ES 3.2
|
||||
@@ -837,7 +835,9 @@ namespace Nz
|
||||
if constexpr (std::is_same_v<T, Vector2i32> || std::is_same_v<T, Vector3i32> || std::is_same_v<T, Vector4i32>)
|
||||
Append("i"); //< for ivec
|
||||
|
||||
if constexpr (std::is_same_v<T, bool>)
|
||||
if constexpr (std::is_same_v<T, ShaderAst::NoValue>)
|
||||
throw std::runtime_error("invalid type (value expected)");
|
||||
else if constexpr (std::is_same_v<T, bool>)
|
||||
Append((arg) ? "true" : "false");
|
||||
else if constexpr (std::is_same_v<T, float> || std::is_same_v<T, Int32> || std::is_same_v<T, UInt32>)
|
||||
Append(std::to_string(arg));
|
||||
|
||||
@@ -643,7 +643,9 @@ namespace Nz
|
||||
{
|
||||
using T = std::decay_t<decltype(arg)>;
|
||||
|
||||
if constexpr (std::is_same_v<T, bool>)
|
||||
if constexpr (std::is_same_v<T, ShaderAst::NoValue>)
|
||||
throw std::runtime_error("invalid type (value expected)");
|
||||
else if constexpr (std::is_same_v<T, bool>)
|
||||
Append((arg) ? "true" : "false");
|
||||
else if constexpr (std::is_same_v<T, float> || std::is_same_v<T, Int32> || std::is_same_v<T, UInt32>)
|
||||
Append(std::to_string(arg));
|
||||
@@ -733,10 +735,10 @@ namespace Nz
|
||||
RegisterConstant(*node.optIndex, node.optName);
|
||||
|
||||
Append("option ", node.optName, ": ", node.optType);
|
||||
if (node.initialValue)
|
||||
if (node.defaultValue)
|
||||
{
|
||||
Append(" = ");
|
||||
node.initialValue->Visit(*this);
|
||||
node.defaultValue->Visit(*this);
|
||||
}
|
||||
|
||||
Append(";");
|
||||
|
||||
@@ -418,7 +418,9 @@ namespace Nz
|
||||
{
|
||||
using T = std::decay_t<decltype(arg)>;
|
||||
|
||||
if constexpr (std::is_same_v<T, bool>)
|
||||
if constexpr (std::is_same_v<T, ShaderAst::NoValue>)
|
||||
throw std::runtime_error("invalid type (value expected)");
|
||||
else if constexpr (std::is_same_v<T, bool>)
|
||||
return ConstantBool{ arg };
|
||||
else if constexpr (std::is_same_v<T, float> || std::is_same_v<T, Int32> || std::is_same_v<T, UInt32>)
|
||||
return ConstantScalar{ arg };
|
||||
|
||||
@@ -463,7 +463,7 @@ namespace Nz
|
||||
if (!states.sanitized)
|
||||
{
|
||||
ShaderAst::SanitizeVisitor::Options options;
|
||||
options.enabledOptions = states.enabledOptions;
|
||||
options.optionValues = states.optionValues;
|
||||
|
||||
sanitizedAst = ShaderAst::Sanitize(shader, options);
|
||||
targetAst = sanitizedAst.get();
|
||||
@@ -653,11 +653,6 @@ namespace Nz
|
||||
return m_currentState->constantTypeCache.GetId(*m_currentState->constantTypeCache.BuildType(type));
|
||||
}
|
||||
|
||||
bool SpirvWriter::IsOptionEnabled(std::size_t optionIndex) const
|
||||
{
|
||||
return TestBit<Nz::UInt64>(m_context.states->enabledOptions, optionIndex);
|
||||
}
|
||||
|
||||
UInt32 SpirvWriter::RegisterConstant(const ShaderAst::ConstantValue& value)
|
||||
{
|
||||
return m_currentState->constantTypeCache.Register(*m_currentState->constantTypeCache.BuildConstant(value));
|
||||
|
||||
@@ -55,29 +55,24 @@ void CodeOutputWidget::Refresh()
|
||||
{
|
||||
try
|
||||
{
|
||||
Nz::UInt64 enabledOptions = 0;
|
||||
Nz::ShaderWriter::States states;
|
||||
|
||||
for (std::size_t i = 0; i < m_shaderGraph.GetOptionCount(); ++i)
|
||||
{
|
||||
if (m_shaderGraph.IsOptionEnabled(i))
|
||||
enabledOptions = Nz::SetBit<Nz::UInt64>(enabledOptions, i);
|
||||
}
|
||||
states.optionValues[i] = m_shaderGraph.IsOptionEnabled(i);
|
||||
|
||||
Nz::ShaderAst::StatementPtr shaderAst = m_shaderGraph.ToAst();
|
||||
|
||||
if (m_optimisationCheckbox->isChecked())
|
||||
{
|
||||
shaderAst = Nz::ShaderAst::Sanitize(*shaderAst);
|
||||
Nz::ShaderAst::SanitizeVisitor::Options sanitizeOptions;
|
||||
sanitizeOptions.optionValues = states.optionValues;
|
||||
|
||||
Nz::ShaderAst::AstOptimizer::Options optimOptions;
|
||||
optimOptions.enabledOptions = enabledOptions;
|
||||
shaderAst = Nz::ShaderAst::Sanitize(*shaderAst, sanitizeOptions);
|
||||
|
||||
Nz::ShaderAst::AstOptimizer optimiser;
|
||||
shaderAst = optimiser.Optimise(*shaderAst, optimOptions);
|
||||
shaderAst = optimiser.Optimise(*shaderAst);
|
||||
}
|
||||
|
||||
Nz::ShaderWriter::States states;
|
||||
states.enabledOptions = enabledOptions;
|
||||
|
||||
std::string output;
|
||||
OutputLanguage outputLang = static_cast<OutputLanguage>(m_outputLang->currentIndex());
|
||||
switch (outputLang)
|
||||
|
||||
Reference in New Issue
Block a user