Shader: Add export attribute for structs ([export])

This commit is contained in:
Jérôme Leclercq 2022-03-04 18:26:18 +01:00
parent a2f4f3c802
commit ca83f363a3
6 changed files with 40 additions and 15 deletions

View File

@ -33,6 +33,7 @@ namespace Nz
DepthWrite, //< Depth write mode (function only) - has argument type DepthWrite, //< Depth write mode (function only) - has argument type
EarlyFragmentTests, //< Entry point (function only) - has argument on/off EarlyFragmentTests, //< Entry point (function only) - has argument on/off
Entry, //< Entry point (function only) - has argument type Entry, //< Entry point (function only) - has argument type
Export, //< Exported (external block, function and struct only)
Layout, //< Struct layout (struct only) - has argument style Layout, //< Struct layout (struct only) - has argument style
Location, //< Location (struct member only) - has argument index Location, //< Location (struct member only) - has argument index
LangVersion, //< NZSL version - has argument version string LangVersion, //< NZSL version - has argument version string

View File

@ -249,9 +249,9 @@ namespace Nz::ShaderAst
NodeType GetType() const override; NodeType GetType() const override;
void Visit(AstStatementVisitor& visitor) override; void Visit(AstStatementVisitor& visitor) override;
ExpressionValue<ExpressionType> type;
std::optional<std::size_t> constIndex; std::optional<std::size_t> constIndex;
std::string name; std::string name;
ExpressionValue<ExpressionType> type;
ExpressionPtr expression; ExpressionPtr expression;
}; };
@ -262,11 +262,11 @@ namespace Nz::ShaderAst
struct ExternalVar struct ExternalVar
{ {
std::optional<std::size_t> varIndex;
std::string name;
ExpressionValue<UInt32> bindingIndex; ExpressionValue<UInt32> bindingIndex;
ExpressionValue<UInt32> bindingSet; ExpressionValue<UInt32> bindingSet;
ExpressionValue<ExpressionType> type; ExpressionValue<ExpressionType> type;
std::optional<std::size_t> varIndex;
std::string name;
}; };
ExpressionValue<UInt32> bindingSet; ExpressionValue<UInt32> bindingSet;
@ -284,15 +284,15 @@ namespace Nz::ShaderAst
ExpressionValue<ExpressionType> type; ExpressionValue<ExpressionType> type;
}; };
ExpressionValue<DepthWriteMode> depthWrite;
ExpressionValue<bool> earlyFragmentTests;
ExpressionValue<ShaderStageType> entryStage;
ExpressionValue<ExpressionType> returnType;
std::optional<std::size_t> funcIndex; std::optional<std::size_t> funcIndex;
std::optional<std::size_t> varIndex; std::optional<std::size_t> varIndex;
std::string name; std::string name;
std::vector<Parameter> parameters; std::vector<Parameter> parameters;
std::vector<StatementPtr> statements; std::vector<StatementPtr> statements;
ExpressionValue<DepthWriteMode> depthWrite;
ExpressionValue<bool> earlyFragmentTests;
ExpressionValue<ShaderStageType> entryStage;
ExpressionValue<ExpressionType> returnType;
}; };
struct NAZARA_SHADER_API DeclareOptionStatement : Statement struct NAZARA_SHADER_API DeclareOptionStatement : Statement
@ -312,6 +312,7 @@ namespace Nz::ShaderAst
void Visit(AstStatementVisitor& visitor) override; void Visit(AstStatementVisitor& visitor) override;
std::optional<std::size_t> structIndex; std::optional<std::size_t> structIndex;
ExpressionValue<bool> isExported;
StructDescription description; StructDescription description;
}; };

View File

@ -148,6 +148,7 @@ namespace Nz::ShaderAst
{ {
auto clone = std::make_unique<DeclareStructStatement>(); auto clone = std::make_unique<DeclareStructStatement>();
clone->structIndex = node.structIndex; clone->structIndex = node.structIndex;
clone->isExported = Clone(node.isExported);
clone->description.layout = Clone(node.description.layout); clone->description.layout = Clone(node.description.layout);
clone->description.name = node.description.name; clone->description.name = node.description.name;

View File

@ -3,9 +3,9 @@
// 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/Shader/Ast/AstSerializer.hpp> #include <Nazara/Shader/Ast/AstSerializer.hpp>
#include <Nazara/Shader/ShaderBuilder.hpp>
#include <Nazara/Shader/Ast/AstExpressionVisitor.hpp> #include <Nazara/Shader/Ast/AstExpressionVisitor.hpp>
#include <Nazara/Shader/Ast/AstStatementVisitor.hpp> #include <Nazara/Shader/Ast/AstStatementVisitor.hpp>
#include <Nazara/Shader/ShaderBuilder.hpp>
#include <Nazara/Shader/Debug.hpp> #include <Nazara/Shader/Debug.hpp>
namespace Nz::ShaderAst namespace Nz::ShaderAst
@ -249,6 +249,7 @@ namespace Nz::ShaderAst
void AstSerializerBase::Serialize(DeclareStructStatement& node) void AstSerializerBase::Serialize(DeclareStructStatement& node)
{ {
OptVal(node.structIndex); OptVal(node.structIndex);
ExprValue(node.isExported);
Value(node.description.name); Value(node.description.name);
ExprValue(node.description.layout); ExprValue(node.description.layout);

View File

@ -939,6 +939,9 @@ namespace Nz::ShaderAst
auto clone = static_unique_pointer_cast<DeclareStructStatement>(AstCloner::Clone(node)); auto clone = static_unique_pointer_cast<DeclareStructStatement>(AstCloner::Clone(node));
if (clone->isExported.HasValue())
clone->isExported = ComputeExprValue(clone->isExported);
std::unordered_set<std::string> declaredMembers; std::unordered_set<std::string> declaredMembers;
for (auto& member : clone->description.members) for (auto& member : clone->description.members)
{ {

View File

@ -28,6 +28,7 @@ namespace Nz::ShaderLang
{ "depth_write", ShaderAst::AttributeType::DepthWrite }, { "depth_write", ShaderAst::AttributeType::DepthWrite },
{ "early_fragment_tests", ShaderAst::AttributeType::EarlyFragmentTests }, { "early_fragment_tests", ShaderAst::AttributeType::EarlyFragmentTests },
{ "entry", ShaderAst::AttributeType::Entry }, { "entry", ShaderAst::AttributeType::Entry },
{ "export", ShaderAst::AttributeType::Export },
{ "layout", ShaderAst::AttributeType::Layout }, { "layout", ShaderAst::AttributeType::Layout },
{ "location", ShaderAst::AttributeType::Location }, { "location", ShaderAst::AttributeType::Location },
{ "nzsl_version", ShaderAst::AttributeType::LangVersion }, { "nzsl_version", ShaderAst::AttributeType::LangVersion },
@ -66,15 +67,27 @@ namespace Nz::ShaderLang
} }
template<typename T> template<typename T>
void HandleUniqueAttribute(const std::string_view& attributeName, ShaderAst::ExpressionValue<T>& targetAttribute, ShaderAst::ExprValue::Param&& param, bool requireValue = true) void HandleUniqueAttribute(const std::string_view& attributeName, ShaderAst::ExpressionValue<T>& targetAttribute, ShaderAst::ExprValue::Param&& param)
{ {
if (targetAttribute.HasValue()) if (targetAttribute.HasValue())
throw AttributeError{ "attribute " + std::string(attributeName) + " must be present once" }; throw AttributeError{ "attribute " + std::string(attributeName) + " must be present once" };
if (!param && requireValue) if (param)
throw AttributeError{ "attribute " + std::string(attributeName) + " requires a parameter" };
targetAttribute = std::move(*param); targetAttribute = std::move(*param);
else
throw AttributeError{ "attribute " + std::string(attributeName) + " requires a parameter" };
}
template<typename T>
void HandleUniqueAttribute(const std::string_view& attributeName, ShaderAst::ExpressionValue<T>& targetAttribute, ShaderAst::ExprValue::Param&& param, T defaultValue)
{
if (targetAttribute.HasValue())
throw AttributeError{ "attribute " + std::string(attributeName) + " must be present once" };
if (param)
targetAttribute = std::move(*param);
else
targetAttribute = std::move(defaultValue);
} }
template<typename T> template<typename T>
@ -122,7 +135,7 @@ namespace Nz::ShaderLang
{ {
ShaderAst::StatementPtr statement = ParseRootStatement(); ShaderAst::StatementPtr statement = ParseRootStatement();
if (!m_context->module) if (!m_context->module)
throw UnexpectedToken{ "unexpected token before module declaration" }; throw UnexpectedToken{}; //< "unexpected token before module declaration"
if (!statement) if (!statement)
break; break;
@ -611,7 +624,7 @@ namespace Nz::ShaderLang
break; break;
case ShaderAst::AttributeType::EarlyFragmentTests: case ShaderAst::AttributeType::EarlyFragmentTests:
HandleUniqueAttribute("early_fragment_tests", func->earlyFragmentTests, std::move(arg), false); HandleUniqueAttribute("early_fragment_tests", func->earlyFragmentTests, std::move(arg), true);
break; break;
default: default:
@ -836,6 +849,7 @@ namespace Nz::ShaderLang
description.name = ParseIdentifierAsName(); description.name = ParseIdentifierAsName();
ShaderAst::ExpressionValue<bool> condition; ShaderAst::ExpressionValue<bool> condition;
ShaderAst::ExpressionValue<bool> exported;
for (auto&& [attributeType, attributeParam] : attributes) for (auto&& [attributeType, attributeParam] : attributes)
{ {
@ -845,6 +859,10 @@ namespace Nz::ShaderLang
HandleUniqueAttribute("cond", condition, std::move(attributeParam)); HandleUniqueAttribute("cond", condition, std::move(attributeParam));
break; break;
case ShaderAst::AttributeType::Export:
HandleUniqueAttribute("export", exported, std::move(attributeParam), true);
break;
case ShaderAst::AttributeType::Layout: case ShaderAst::AttributeType::Layout:
HandleUniqueStringAttribute("layout", s_layoutMapping, description.layout, std::move(attributeParam)); HandleUniqueStringAttribute("layout", s_layoutMapping, description.layout, std::move(attributeParam));
break; break;
@ -917,9 +935,9 @@ namespace Nz::ShaderLang
Expect(Advance(), TokenType::ClosingCurlyBracket); Expect(Advance(), TokenType::ClosingCurlyBracket);
if (condition.HasValue()) if (condition.HasValue())
return ShaderBuilder::ConditionalStatement(std::move(condition).GetExpression(), ShaderBuilder::DeclareStruct(std::move(description))); return ShaderBuilder::ConditionalStatement(std::move(condition).GetExpression(), ShaderBuilder::DeclareStruct(std::move(description), std::move(exported)));
else else
return ShaderBuilder::DeclareStruct(std::move(description)); return ShaderBuilder::DeclareStruct(std::move(description), std::move(exported));
} }
ShaderAst::ExpressionPtr Parser::ParseVariableAssignation() ShaderAst::ExpressionPtr Parser::ParseVariableAssignation()