diff --git a/include/Nazara/Shader/ShaderBuilder.hpp b/include/Nazara/Shader/ShaderBuilder.hpp index 5f01128e3..502dbed73 100644 --- a/include/Nazara/Shader/ShaderBuilder.hpp +++ b/include/Nazara/Shader/ShaderBuilder.hpp @@ -89,10 +89,15 @@ namespace Nz::ShaderBuilder inline std::unique_ptr operator()(ShaderAst::IntrinsicType intrinsicType, std::vector parameters) const; }; + struct Multi + { + inline std::unique_ptr operator()(std::vector statements) const; + }; + template struct NoParam { - std::unique_ptr operator()() const; + inline std::unique_ptr operator()() const; }; struct Return @@ -121,6 +126,7 @@ namespace Nz::ShaderBuilder constexpr Impl::NoParam Discard; constexpr Impl::Identifier Identifier; constexpr Impl::Intrinsic Intrinsic; + constexpr Impl::Multi MultiStatement; constexpr Impl::NoParam NoOp; constexpr Impl::Return Return; constexpr Impl::Swizzle Swizzle; diff --git a/include/Nazara/Shader/ShaderBuilder.inl b/include/Nazara/Shader/ShaderBuilder.inl index f72c98dbe..d27cbd5fd 100644 --- a/include/Nazara/Shader/ShaderBuilder.inl +++ b/include/Nazara/Shader/ShaderBuilder.inl @@ -172,12 +172,12 @@ namespace Nz::ShaderBuilder return intrinsicExpression; } - inline std::unique_ptr Impl::Return::operator()(ShaderAst::ExpressionPtr expr) const + inline std::unique_ptr Impl::Multi::operator()(std::vector statements) const { - auto returnNode = std::make_unique(); - returnNode->returnExpr = std::move(expr); + auto multiStatement = std::make_unique(); + multiStatement->statements = std::move(statements); - return returnNode; + return multiStatement; } template @@ -186,6 +186,14 @@ namespace Nz::ShaderBuilder return std::make_unique(); } + inline std::unique_ptr Impl::Return::operator()(ShaderAst::ExpressionPtr expr) const + { + auto returnNode = std::make_unique(); + returnNode->returnExpr = std::move(expr); + + return returnNode; + } + inline std::unique_ptr Impl::Swizzle::operator()(ShaderAst::ExpressionPtr expression, std::vector swizzleComponents) const { auto swizzleNode = std::make_unique(); diff --git a/include/Nazara/Shader/ShaderNodes.hpp b/include/Nazara/Shader/ShaderNodes.hpp index 0e84c8d1f..5a6a2bae7 100644 --- a/include/Nazara/Shader/ShaderNodes.hpp +++ b/include/Nazara/Shader/ShaderNodes.hpp @@ -26,6 +26,10 @@ namespace Nz::ShaderAst class AstExpressionVisitor; class AstStatementVisitor; + struct Node; + + using NodePtr = std::unique_ptr; + struct NAZARA_SHADER_API Node { Node() = default; diff --git a/src/ShaderNode/DataModels/BinOp.hpp b/src/ShaderNode/DataModels/BinOp.hpp index a4ac0a189..e8dcfd8a1 100644 --- a/src/ShaderNode/DataModels/BinOp.hpp +++ b/src/ShaderNode/DataModels/BinOp.hpp @@ -7,14 +7,14 @@ #include #include -template +template class BinOp : public ShaderNode { public: BinOp(ShaderGraph& graph); ~BinOp() = default; - Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; + Nz::ShaderAst::NodePtr BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; virtual QString GetOperationString() const = 0; @@ -45,40 +45,40 @@ class BinOp : public ShaderNode template -class BinAdd : public BinOp +class BinAdd : public BinOp { public: - using BinOp::BinOp; + using BinOp::BinOp; void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override; QString GetOperationString() const final; }; template -class BinMul : public BinOp +class BinMul : public BinOp { public: - using BinOp::BinOp; + using BinOp::BinOp; void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override; QString GetOperationString() const final; }; template -class BinSub : public BinOp +class BinSub : public BinOp { public: - using BinOp::BinOp; + using BinOp::BinOp; void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override; QString GetOperationString() const final; }; template -class BinDiv : public BinOp +class BinDiv : public BinOp { public: - using BinOp::BinOp; + using BinOp::BinOp; void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override; QString GetOperationString() const final; diff --git a/src/ShaderNode/DataModels/BinOp.inl b/src/ShaderNode/DataModels/BinOp.inl index 10031254c..b91999e18 100644 --- a/src/ShaderNode/DataModels/BinOp.inl +++ b/src/ShaderNode/DataModels/BinOp.inl @@ -1,25 +1,23 @@ #include #include -template +template BinOp::BinOp(ShaderGraph& graph) : ShaderNode(graph) { UpdateOutput(); } -template -Nz::ShaderNodes::NodePtr BinOp::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const +template +Nz::ShaderAst::NodePtr BinOp::BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const { assert(count == 2); assert(outputIndex == 0); - using BuilderType = typename Nz::ShaderBuilder::template BinOpBuilder; - constexpr BuilderType builder; - return builder(expressions[0], expressions[1]); + return Nz::ShaderBuilder::Binary(Op, std::move(expressions[0]), std::move(expressions[1])); } -template +template QtNodes::NodeDataType BinOp::dataType(QtNodes::PortType /*portType*/, QtNodes::PortIndex portIndex) const { assert(portIndex == 0 || portIndex == 1); @@ -27,7 +25,7 @@ QtNodes::NodeDataType BinOp::dataType(QtNodes::PortType /*portType return DataType::Type(); } -template +template unsigned int BinOp::nPorts(QtNodes::PortType portType) const { switch (portType) @@ -41,14 +39,14 @@ unsigned int BinOp::nPorts(QtNodes::PortType portType) const throw std::runtime_error("invalid port type"); } -template +template std::shared_ptr BinOp::outData(QtNodes::PortIndex port) { assert(port == 0); return m_output; } -template +template QString BinOp::portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const { switch (portType) @@ -81,14 +79,14 @@ QString BinOp::portCaption(QtNodes::PortType portType, QtNodes::Po return QString{}; } -template +template bool BinOp::portCaptionVisible(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const { assert(portIndex == 0 || portIndex == 1); return portType == QtNodes::PortType::In || portType == QtNodes::PortType::Out; } -template +template void BinOp::setInData(std::shared_ptr value, int index) { assert(index == 0 || index == 1); @@ -105,7 +103,7 @@ void BinOp::setInData(std::shared_ptr value, in UpdateOutput(); } -template +template QtNodes::NodeValidationState BinOp::validationState() const { if (!m_lhs || !m_rhs) @@ -120,7 +118,7 @@ QtNodes::NodeValidationState BinOp::validationState() const return QtNodes::NodeValidationState::Valid; } -template +template QString BinOp::validationMessage() const { if (!m_lhs || !m_rhs) @@ -135,7 +133,7 @@ QString BinOp::validationMessage() const return QString(); } -template +template bool BinOp::ComputePreview(QPixmap& pixmap) { if (!m_lhs || !m_rhs) @@ -145,7 +143,7 @@ bool BinOp::ComputePreview(QPixmap& pixmap) return true; } -template +template void BinOp::UpdateOutput() { if (validationState() != QtNodes::NodeValidationState::Valid) diff --git a/src/ShaderNode/DataModels/BoolValue.cpp b/src/ShaderNode/DataModels/BoolValue.cpp index 940d8f0fb..2e06c627e 100644 --- a/src/ShaderNode/DataModels/BoolValue.cpp +++ b/src/ShaderNode/DataModels/BoolValue.cpp @@ -89,7 +89,7 @@ void BoolValue::BuildNodeEdition(QFormLayout* layout) layout->addRow(tr("Value"), checkbox); } -Nz::ShaderNodes::NodePtr BoolValue::BuildNode(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count, std::size_t outputIndex) const +Nz::ShaderAst::NodePtr BoolValue::BuildNode(Nz::ShaderAst::ExpressionPtr* /*expressions*/, std::size_t count, std::size_t outputIndex) const { assert(count == 0); assert(outputIndex == 0); diff --git a/src/ShaderNode/DataModels/BoolValue.hpp b/src/ShaderNode/DataModels/BoolValue.hpp index d3e664d9d..8e906e97b 100644 --- a/src/ShaderNode/DataModels/BoolValue.hpp +++ b/src/ShaderNode/DataModels/BoolValue.hpp @@ -17,7 +17,7 @@ class BoolValue : public ShaderNode BoolValue(ShaderGraph& graph); ~BoolValue() = default; - Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; + Nz::ShaderAst::NodePtr BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; void BuildNodeEdition(QFormLayout* layout) override; QString caption() const override; diff --git a/src/ShaderNode/DataModels/BufferField.cpp b/src/ShaderNode/DataModels/BufferField.cpp index 6f2c506fe..b191aeba4 100644 --- a/src/ShaderNode/DataModels/BufferField.cpp +++ b/src/ShaderNode/DataModels/BufferField.cpp @@ -49,7 +49,7 @@ ShaderNode(graph) UpdatePreview(); } -Nz::ShaderNodes::NodePtr BufferField::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const +Nz::ShaderAst::NodePtr BufferField::BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const { assert(count == 0); assert(outputIndex == 0); @@ -62,23 +62,13 @@ Nz::ShaderNodes::NodePtr BufferField::BuildNode(Nz::ShaderNodes::ExpressionPtr* const auto& bufferEntry = graph.GetBuffer(*m_currentBufferIndex); const auto& structEntry = graph.GetStruct(bufferEntry.structIndex); - Nz::ShaderNodes::VariablePtr varPtr; - switch (bufferEntry.type) - { - case BufferType::UniformBufferObject: - varPtr = Nz::ShaderBuilder::Uniform(bufferEntry.name, structEntry.name); - break; - } - - assert(varPtr); - assert(m_currentFieldIndex); const CurrentField& currentField = *m_currentFieldIndex; - Nz::ShaderNodes::ExpressionPtr sourceExpr = Nz::ShaderBuilder::Identifier(varPtr); + Nz::ShaderAst::ExpressionPtr sourceExpr = Nz::ShaderBuilder::Identifier(bufferEntry.name); - std::vector memberIndices; - memberIndices.reserve(currentField.nestedFields.size() + 1); + std::vector memberIdentifiers; + memberIdentifiers.reserve(currentField.nestedFields.size() + 1); const ShaderGraph::StructEntry* sourceStruct = &structEntry; for (std::size_t nestedIndex : currentField.nestedFields) @@ -90,16 +80,17 @@ Nz::ShaderNodes::NodePtr BufferField::BuildNode(Nz::ShaderNodes::ExpressionPtr* std::size_t nestedStructIndex = std::get(memberEntry.type); sourceStruct = &graph.GetStruct(nestedStructIndex); - memberIndices.push_back(nestedIndex); + memberIdentifiers.push_back(memberEntry.name); } - memberIndices.push_back(currentField.finalFieldIndex); - assert(currentField.finalFieldIndex < sourceStruct->members.size()); const auto& memberEntry = sourceStruct->members[currentField.finalFieldIndex]; assert(std::holds_alternative(memberEntry.type)); - return Nz::ShaderBuilder::AccessMember(std::move(sourceExpr), std::move(memberIndices), graph.ToShaderExpressionType(std::get(memberEntry.type))); + memberIdentifiers.push_back(memberEntry.name); + + using namespace Nz; + return ShaderBuilder::AccessMember(std::move(sourceExpr), std::move(memberIdentifiers)); } unsigned int BufferField::nPorts(QtNodes::PortType portType) const diff --git a/src/ShaderNode/DataModels/BufferField.hpp b/src/ShaderNode/DataModels/BufferField.hpp index 7e5e46be4..eed42d9e1 100644 --- a/src/ShaderNode/DataModels/BufferField.hpp +++ b/src/ShaderNode/DataModels/BufferField.hpp @@ -15,7 +15,7 @@ class BufferField : public ShaderNode BufferField(ShaderGraph& graph); ~BufferField() = default; - Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; + Nz::ShaderAst::NodePtr BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; void BuildNodeEdition(QFormLayout* layout) override; QString caption() const override { return "BufferField"; } diff --git a/src/ShaderNode/DataModels/Cast.hpp b/src/ShaderNode/DataModels/Cast.hpp index ea3303dd3..47f954f81 100644 --- a/src/ShaderNode/DataModels/Cast.hpp +++ b/src/ShaderNode/DataModels/Cast.hpp @@ -17,7 +17,7 @@ class CastVec : public ShaderNode CastVec(ShaderGraph& graph); ~CastVec() = default; - Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const; + Nz::ShaderAst::NodePtr BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const; void BuildNodeEdition(QFormLayout* layout) override; QString caption() const override; diff --git a/src/ShaderNode/DataModels/Cast.inl b/src/ShaderNode/DataModels/Cast.inl index a8e932fed..f52efbb74 100644 --- a/src/ShaderNode/DataModels/Cast.inl +++ b/src/ShaderNode/DataModels/Cast.inl @@ -18,7 +18,7 @@ ShaderNode(graph) } template -Nz::ShaderNodes::NodePtr CastVec::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const +Nz::ShaderAst::NodePtr CastVec::BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const { assert(m_input); assert(count == 1); @@ -30,29 +30,27 @@ Nz::ShaderNodes::NodePtr CastVec::BuildNode(Nz::ShaderNodes::E { std::size_t overflowComponentCount = ToComponentCount - fromComponentCount; - std::array expr; - expr[0] = expressions[0]; + std::vector params; + params.emplace_back(std::move(params[0])); for (std::size_t i = 0; i < overflowComponentCount; ++i) - expr[i + 1] = Nz::ShaderBuilder::Constant(m_overflowComponents[i]); + params.emplace_back(Nz::ShaderBuilder::Constant(m_overflowComponents[i])); - constexpr auto ExpressionType = VecExpressionType; - - return Nz::ShaderBuilder::Cast(expr.data(), 1 + overflowComponentCount); + return Nz::ShaderBuilder::Cast(Nz::ShaderAst::VectorType{ ToComponentCount, Nz::ShaderAst::PrimitiveType::Float32 }, std::move(params)); } else if (ToComponentCount < fromComponentCount) { - std::array swizzleComponents; + std::array swizzleComponents; for (std::size_t i = 0; i < ToComponentCount; ++i) - swizzleComponents[i] = static_cast(static_cast(Nz::ShaderNodes::SwizzleComponent::First) + i); + swizzleComponents[i] = static_cast(static_cast(Nz::ShaderAst::SwizzleComponent::First) + i); return std::apply([&](auto... components) - { - std::initializer_list componentList{ components... }; - return Nz::ShaderBuilder::Swizzle(expressions[0], componentList); - }, swizzleComponents); + { + std::initializer_list componentList{ components... }; + return Nz::ShaderBuilder::Swizzle(std::move(expressions[0]), componentList); + }, swizzleComponents); } else - return expressions[0]; //< no-op + return std::move(expressions[0]); //< no-op } template @@ -110,6 +108,7 @@ QtNodes::NodeDataType CastVec::dataType(QtNodes::PortType port { case QtNodes::PortType::In: return VecData::Type(); case QtNodes::PortType::Out: return VecData::Type(); + default: break; } assert(false); diff --git a/src/ShaderNode/DataModels/CompOp.hpp b/src/ShaderNode/DataModels/CompOp.hpp index cb7da53e4..134fe87ca 100644 --- a/src/ShaderNode/DataModels/CompOp.hpp +++ b/src/ShaderNode/DataModels/CompOp.hpp @@ -8,14 +8,14 @@ #include #include -template +template class CompOp : public ShaderNode { public: CompOp(ShaderGraph& graph); ~CompOp() = default; - Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; + Nz::ShaderAst::NodePtr BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; virtual QString GetOperationString() const = 0; @@ -46,60 +46,60 @@ class CompOp : public ShaderNode template -class CompEq : public CompOp +class CompEq : public CompOp { public: - using CompOp::CompOp; + using CompOp::CompOp; void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override; QString GetOperationString() const final; }; template -class CompGe : public CompOp +class CompGe : public CompOp { public: - using CompOp::CompOp; + using CompOp::CompOp; void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override; QString GetOperationString() const final; }; template -class CompGt : public CompOp +class CompGt : public CompOp { public: - using CompOp::CompOp; + using CompOp::CompOp; void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override; QString GetOperationString() const final; }; template -class CompLe : public CompOp +class CompLe : public CompOp { public: - using CompOp::CompOp; + using CompOp::CompOp; void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override; QString GetOperationString() const final; }; template -class CompLt : public CompOp +class CompLt : public CompOp { public: - using CompOp::CompOp; + using CompOp::CompOp; void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override; QString GetOperationString() const final; }; template -class CompNe : public CompOp +class CompNe : public CompOp { public: - using CompOp::CompOp; + using CompOp::CompOp; void ApplyOp(const Nz::Vector4f* left, const Nz::Vector4f* right, Nz::Vector4f* output, std::size_t pixelCount) override; QString GetOperationString() const final; diff --git a/src/ShaderNode/DataModels/CompOp.inl b/src/ShaderNode/DataModels/CompOp.inl index 4ca0a122e..ba4b55ad8 100644 --- a/src/ShaderNode/DataModels/CompOp.inl +++ b/src/ShaderNode/DataModels/CompOp.inl @@ -1,25 +1,23 @@ #include #include -template +template CompOp::CompOp(ShaderGraph& graph) : ShaderNode(graph) { UpdateOutput(); } -template -Nz::ShaderNodes::NodePtr CompOp::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const +template +Nz::ShaderAst::NodePtr CompOp::BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const { assert(count == 2); assert(outputIndex == 0); - using BuilderType = typename Nz::ShaderBuilder::template BinOpBuilder; - constexpr BuilderType builder; - return builder(expressions[0], expressions[1]); + return Nz::ShaderBuilder::Binary(Op, std::move(expressions[0]), std::move(expressions[1])); } -template +template QtNodes::NodeDataType CompOp::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const { switch (portType) @@ -43,7 +41,7 @@ QtNodes::NodeDataType CompOp::dataType(QtNodes::PortType portType, throw std::runtime_error("invalid port type"); } -template +template unsigned int CompOp::nPorts(QtNodes::PortType portType) const { switch (portType) @@ -57,14 +55,14 @@ unsigned int CompOp::nPorts(QtNodes::PortType portType) const throw std::runtime_error("invalid port type"); } -template +template std::shared_ptr CompOp::outData(QtNodes::PortIndex port) { assert(port == 0); return m_output; } -template +template QString CompOp::portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const { switch (portType) @@ -97,14 +95,14 @@ QString CompOp::portCaption(QtNodes::PortType portType, QtNodes::P return QString{}; } -template +template bool CompOp::portCaptionVisible(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const { assert(portIndex == 0 || portIndex == 1); return portType == QtNodes::PortType::In || portType == QtNodes::PortType::Out; } -template +template void CompOp::setInData(std::shared_ptr value, int index) { assert(index == 0 || index == 1); @@ -121,7 +119,7 @@ void CompOp::setInData(std::shared_ptr value, i UpdateOutput(); } -template +template QtNodes::NodeValidationState CompOp::validationState() const { if (!m_lhs || !m_rhs) @@ -136,7 +134,7 @@ QtNodes::NodeValidationState CompOp::validationState() const return QtNodes::NodeValidationState::Valid; } -template +template QString CompOp::validationMessage() const { if (!m_lhs || !m_rhs) @@ -151,7 +149,7 @@ QString CompOp::validationMessage() const return QString(); } -template +template bool CompOp::ComputePreview(QPixmap& pixmap) { if (!m_lhs || !m_rhs) @@ -161,7 +159,7 @@ bool CompOp::ComputePreview(QPixmap& pixmap) return true; } -template +template void CompOp::UpdateOutput() { if (validationState() != QtNodes::NodeValidationState::Valid) diff --git a/src/ShaderNode/DataModels/ConditionalExpression.cpp b/src/ShaderNode/DataModels/ConditionalExpression.cpp index 27224e8d6..3b49f2237 100644 --- a/src/ShaderNode/DataModels/ConditionalExpression.cpp +++ b/src/ShaderNode/DataModels/ConditionalExpression.cpp @@ -35,7 +35,7 @@ ShaderNode(graph) UpdatePreview(); } -Nz::ShaderNodes::NodePtr ConditionalExpression::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const +Nz::ShaderAst::NodePtr ConditionalExpression::BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const { assert(count == 2); assert(outputIndex == 0); @@ -46,7 +46,7 @@ Nz::ShaderNodes::NodePtr ConditionalExpression::BuildNode(Nz::ShaderNodes::Expre const ShaderGraph& graph = GetGraph(); const auto& conditionEntry = graph.GetCondition(*m_currentConditionIndex); - return Nz::ShaderBuilder::ConditionalExpression(conditionEntry.name, expressions[0], expressions[1]); + return Nz::ShaderBuilder::ConditionalExpression(conditionEntry.name, std::move(expressions[0]), std::move(expressions[1])); } QString ConditionalExpression::caption() const diff --git a/src/ShaderNode/DataModels/ConditionalExpression.hpp b/src/ShaderNode/DataModels/ConditionalExpression.hpp index 1c732243d..a2bd1eb3a 100644 --- a/src/ShaderNode/DataModels/ConditionalExpression.hpp +++ b/src/ShaderNode/DataModels/ConditionalExpression.hpp @@ -15,7 +15,7 @@ class ConditionalExpression : public ShaderNode ConditionalExpression(ShaderGraph& graph); ~ConditionalExpression() = default; - Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; + Nz::ShaderAst::NodePtr BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; void BuildNodeEdition(QFormLayout* layout) override; QString caption() const override; diff --git a/src/ShaderNode/DataModels/Discard.cpp b/src/ShaderNode/DataModels/Discard.cpp index 968e8d53c..aa3035155 100644 --- a/src/ShaderNode/DataModels/Discard.cpp +++ b/src/ShaderNode/DataModels/Discard.cpp @@ -16,14 +16,15 @@ ShaderNode(graph) DisableCustomVariableName(); } -Nz::ShaderNodes::NodePtr Discard::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const +Nz::ShaderAst::NodePtr Discard::BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const { - using namespace Nz::ShaderBuilder; - assert(count == 1); assert(outputIndex == 0); - return Branch(Equal(expressions[0], Constant(true)), Nz::ShaderBuilder::Discard(), nullptr); + using namespace Nz; + + auto condition = ShaderBuilder::Binary(ShaderAst::BinaryType::CompEq, std::move(expressions[0]), ShaderBuilder::Constant(true)); + return ShaderBuilder::Branch(std::move(condition), ShaderBuilder::Discard()); } int Discard::GetOutputOrder() const diff --git a/src/ShaderNode/DataModels/Discard.hpp b/src/ShaderNode/DataModels/Discard.hpp index 55f6be153..91f88edea 100644 --- a/src/ShaderNode/DataModels/Discard.hpp +++ b/src/ShaderNode/DataModels/Discard.hpp @@ -14,7 +14,7 @@ class Discard : public ShaderNode public: Discard(ShaderGraph& graph); - Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; + Nz::ShaderAst::NodePtr BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; int GetOutputOrder() const; QString caption() const override { return "Discard"; } diff --git a/src/ShaderNode/DataModels/FloatValue.cpp b/src/ShaderNode/DataModels/FloatValue.cpp index 4efc10585..49513baa6 100644 --- a/src/ShaderNode/DataModels/FloatValue.cpp +++ b/src/ShaderNode/DataModels/FloatValue.cpp @@ -89,7 +89,7 @@ void FloatValue::BuildNodeEdition(QFormLayout* layout) layout->addRow(tr("Value"), spinbox); } -Nz::ShaderNodes::NodePtr FloatValue::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const +Nz::ShaderAst::NodePtr FloatValue::BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const { assert(count == 0); assert(outputIndex == 0); diff --git a/src/ShaderNode/DataModels/FloatValue.hpp b/src/ShaderNode/DataModels/FloatValue.hpp index 6dfb110f8..722ee44ca 100644 --- a/src/ShaderNode/DataModels/FloatValue.hpp +++ b/src/ShaderNode/DataModels/FloatValue.hpp @@ -17,7 +17,7 @@ class FloatValue : public ShaderNode FloatValue(ShaderGraph& graph); ~FloatValue() = default; - Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; + Nz::ShaderAst::NodePtr BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; void BuildNodeEdition(QFormLayout* layout) override; QString caption() const override; diff --git a/src/ShaderNode/DataModels/InputValue.cpp b/src/ShaderNode/DataModels/InputValue.cpp index f6926278b..51dc4953b 100644 --- a/src/ShaderNode/DataModels/InputValue.cpp +++ b/src/ShaderNode/DataModels/InputValue.cpp @@ -109,7 +109,7 @@ void InputValue::BuildNodeEdition(QFormLayout* layout) layout->addRow(tr("Input"), inputSelection); } -Nz::ShaderNodes::NodePtr InputValue::BuildNode(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count, std::size_t outputIndex) const +Nz::ShaderAst::NodePtr InputValue::BuildNode(Nz::ShaderAst::ExpressionPtr* /*expressions*/, std::size_t count, std::size_t outputIndex) const { assert(count == 0); assert(outputIndex == 0); @@ -118,7 +118,7 @@ Nz::ShaderNodes::NodePtr InputValue::BuildNode(Nz::ShaderNodes::ExpressionPtr* / throw std::runtime_error("no input"); const auto& inputEntry = GetGraph().GetInput(*m_currentInputIndex); - return Nz::ShaderBuilder::Identifier(Nz::ShaderBuilder::Input(inputEntry.name, ShaderGraph::ToShaderExpressionType(inputEntry.type))); + return Nz::ShaderBuilder::AccessMember(Nz::ShaderBuilder::Identifier("input"), { inputEntry.name }); } auto InputValue::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const -> QtNodes::NodeDataType diff --git a/src/ShaderNode/DataModels/InputValue.hpp b/src/ShaderNode/DataModels/InputValue.hpp index 9863d7b98..63cbf197c 100644 --- a/src/ShaderNode/DataModels/InputValue.hpp +++ b/src/ShaderNode/DataModels/InputValue.hpp @@ -19,7 +19,7 @@ class InputValue : public ShaderNode void BuildNodeEdition(QFormLayout* layout) override; - Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; + Nz::ShaderAst::NodePtr BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; QString caption() const override { return "Input"; } QString name() const override { return "Input"; } diff --git a/src/ShaderNode/DataModels/Mat4BinOp.hpp b/src/ShaderNode/DataModels/Mat4BinOp.hpp index 1d6d71eee..e752b21a4 100644 --- a/src/ShaderNode/DataModels/Mat4BinOp.hpp +++ b/src/ShaderNode/DataModels/Mat4BinOp.hpp @@ -6,14 +6,14 @@ #include #include -template +template class Mat4BinOp : public ShaderNode { public: Mat4BinOp(ShaderGraph& graph); ~Mat4BinOp() = default; - Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const; + Nz::ShaderAst::NodePtr BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const; unsigned int nPorts(QtNodes::PortType portType) const override; @@ -35,28 +35,28 @@ class Mat4BinOp : public ShaderNode std::shared_ptr m_output; }; -class Mat4Add : public Mat4BinOp +class Mat4Add : public Mat4BinOp { public: - using Mat4BinOp::Mat4BinOp; + using Mat4BinOp::Mat4BinOp; QString caption() const override; QString name() const override; }; -class Mat4Mul : public Mat4BinOp +class Mat4Mul : public Mat4BinOp { public: - using Mat4BinOp::Mat4BinOp; + using Mat4BinOp::Mat4BinOp; QString caption() const override; QString name() const override; }; -class Mat4Sub : public Mat4BinOp +class Mat4Sub : public Mat4BinOp { public: - using Mat4BinOp::Mat4BinOp; + using Mat4BinOp::Mat4BinOp; QString caption() const override; QString name() const override; diff --git a/src/ShaderNode/DataModels/Mat4BinOp.inl b/src/ShaderNode/DataModels/Mat4BinOp.inl index 50c4102e4..894328be9 100644 --- a/src/ShaderNode/DataModels/Mat4BinOp.inl +++ b/src/ShaderNode/DataModels/Mat4BinOp.inl @@ -1,25 +1,23 @@ #include #include -template +template Mat4BinOp::Mat4BinOp(ShaderGraph& graph) : ShaderNode(graph) { UpdateOutput(); } -template -Nz::ShaderNodes::NodePtr Mat4BinOp::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const +template +Nz::ShaderAst::NodePtr Mat4BinOp::BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const { assert(count == 2); assert(outputIndex == 0); - using BuilderType = typename Nz::ShaderBuilder::template BinOpBuilder; - constexpr BuilderType builder; - return builder(expressions[0], expressions[1]); + return Nz::ShaderBuilder::Binary(Op, std::move(expressions[0]), std::move(expressions[1])); } -template +template QtNodes::NodeDataType Mat4BinOp::dataType(QtNodes::PortType /*portType*/, QtNodes::PortIndex portIndex) const { assert(portIndex == 0 || portIndex == 1); @@ -27,7 +25,7 @@ QtNodes::NodeDataType Mat4BinOp::dataType(QtNodes::PortType /*portType*/, Qt return Matrix4Data::Type(); } -template +template unsigned int Mat4BinOp::nPorts(QtNodes::PortType portType) const { switch (portType) @@ -41,14 +39,14 @@ unsigned int Mat4BinOp::nPorts(QtNodes::PortType portType) const throw std::runtime_error("invalid port type"); } -template +template std::shared_ptr Mat4BinOp::outData(QtNodes::PortIndex port) { assert(port == 0); return m_output; } -template +template void Mat4BinOp::setInData(std::shared_ptr value, int index) { assert(index == 0 || index == 1); @@ -68,7 +66,7 @@ void Mat4BinOp::setInData(std::shared_ptr value, int inde UpdateOutput(); } -template +template QtNodes::NodeValidationState Mat4BinOp::validationState() const { if (!m_lhs || !m_rhs) @@ -77,7 +75,7 @@ QtNodes::NodeValidationState Mat4BinOp::validationState() const return QtNodes::NodeValidationState::Valid; } -template +template QString Mat4BinOp::validationMessage() const { if (!m_lhs || !m_rhs) @@ -86,7 +84,7 @@ QString Mat4BinOp::validationMessage() const return QString(); } -template +template bool Mat4BinOp::ComputePreview(QPixmap& pixmap) { if (!m_lhs || !m_rhs) @@ -98,7 +96,7 @@ bool Mat4BinOp::ComputePreview(QPixmap& pixmap) //return true; } -template +template void Mat4BinOp::UpdateOutput() { if (validationState() != QtNodes::NodeValidationState::Valid) diff --git a/src/ShaderNode/DataModels/Mat4VecMul.cpp b/src/ShaderNode/DataModels/Mat4VecMul.cpp index 426c0bde1..f859166c1 100644 --- a/src/ShaderNode/DataModels/Mat4VecMul.cpp +++ b/src/ShaderNode/DataModels/Mat4VecMul.cpp @@ -1,4 +1,5 @@ #include +#include #include Mat4VecMul::Mat4VecMul(ShaderGraph& graph) : @@ -7,13 +8,12 @@ ShaderNode(graph) UpdateOutput(); } -Nz::ShaderNodes::NodePtr Mat4VecMul::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const +Nz::ShaderAst::NodePtr Mat4VecMul::BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const { assert(count == 2); assert(outputIndex == 0); - using namespace Nz::ShaderNodes; - return BinaryOp::Build(BinaryType::Multiply, expressions[0], expressions[1]); + return Nz::ShaderBuilder::Binary(Nz::ShaderAst::BinaryType::Multiply, std::move(expressions[0]), std::move(expressions[1])); } QString Mat4VecMul::caption() const diff --git a/src/ShaderNode/DataModels/Mat4VecMul.hpp b/src/ShaderNode/DataModels/Mat4VecMul.hpp index d3b25b3b1..76debc88f 100644 --- a/src/ShaderNode/DataModels/Mat4VecMul.hpp +++ b/src/ShaderNode/DataModels/Mat4VecMul.hpp @@ -13,7 +13,7 @@ class Mat4VecMul : public ShaderNode Mat4VecMul(ShaderGraph& graph); ~Mat4VecMul() = default; - Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; + Nz::ShaderAst::NodePtr BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; QString caption() const override; QString name() const override; diff --git a/src/ShaderNode/DataModels/OutputValue.cpp b/src/ShaderNode/DataModels/OutputValue.cpp index 22d4bfb72..e3471fff8 100644 --- a/src/ShaderNode/DataModels/OutputValue.cpp +++ b/src/ShaderNode/DataModels/OutputValue.cpp @@ -54,11 +54,8 @@ void OutputValue::BuildNodeEdition(QFormLayout* layout) layout->addRow(tr("Output"), outputSelection); } -Nz::ShaderNodes::NodePtr OutputValue::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const +Nz::ShaderAst::NodePtr OutputValue::BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const { - using namespace Nz::ShaderBuilder; - using namespace Nz::ShaderNodes; - assert(count == 1); assert(outputIndex == 0); @@ -66,9 +63,10 @@ Nz::ShaderNodes::NodePtr OutputValue::BuildNode(Nz::ShaderNodes::ExpressionPtr* throw std::runtime_error("no output"); const auto& outputEntry = GetGraph().GetOutput(*m_currentOutputIndex); - auto output = Nz::ShaderBuilder::Identifier(Nz::ShaderBuilder::Output(outputEntry.name, ShaderGraph::ToShaderExpressionType(outputEntry.type))); + auto output = Nz::ShaderBuilder::AccessMember(Nz::ShaderBuilder::Identifier("output"), { outputEntry.name }); - return Nz::ShaderBuilder::Assign(std::move(output), *expressions); + using namespace Nz; + return Nz::ShaderBuilder::Assign(ShaderAst::AssignType::Simple, std::move(output), std::move(expressions[0])); } std::shared_ptr OutputValue::outData(QtNodes::PortIndex /*port*/) diff --git a/src/ShaderNode/DataModels/OutputValue.hpp b/src/ShaderNode/DataModels/OutputValue.hpp index e798b7e82..a44284e1a 100644 --- a/src/ShaderNode/DataModels/OutputValue.hpp +++ b/src/ShaderNode/DataModels/OutputValue.hpp @@ -16,7 +16,7 @@ class OutputValue : public ShaderNode void BuildNodeEdition(QFormLayout* layout) override; - Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; + Nz::ShaderAst::NodePtr BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; QString caption() const override { return "Output"; } QString name() const override { return "Output"; } diff --git a/src/ShaderNode/DataModels/PositionOutputValue.cpp b/src/ShaderNode/DataModels/PositionOutputValue.cpp index 2f9f59716..14745fb45 100644 --- a/src/ShaderNode/DataModels/PositionOutputValue.cpp +++ b/src/ShaderNode/DataModels/PositionOutputValue.cpp @@ -14,16 +14,15 @@ ShaderNode(graph) DisableCustomVariableName(); } -Nz::ShaderNodes::NodePtr PositionOutputValue::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const +Nz::ShaderAst::NodePtr PositionOutputValue::BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const { - using namespace Nz::ShaderBuilder; - using namespace Nz::ShaderNodes; + using namespace Nz; assert(count == 1); assert(outputIndex == 0); - auto output = Nz::ShaderBuilder::Identifier(Nz::ShaderBuilder::Builtin(BuiltinEntry::VertexPosition)); - return Nz::ShaderBuilder::Assign(std::move(output), *expressions); + auto output = Nz::ShaderBuilder::AccessMember(Nz::ShaderBuilder::Identifier("OutputData"), { "position" }); + return ShaderBuilder::Assign(ShaderAst::AssignType::Simple, std::move(output), std::move(expressions[0])); } QtNodes::NodeDataType PositionOutputValue::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const diff --git a/src/ShaderNode/DataModels/PositionOutputValue.hpp b/src/ShaderNode/DataModels/PositionOutputValue.hpp index 6626226e4..1cb8ed8ef 100644 --- a/src/ShaderNode/DataModels/PositionOutputValue.hpp +++ b/src/ShaderNode/DataModels/PositionOutputValue.hpp @@ -14,7 +14,7 @@ class PositionOutputValue : public ShaderNode public: PositionOutputValue(ShaderGraph& graph); - Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; + Nz::ShaderAst::NodePtr BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; QString caption() const override { return "PositionOutputValue"; } QString name() const override { return "PositionOutputValue"; } diff --git a/src/ShaderNode/DataModels/SampleTexture.cpp b/src/ShaderNode/DataModels/SampleTexture.cpp index 4d7fcddee..7a697f7a7 100644 --- a/src/ShaderNode/DataModels/SampleTexture.cpp +++ b/src/ShaderNode/DataModels/SampleTexture.cpp @@ -71,14 +71,18 @@ bool SampleTexture::ComputePreview(QPixmap& pixmap) return true; } -Nz::ShaderNodes::NodePtr SampleTexture::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const +Nz::ShaderAst::NodePtr SampleTexture::BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const { assert(m_texture); assert(m_uv); assert(count == 2); assert(outputIndex == 0); - return Nz::ShaderBuilder::Sample2D(expressions[0], expressions[1]); + std::vector params; + params.push_back(std::move(expressions[0])); + params.push_back(std::move(expressions[1])); + + return Nz::ShaderBuilder::Intrinsic(Nz::ShaderAst::IntrinsicType::SampleTexture, std::move(params)); } auto SampleTexture::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const -> QtNodes::NodeDataType diff --git a/src/ShaderNode/DataModels/SampleTexture.hpp b/src/ShaderNode/DataModels/SampleTexture.hpp index d819a0df0..d09c71521 100644 --- a/src/ShaderNode/DataModels/SampleTexture.hpp +++ b/src/ShaderNode/DataModels/SampleTexture.hpp @@ -17,7 +17,7 @@ class SampleTexture : public ShaderNode SampleTexture(ShaderGraph& graph); ~SampleTexture() = default; - Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; + Nz::ShaderAst::NodePtr BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; QString caption() const override { return "Sample texture"; } QString name() const override { return "SampleTexture"; } diff --git a/src/ShaderNode/DataModels/ShaderNode.hpp b/src/ShaderNode/DataModels/ShaderNode.hpp index d3b200768..eeb8d0b3e 100644 --- a/src/ShaderNode/DataModels/ShaderNode.hpp +++ b/src/ShaderNode/DataModels/ShaderNode.hpp @@ -18,7 +18,7 @@ class ShaderNode : public QtNodes::NodeDataModel public: ShaderNode(ShaderGraph& graph); - virtual Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const = 0; + virtual Nz::ShaderAst::NodePtr BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const = 0; virtual void BuildNodeEdition(QFormLayout* layout); inline void DisablePreview(); diff --git a/src/ShaderNode/DataModels/TextureValue.cpp b/src/ShaderNode/DataModels/TextureValue.cpp index 9d0d25665..0be18dd88 100644 --- a/src/ShaderNode/DataModels/TextureValue.cpp +++ b/src/ShaderNode/DataModels/TextureValue.cpp @@ -110,7 +110,7 @@ void TextureValue::BuildNodeEdition(QFormLayout* layout) layout->addRow(tr("Texture"), textureSelection); } -Nz::ShaderNodes::NodePtr TextureValue::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const +Nz::ShaderAst::NodePtr TextureValue::BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const { if (!m_currentTextureIndex) throw std::runtime_error("invalid texture input"); @@ -119,19 +119,7 @@ Nz::ShaderNodes::NodePtr TextureValue::BuildNode(Nz::ShaderNodes::ExpressionPtr* assert(outputIndex == 0); const auto& textureEntry = GetGraph().GetTexture(*m_currentTextureIndex); - - Nz::ShaderNodes::BasicType expression = [&] - { - switch (textureEntry.type) - { - case TextureType::Sampler2D: return Nz::ShaderNodes::BasicType::Sampler2D; - } - - assert(false); - throw std::runtime_error("Unhandled texture type"); - }(); - - return Nz::ShaderBuilder::Identifier(Nz::ShaderBuilder::Uniform(textureEntry.name, expression)); + return Nz::ShaderBuilder::Identifier(textureEntry.name); } auto TextureValue::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const -> QtNodes::NodeDataType diff --git a/src/ShaderNode/DataModels/TextureValue.hpp b/src/ShaderNode/DataModels/TextureValue.hpp index 6d6e6ff27..5de2a556d 100644 --- a/src/ShaderNode/DataModels/TextureValue.hpp +++ b/src/ShaderNode/DataModels/TextureValue.hpp @@ -18,7 +18,7 @@ class TextureValue : public ShaderNode void BuildNodeEdition(QFormLayout* layout) override; - Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; + Nz::ShaderAst::NodePtr BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; QString caption() const override { return "Texture"; } QString name() const override { return "Texture"; } diff --git a/src/ShaderNode/DataModels/VecComposition.hpp b/src/ShaderNode/DataModels/VecComposition.hpp index 6a41b1e20..d6dfca579 100644 --- a/src/ShaderNode/DataModels/VecComposition.hpp +++ b/src/ShaderNode/DataModels/VecComposition.hpp @@ -17,7 +17,7 @@ class VecComposition : public ShaderNode VecComposition(ShaderGraph& graph); ~VecComposition() = default; - Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const; + Nz::ShaderAst::NodePtr BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; QString caption() const override; QString name() const override; diff --git a/src/ShaderNode/DataModels/VecComposition.inl b/src/ShaderNode/DataModels/VecComposition.inl index 9f17da698..70e8c15a6 100644 --- a/src/ShaderNode/DataModels/VecComposition.inl +++ b/src/ShaderNode/DataModels/VecComposition.inl @@ -14,17 +14,16 @@ ShaderNode(graph) } template -Nz::ShaderNodes::NodePtr VecComposition::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const +Nz::ShaderAst::NodePtr VecComposition::BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const { assert(count == ComponentCount); assert(outputIndex == 0); - std::array expr; + std::vector params; for (std::size_t i = 0; i < count; ++i) - expr[i] = expressions[i]; + params.emplace_back(std::move(expressions[i])); - constexpr auto ExpressionType = VecExpressionType; - return Nz::ShaderBuilder::Cast(expr.data(), expr.size()); + return Nz::ShaderBuilder::Cast(Nz::ShaderAst::VectorType{ ComponentCount, Nz::ShaderAst::PrimitiveType::Float32 }, std::move(params)); } template diff --git a/src/ShaderNode/DataModels/VecDecomposition.cpp b/src/ShaderNode/DataModels/VecDecomposition.cpp index df69df8e6..f36fcea50 100644 --- a/src/ShaderNode/DataModels/VecDecomposition.cpp +++ b/src/ShaderNode/DataModels/VecDecomposition.cpp @@ -16,15 +16,15 @@ ShaderNode(graph) DisableCustomVariableName(); } -Nz::ShaderNodes::NodePtr VecDecomposition::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const +Nz::ShaderAst::NodePtr VecDecomposition::BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const { assert(count == 1); assert(outputIndex < m_outputs.size()); - using namespace Nz::ShaderBuilder; - using namespace Nz::ShaderNodes; + using namespace Nz; - return Nz::ShaderBuilder::Swizzle(expressions[0], static_cast(Nz::UnderlyingCast(SwizzleComponent::First) + outputIndex)); + ShaderAst::SwizzleComponent swizzleComponent = static_cast(Nz::UnderlyingCast(ShaderAst::SwizzleComponent::First) + outputIndex); + return ShaderBuilder::Swizzle(std::move(expressions[0]), { swizzleComponent }); } QString VecDecomposition::caption() const diff --git a/src/ShaderNode/DataModels/VecDecomposition.hpp b/src/ShaderNode/DataModels/VecDecomposition.hpp index c50c95f40..a66326fbf 100644 --- a/src/ShaderNode/DataModels/VecDecomposition.hpp +++ b/src/ShaderNode/DataModels/VecDecomposition.hpp @@ -18,7 +18,7 @@ class VecDecomposition : public ShaderNode VecDecomposition(ShaderGraph& graph); ~VecDecomposition() = default; - Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; + Nz::ShaderAst::NodePtr BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; QString caption() const override; QString name() const override; diff --git a/src/ShaderNode/DataModels/VecDot.cpp b/src/ShaderNode/DataModels/VecDot.cpp index e327cf06b..0a6e7f0ce 100644 --- a/src/ShaderNode/DataModels/VecDot.cpp +++ b/src/ShaderNode/DataModels/VecDot.cpp @@ -1,4 +1,5 @@ #include +#include #include VecDot::VecDot(ShaderGraph& graph) : @@ -8,13 +9,16 @@ ShaderNode(graph) UpdateOutput(); } -Nz::ShaderNodes::NodePtr VecDot::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const +Nz::ShaderAst::NodePtr VecDot::BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const { assert(count == 2); assert(outputIndex == 0); - using namespace Nz::ShaderNodes; - return IntrinsicCall::Build(IntrinsicType::DotProduct, { expressions[0], expressions[1] }); + std::vector params; + params.push_back(std::move(expressions[0])); + params.push_back(std::move(expressions[1])); + + return Nz::ShaderBuilder::Intrinsic(Nz::ShaderAst::IntrinsicType::DotProduct, std::move(params)); } QString VecDot::caption() const diff --git a/src/ShaderNode/DataModels/VecDot.hpp b/src/ShaderNode/DataModels/VecDot.hpp index 251694ae8..194037bc6 100644 --- a/src/ShaderNode/DataModels/VecDot.hpp +++ b/src/ShaderNode/DataModels/VecDot.hpp @@ -13,7 +13,7 @@ class VecDot : public ShaderNode VecDot(ShaderGraph& graph); ~VecDot() = default; - Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; + Nz::ShaderAst::NodePtr BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; QString caption() const override; QString name() const override; diff --git a/src/ShaderNode/DataModels/VecFloatMul.cpp b/src/ShaderNode/DataModels/VecFloatMul.cpp index 33237dc25..62abd27e8 100644 --- a/src/ShaderNode/DataModels/VecFloatMul.cpp +++ b/src/ShaderNode/DataModels/VecFloatMul.cpp @@ -1,4 +1,5 @@ #include +#include #include VecFloatMul::VecFloatMul(ShaderGraph& graph) : @@ -7,13 +8,12 @@ ShaderNode(graph) UpdateOutput(); } -Nz::ShaderNodes::NodePtr VecFloatMul::BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const +Nz::ShaderAst::NodePtr VecFloatMul::BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const { assert(count == 2); assert(outputIndex == 0); - using namespace Nz::ShaderNodes; - return BinaryOp::Build(BinaryType::Multiply, expressions[0], expressions[1]); + return Nz::ShaderBuilder::Binary(Nz::ShaderAst::BinaryType::Multiply, std::move(expressions[0]), std::move(expressions[1])); } QString VecFloatMul::caption() const diff --git a/src/ShaderNode/DataModels/VecFloatMul.hpp b/src/ShaderNode/DataModels/VecFloatMul.hpp index b7759d4c7..7295d75ce 100644 --- a/src/ShaderNode/DataModels/VecFloatMul.hpp +++ b/src/ShaderNode/DataModels/VecFloatMul.hpp @@ -13,7 +13,7 @@ class VecFloatMul : public ShaderNode VecFloatMul(ShaderGraph& graph); ~VecFloatMul() = default; - Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; + Nz::ShaderAst::NodePtr BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; QString caption() const override; QString name() const override; diff --git a/src/ShaderNode/DataModels/VecValue.hpp b/src/ShaderNode/DataModels/VecValue.hpp index 3fcebb638..40035655c 100644 --- a/src/ShaderNode/DataModels/VecValue.hpp +++ b/src/ShaderNode/DataModels/VecValue.hpp @@ -18,7 +18,7 @@ class VecValue : public ShaderNode VecValue(ShaderGraph& graph); ~VecValue() = default; - Nz::ShaderNodes::NodePtr BuildNode(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; + Nz::ShaderAst::NodePtr BuildNode(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const override; void BuildNodeEdition(QFormLayout* layout) override; QString caption() const override; diff --git a/src/ShaderNode/DataModels/VecValue.inl b/src/ShaderNode/DataModels/VecValue.inl index ef5ad0622..90b6ca375 100644 --- a/src/ShaderNode/DataModels/VecValue.inl +++ b/src/ShaderNode/DataModels/VecValue.inl @@ -127,7 +127,7 @@ void VecValue::BuildNodeEdition(QFormLayout* layout) } template -Nz::ShaderNodes::NodePtr VecValue::BuildNode(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count, std::size_t outputIndex) const +Nz::ShaderAst::NodePtr VecValue::BuildNode(Nz::ShaderAst::ExpressionPtr* /*expressions*/, std::size_t count, std::size_t outputIndex) const { assert(count == 0); assert(outputIndex == 0); diff --git a/src/ShaderNode/DataTypes/VecData.cpp b/src/ShaderNode/DataTypes/VecData.cpp deleted file mode 100644 index 0402864e0..000000000 --- a/src/ShaderNode/DataTypes/VecData.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include -#include -#include - -Nz::ShaderNodes::BasicType VecData::GetExpressionType() const -{ - switch (componentCount) - { - case 2: return Nz::ShaderNodes::BasicType::Float2; - case 3: return Nz::ShaderNodes::BasicType::Float3; - case 4: return Nz::ShaderNodes::BasicType::Float4; - default: - break; - } - - assert(false); - throw std::runtime_error("invalid component count"); -} diff --git a/src/ShaderNode/DataTypes/VecData.hpp b/src/ShaderNode/DataTypes/VecData.hpp index f6e1bfdd9..44ef84e67 100644 --- a/src/ShaderNode/DataTypes/VecData.hpp +++ b/src/ShaderNode/DataTypes/VecData.hpp @@ -13,43 +13,12 @@ struct VecData : public QtNodes::NodeData inline QtNodes::NodeDataType type() const override; - Nz::ShaderNodes::BasicType GetExpressionType() const; - static inline QtNodes::NodeDataType Type(); std::size_t componentCount; PreviewValues preview; }; -template -struct VecExpressionTypeHelper; - -template<> -struct VecExpressionTypeHelper<1> -{ - static constexpr Nz::ShaderNodes::BasicType ExpressionType = Nz::ShaderNodes::BasicType::Float1; -}; - -template<> -struct VecExpressionTypeHelper<2> -{ - static constexpr Nz::ShaderNodes::BasicType ExpressionType = Nz::ShaderNodes::BasicType::Float2; -}; - -template<> -struct VecExpressionTypeHelper<3> -{ - static constexpr Nz::ShaderNodes::BasicType ExpressionType = Nz::ShaderNodes::BasicType::Float3; -}; - -template<> -struct VecExpressionTypeHelper<4> -{ - static constexpr Nz::ShaderNodes::BasicType ExpressionType = Nz::ShaderNodes::BasicType::Float4; -}; - -template constexpr Nz::ShaderNodes::BasicType VecExpressionType = VecExpressionTypeHelper::ExpressionType; - struct VecTypeDummy {}; diff --git a/src/ShaderNode/ShaderGraph.cpp b/src/ShaderNode/ShaderGraph.cpp index 68e11685f..3e3fa273c 100644 --- a/src/ShaderNode/ShaderGraph.cpp +++ b/src/ShaderNode/ShaderGraph.cpp @@ -1,5 +1,7 @@ #include #include +#include +#include #include #include #include @@ -45,6 +47,12 @@ namespace auto creator = [&] { return std::make_unique(graph); }; registry->registerModel(category, std::move(creator)); } + + template + std::unique_ptr static_unique_pointer_cast(std::unique_ptr&& ptr) + { + return std::unique_ptr(static_cast(ptr.release())); + } } ShaderGraph::ShaderGraph() : @@ -442,157 +450,29 @@ QJsonObject ShaderGraph::Save() return sceneJson; } -Nz::ShaderNodes::StatementPtr ShaderGraph::ToAst() const +Nz::ShaderAst::StatementPtr ShaderGraph::ToAst() const { - std::vector statements; + std::vector statements; - using Key = QPair; - auto BuildKey = [](QUuid uuid, std::size_t index) + // Declare all structures + for (const auto& structInfo : m_structs) { - return Key(uuid, index); - }; + Nz::ShaderAst::StructDescription structDesc; + structDesc.layout = Nz::StructLayout_Std140; + structDesc.name = structInfo.name; - QHash usageCount; - - std::function DetectVariables; - DetectVariables = [&](QtNodes::Node* node, std::size_t outputIndex) - { - auto it = usageCount.find(BuildKey(node->id(), outputIndex)); - if (it == usageCount.end()) + for (const auto& memberInfo : structInfo.members) { - for (const auto& connectionSet : node->nodeState().getEntries(QtNodes::PortType::In)) - { - for (const auto& [uuid, conn] : connectionSet) - { - DetectVariables(conn->getNode(QtNodes::PortType::Out), conn->getPortIndex(QtNodes::PortType::Out)); - } - } - - it = usageCount.insert(BuildKey(node->id(), outputIndex), 0); + auto& structMember = structDesc.members.emplace_back(); + structMember.name = memberInfo.name; + structMember.type = ToShaderExpressionType(memberInfo.type); } - (*it)++; - }; - - std::vector outputNodes; - - m_flowScene.iterateOverNodes([&](QtNodes::Node* node) - { - if (node->nodeDataModel()->nPorts(QtNodes::PortType::Out) == 0) - { - DetectVariables(node, 0); - outputNodes.push_back(node); - } - }); - - QHash variableExpressions; - - unsigned int varCount = 0; - std::unordered_set usedVariableNames; - - std::function HandleNode; - HandleNode = [&](QtNodes::Node* node, std::size_t portIndex) -> Nz::ShaderNodes::NodePtr - { - ShaderNode* shaderNode = static_cast(node->nodeDataModel()); - if (shaderNode->validationState() != QtNodes::NodeValidationState::Valid) - throw std::runtime_error(shaderNode->validationMessage().toStdString()); - - qDebug() << shaderNode->name() << node->id(); - if (auto it = variableExpressions.find(BuildKey(node->id(), portIndex)); it != variableExpressions.end()) - return *it; - - auto it = usageCount.find(BuildKey(node->id(), portIndex)); - assert(it != usageCount.end()); - - std::size_t inputCount = shaderNode->nPorts(QtNodes::PortType::In); - Nz::StackArray expressions = NazaraStackArray(Nz::ShaderNodes::ExpressionPtr, inputCount); - std::size_t i = 0; - - for (const auto& connectionSet : node->nodeState().getEntries(QtNodes::PortType::In)) - { - for (const auto& [uuid, conn] : connectionSet) - { - assert(i < expressions.size()); - Nz::ShaderNodes::NodePtr inputNode = HandleNode(conn->getNode(QtNodes::PortType::Out), conn->getPortIndex(QtNodes::PortType::Out)); - if (inputNode->IsStatement()) - throw std::runtime_error("unexpected statement"); - - expressions[i] = std::static_pointer_cast(inputNode); - i++; - } - } - - auto astNode = shaderNode->BuildNode(expressions.data(), expressions.size(), portIndex); - - const std::string& variableName = shaderNode->GetVariableName(); - if (*it > 1 || !variableName.empty()) - { - if (astNode->IsStatement()) - throw std::runtime_error("unexpected statement"); - - auto expression = std::static_pointer_cast(astNode); - - Nz::ShaderNodes::ExpressionPtr varExpression; - if (Nz::GetExpressionCategory(expression) == Nz::ShaderNodes::ExpressionCategory::RValue) - { - std::string name; - if (variableName.empty()) - name = "var" + std::to_string(varCount++); - else - name = variableName; - - if (usedVariableNames.find(name) != usedVariableNames.end()) - throw std::runtime_error("duplicate variable found: " + name); - - usedVariableNames.insert(name); - - auto variable = Nz::ShaderBuilder::Local(std::move(name), expression->GetExpressionType()); - statements.emplace_back(Nz::ShaderBuilder::DeclareVariable(variable, std::move(expression))); - - varExpression = Nz::ShaderBuilder::Identifier(variable); - } - else - varExpression = std::move(expression); - - variableExpressions.insert(BuildKey(node->id(), portIndex), varExpression); - - return varExpression; - } - else - return astNode; - }; - - std::sort(outputNodes.begin(), outputNodes.end(), [](QtNodes::Node* lhs, QtNodes::Node* rhs) - { - ShaderNode* leftNode = static_cast(lhs->nodeDataModel()); - ShaderNode* rightNode = static_cast(rhs->nodeDataModel()); - - return leftNode->GetOutputOrder() < rightNode->GetOutputOrder(); - }); - - for (QtNodes::Node* node : outputNodes) - { - auto astNode = HandleNode(node, 0); - if (!astNode->IsStatement()) - statements.emplace_back(Nz::ShaderBuilder::ExprStatement(std::static_pointer_cast(astNode))); - else - statements.emplace_back(std::static_pointer_cast(astNode)); + statements.push_back(Nz::ShaderBuilder::DeclareStruct(std::move(structDesc))); } - return Nz::ShaderNodes::StatementBlock::Build(std::move(statements)); -} - -Nz::ShaderAst ShaderGraph::ToShader() const -{ - Nz::ShaderAst shader(ShaderGraph::ToShaderStageType(m_type)); //< FIXME - for (const auto& condition : m_conditions) - shader.AddCondition(condition.name); - - for (const auto& input : m_inputs) - shader.AddInput(input.name, ToShaderExpressionType(input.type), input.locationIndex); - - for (const auto& output : m_outputs) - shader.AddOutput(output.name, ToShaderExpressionType(output.type), output.locationIndex); + // External block + auto external = std::make_unique(); for (const auto& buffer : m_buffers) { @@ -600,46 +480,74 @@ Nz::ShaderAst ShaderGraph::ToShader() const throw std::runtime_error("buffer " + buffer.name + " references out-of-bounds struct #" + std::to_string(buffer.structIndex)); const auto& structInfo = m_structs[buffer.structIndex]; - shader.AddUniform(buffer.name, structInfo.name, buffer.bindingIndex, Nz::ShaderNodes::MemoryLayout::Std140); + + auto& extVar = external->externalVars.emplace_back(); + extVar.bindingIndex = buffer.bindingIndex; + extVar.name = buffer.name; + extVar.type = Nz::ShaderAst::IdentifierType{ structInfo.name }; } - for (const auto& uniform : m_textures) - shader.AddUniform(uniform.name, ToShaderExpressionType(uniform.type), uniform.bindingIndex, {}); - - for (const auto& s : m_structs) + for (const auto& texture : m_textures) { - std::vector members; - for (const auto& sMember : s.members) + auto& extVar = external->externalVars.emplace_back(); + extVar.bindingIndex = texture.bindingIndex; + extVar.name = texture.name; + extVar.type = ToShaderExpressionType(texture.type); + } + + if (!external->externalVars.empty()) + statements.push_back(std::move(external)); + + // Inputs / outputs + if (!m_inputs.empty()) + { + Nz::ShaderAst::StructDescription structDesc; + structDesc.name = "InputData"; + + for (const auto& input : m_inputs) { - auto& member = members.emplace_back(); - member.name = sMember.name; - - std::visit([&](auto&& arg) - { - using T = std::decay_t; - if constexpr (std::is_same_v) - member.type = ToShaderExpressionType(arg); - else if constexpr (std::is_same_v) - { - if (arg >= m_structs.size()) - throw std::runtime_error("struct " + s.name + " references out-of-bounds struct #" + std::to_string(arg)); - - member.type = m_structs[arg].name; - } - else - static_assert(AlwaysFalse::value, "non-exhaustive visitor"); - }, sMember.type); + auto& structMember = structDesc.members.emplace_back(); + structMember.name = input.name; + structMember.type = ToShaderExpressionType(input.type); + structMember.locationIndex = input.locationIndex; } - shader.AddStruct(s.name, std::move(members)); + statements.push_back(Nz::ShaderBuilder::DeclareStruct(std::move(structDesc))); } - return shader; + Nz::ShaderAst::ExpressionType returnType; + if (!m_outputs.empty()) + { + Nz::ShaderAst::StructDescription structDesc; + structDesc.name = "OutputData"; + + for (const auto& output : m_outputs) + { + auto& structMember = structDesc.members.emplace_back(); + structMember.name = output.name; + structMember.type = ToShaderExpressionType(output.type); + structMember.locationIndex = output.locationIndex; + } + + if (m_type == ShaderType::Vertex) + { + auto& position = structDesc.members.emplace_back(); + position.name = "position"; + position.type = Nz::ShaderAst::VectorType{ 4, Nz::ShaderAst::PrimitiveType::Float32 }; + } + + statements.push_back(Nz::ShaderBuilder::DeclareStruct(std::move(structDesc))); + } + + // Functions + statements.push_back(ToFunction()); + + return Nz::ShaderBuilder::MultiStatement(std::move(statements)); } -Nz::ShaderExpressionType ShaderGraph::ToShaderExpressionType(const std::variant& type) const +Nz::ShaderAst::ExpressionType ShaderGraph::ToShaderExpressionType(const std::variant& type) const { - return std::visit([&](auto&& arg) -> Nz::ShaderExpressionType + return std::visit([&](auto&& arg) -> Nz::ShaderAst::ExpressionType { using T = std::decay_t; if constexpr (std::is_same_v) @@ -648,7 +556,7 @@ Nz::ShaderExpressionType ShaderGraph::ToShaderExpressionType(const std::variant< { assert(arg < m_structs.size()); const auto& s = m_structs[arg]; - return s.name; + return Nz::ShaderAst::IdentifierType{ s.name }; } else static_assert(Nz::AlwaysFalse::value, "non-exhaustive visitor"); @@ -763,27 +671,27 @@ QtNodes::NodeDataType ShaderGraph::ToNodeDataType(PrimitiveType type) throw std::runtime_error("Unhandled input type"); } -Nz::ShaderExpressionType ShaderGraph::ToShaderExpressionType(PrimitiveType type) +Nz::ShaderAst::ExpressionType ShaderGraph::ToShaderExpressionType(PrimitiveType type) { switch (type) { - case PrimitiveType::Bool: return Nz::ShaderNodes::BasicType::Boolean; - case PrimitiveType::Float1: return Nz::ShaderNodes::BasicType::Float1; - case PrimitiveType::Float2: return Nz::ShaderNodes::BasicType::Float2; - case PrimitiveType::Float3: return Nz::ShaderNodes::BasicType::Float3; - case PrimitiveType::Float4: return Nz::ShaderNodes::BasicType::Float4; - case PrimitiveType::Mat4x4: return Nz::ShaderNodes::BasicType::Mat4x4; + case PrimitiveType::Bool: return Nz::ShaderAst::PrimitiveType::Boolean; + case PrimitiveType::Float1: return Nz::ShaderAst::PrimitiveType::Float32; + case PrimitiveType::Float2: return Nz::ShaderAst::VectorType{ 2, Nz::ShaderAst::PrimitiveType::Float32 }; + case PrimitiveType::Float3: return Nz::ShaderAst::VectorType{ 3, Nz::ShaderAst::PrimitiveType::Float32 }; + case PrimitiveType::Float4: return Nz::ShaderAst::VectorType{ 4, Nz::ShaderAst::PrimitiveType::Float32 }; + case PrimitiveType::Mat4x4: return Nz::ShaderAst::MatrixType{ 4, 4, Nz::ShaderAst::PrimitiveType::Float32 }; } assert(false); throw std::runtime_error("Unhandled primitive type"); } -Nz::ShaderExpressionType ShaderGraph::ToShaderExpressionType(TextureType type) +Nz::ShaderAst::ExpressionType ShaderGraph::ToShaderExpressionType(TextureType type) { switch (type) { - case TextureType::Sampler2D: return Nz::ShaderNodes::BasicType::Sampler2D; + case TextureType::Sampler2D: return Nz::ShaderAst::SamplerType{ Nz::ImageType_2D, Nz::ShaderAst::PrimitiveType::Float32 }; } assert(false); @@ -879,3 +787,158 @@ std::shared_ptr ShaderGraph::BuildRegistry() return registry; } + +std::unique_ptr ShaderGraph::ToFunction() const +{ + std::vector statements; + + std::vector parameters; + if (!m_inputs.empty()) + { + parameters.push_back({ + "input", + Nz::ShaderAst::IdentifierType{ "InputData" } + }); + } + + Nz::ShaderAst::ExpressionType returnType; + if (!m_outputs.empty()) + { + returnType = Nz::ShaderAst::IdentifierType{ "OutputData" }; + + statements.push_back(Nz::ShaderBuilder::DeclareVariable("output", returnType)); + } + + using Key = QPair; + auto BuildKey = [](QUuid uuid, std::size_t index) + { + return Key(uuid, index); + }; + + std::map usageCount; + + std::function DetectVariables; + DetectVariables = [&](QtNodes::Node* node, std::size_t outputIndex) + { + auto it = usageCount.find(BuildKey(node->id(), outputIndex)); + if (it == usageCount.end()) + { + for (const auto& connectionSet : node->nodeState().getEntries(QtNodes::PortType::In)) + { + for (const auto& [uuid, conn] : connectionSet) + { + DetectVariables(conn->getNode(QtNodes::PortType::Out), conn->getPortIndex(QtNodes::PortType::Out)); + } + } + + it = usageCount.emplace(BuildKey(node->id(), outputIndex), 0).first; + } + + it->second++; + }; + + std::vector outputNodes; + + m_flowScene.iterateOverNodes([&](QtNodes::Node* node) + { + if (node->nodeDataModel()->nPorts(QtNodes::PortType::Out) == 0) + { + DetectVariables(node, 0); + outputNodes.push_back(node); + } + }); + + std::map variableExpressions; + + unsigned int varCount = 0; + std::unordered_set usedVariableNames; + + std::function HandleNode; + HandleNode = [&](QtNodes::Node* node, std::size_t portIndex) -> Nz::ShaderAst::NodePtr + { + ShaderNode* shaderNode = static_cast(node->nodeDataModel()); + if (shaderNode->validationState() != QtNodes::NodeValidationState::Valid) + throw std::runtime_error(shaderNode->validationMessage().toStdString()); + + qDebug() << shaderNode->name() << node->id(); + if (auto it = variableExpressions.find(BuildKey(node->id(), portIndex)); it != variableExpressions.end()) + return Nz::ShaderAst::Clone(it->second); + + auto it = usageCount.find(BuildKey(node->id(), portIndex)); + assert(it != usageCount.end()); + + std::size_t inputCount = shaderNode->nPorts(QtNodes::PortType::In); + Nz::StackArray expressions = NazaraStackArray(Nz::ShaderAst::ExpressionPtr, inputCount); + std::size_t i = 0; + + for (const auto& connectionSet : node->nodeState().getEntries(QtNodes::PortType::In)) + { + for (const auto& [uuid, conn] : connectionSet) + { + assert(i < expressions.size()); + Nz::ShaderAst::NodePtr inputNode = HandleNode(conn->getNode(QtNodes::PortType::Out), conn->getPortIndex(QtNodes::PortType::Out)); + if (!Nz::ShaderAst::IsExpression(inputNode->GetType())) + throw std::runtime_error("unexpected statement"); + + expressions[i] = static_unique_pointer_cast(std::move(inputNode)); + i++; + } + } + + auto astNode = shaderNode->BuildNode(expressions.data(), expressions.size(), portIndex); + if (!Nz::ShaderAst::IsExpression(astNode->GetType())) + return astNode; + + Nz::ShaderAst::ExpressionPtr expression = static_unique_pointer_cast(std::move(astNode)); + + const std::string& variableName = shaderNode->GetVariableName(); + if (it->second > 1 || !variableName.empty()) + { + Nz::ShaderAst::ExpressionPtr varExpression; + if (Nz::ShaderAst::GetExpressionCategory(*expression) == Nz::ShaderAst::ExpressionCategory::RValue) + { + std::string name; + if (variableName.empty()) + name = "var" + std::to_string(varCount++); + else + name = variableName; + + if (usedVariableNames.find(name) != usedVariableNames.end()) + throw std::runtime_error("duplicate variable found: " + name); + + usedVariableNames.insert(name); + + statements.emplace_back(Nz::ShaderBuilder::DeclareVariable(name, std::move(expression))); + + varExpression = Nz::ShaderBuilder::Identifier(name); + } + else + varExpression = std::move(expression); + + variableExpressions[BuildKey(node->id(), portIndex)] = Nz::ShaderAst::Clone(varExpression); + + return varExpression; + } + else + return expression; + }; + + std::sort(outputNodes.begin(), outputNodes.end(), [](QtNodes::Node* lhs, QtNodes::Node* rhs) + { + ShaderNode* leftNode = static_cast(lhs->nodeDataModel()); + ShaderNode* rightNode = static_cast(rhs->nodeDataModel()); + + return leftNode->GetOutputOrder() < rightNode->GetOutputOrder(); + }); + + for (QtNodes::Node* node : outputNodes) + { + auto astNode = HandleNode(node, 0); + if (!Nz::ShaderAst::IsStatement(astNode->GetType())) + statements.emplace_back(Nz::ShaderBuilder::ExpressionStatement(static_unique_pointer_cast(std::move(astNode)))); + else + statements.emplace_back(static_unique_pointer_cast(std::move(astNode))); + } + + return Nz::ShaderBuilder::DeclareFunction(ToShaderStageType(m_type), "main", std::move(parameters), std::move(statements), std::move(returnType)); +} diff --git a/src/ShaderNode/ShaderGraph.hpp b/src/ShaderNode/ShaderGraph.hpp index 1ca776305..19dcb6813 100644 --- a/src/ShaderNode/ShaderGraph.hpp +++ b/src/ShaderNode/ShaderGraph.hpp @@ -5,7 +5,6 @@ #include #include -#include #include #include #include @@ -67,9 +66,8 @@ class ShaderGraph void Load(const QJsonObject& data); QJsonObject Save(); - Nz::ShaderNodes::StatementPtr ToAst() const; - Nz::ShaderAst ToShader() const; - Nz::ShaderExpressionType ToShaderExpressionType(const std::variant& type) const; + Nz::ShaderAst::StatementPtr ToAst() const; + Nz::ShaderAst::ExpressionType ToShaderExpressionType(const std::variant& type) const; void UpdateBuffer(std::size_t bufferIndex, std::string name, BufferType bufferType, std::size_t structIndex, std::size_t bindingIndex); void UpdateCondition(std::size_t conditionIndex, std::string condition); @@ -147,12 +145,13 @@ class ShaderGraph NazaraSignal(OnTypeUpdated, ShaderGraph*); static QtNodes::NodeDataType ToNodeDataType(PrimitiveType type); - static Nz::ShaderExpressionType ToShaderExpressionType(PrimitiveType type); - static Nz::ShaderExpressionType ToShaderExpressionType(TextureType type); + static Nz::ShaderAst::ExpressionType ToShaderExpressionType(PrimitiveType type); + static Nz::ShaderAst::ExpressionType ToShaderExpressionType(TextureType type); static Nz::ShaderStageType ToShaderStageType(ShaderType type); private: std::shared_ptr BuildRegistry(); + std::unique_ptr ToFunction() const; mutable QtNodes::FlowScene m_flowScene; std::vector m_buffers; diff --git a/src/ShaderNode/Widgets/CodeOutputWidget.cpp b/src/ShaderNode/Widgets/CodeOutputWidget.cpp index 73e9c7d3f..9e20057e1 100644 --- a/src/ShaderNode/Widgets/CodeOutputWidget.cpp +++ b/src/ShaderNode/Widgets/CodeOutputWidget.cpp @@ -58,17 +58,14 @@ void CodeOutputWidget::Refresh() enabledConditions = Nz::SetBit(enabledConditions, i); } - Nz::ShaderAst shaderAst = m_shaderGraph.ToShader(); + Nz::ShaderAst::StatementPtr shaderAst = m_shaderGraph.ToAst(); - Nz::ShaderNodes::StatementPtr mainAst = m_shaderGraph.ToAst(); if (m_optimisationCheckbox->isChecked()) { - Nz::ShaderAstOptimizer optimiser; - mainAst = optimiser.Optimise(mainAst, shaderAst, enabledConditions); + Nz::ShaderAst::AstOptimizer optimiser; + shaderAst = optimiser.Optimise(shaderAst, enabledConditions); } - shaderAst.AddFunction("main", mainAst); - Nz::ShaderWriter::States states; states.enabledConditions = enabledConditions; @@ -79,7 +76,7 @@ void CodeOutputWidget::Refresh() case OutputLanguage::GLSL: { Nz::GlslWriter writer; - output = writer.Generate(shaderAst, states); + output = writer.Generate(ShaderGraph::ToShaderStageType(m_shaderGraph.GetType()), shaderAst, states); break; } diff --git a/src/ShaderNode/Widgets/CodeOutputWidget.hpp b/src/ShaderNode/Widgets/CodeOutputWidget.hpp index ecea4d54b..47945ca34 100644 --- a/src/ShaderNode/Widgets/CodeOutputWidget.hpp +++ b/src/ShaderNode/Widgets/CodeOutputWidget.hpp @@ -3,7 +3,6 @@ #ifndef NAZARA_SHADERNODES_CODEOUTPUTWIDGET_HPP #define NAZARA_SHADERNODES_CODEOUTPUTWIDGET_HPP -#include #include #include diff --git a/src/ShaderNode/Widgets/MainWindow.cpp b/src/ShaderNode/Widgets/MainWindow.cpp index 67b50dd91..5777964b2 100644 --- a/src/ShaderNode/Widgets/MainWindow.cpp +++ b/src/ShaderNode/Widgets/MainWindow.cpp @@ -181,8 +181,7 @@ void MainWindow::OnCompile() { try { - auto shader = m_shaderGraph.ToShader(); - shader.AddFunction("main", m_shaderGraph.ToAst()); + auto shader = m_shaderGraph.ToAst(); QString fileName = QFileDialog::getSaveFileName(nullptr, tr("Save shader"), QString(), tr("Shader Files (*.shader)")); if (fileName.isEmpty()) @@ -192,7 +191,7 @@ void MainWindow::OnCompile() fileName += ".shader"; Nz::File file(fileName.toStdString(), Nz::OpenMode_WriteOnly); - file.Write(Nz::SerializeShader(shader)); + file.Write(Nz::ShaderAst::SerializeShader(shader)); } catch (const std::exception& e) { diff --git a/src/ShaderNode/Widgets/MainWindow.hpp b/src/ShaderNode/Widgets/MainWindow.hpp index 1031eca9a..eaedd6aea 100644 --- a/src/ShaderNode/Widgets/MainWindow.hpp +++ b/src/ShaderNode/Widgets/MainWindow.hpp @@ -9,11 +9,6 @@ class NodeEditor; -namespace Nz -{ - class ShaderAst; -} - class MainWindow : public QMainWindow { public: