From a02dd3bf052af7effa4a83423c64b6a90deaf7a9 Mon Sep 17 00:00:00 2001 From: Lynix Date: Wed, 29 Jul 2020 14:31:54 +0200 Subject: [PATCH] Renderer: Add ShaderRecursiveVisitor --- .../Renderer/ShaderRecursiveVisitor.hpp | 42 +++++++++ .../Renderer/ShaderRecursiveVisitor.inl | 12 +++ include/Nazara/Renderer/ShaderValidator.hpp | 6 +- .../Renderer/ShaderRecursiveVisitor.cpp | 93 +++++++++++++++++++ src/Nazara/Renderer/ShaderValidator.cpp | 36 +++---- 5 files changed, 169 insertions(+), 20 deletions(-) create mode 100644 include/Nazara/Renderer/ShaderRecursiveVisitor.hpp create mode 100644 include/Nazara/Renderer/ShaderRecursiveVisitor.inl create mode 100644 src/Nazara/Renderer/ShaderRecursiveVisitor.cpp diff --git a/include/Nazara/Renderer/ShaderRecursiveVisitor.hpp b/include/Nazara/Renderer/ShaderRecursiveVisitor.hpp new file mode 100644 index 000000000..0e1087a58 --- /dev/null +++ b/include/Nazara/Renderer/ShaderRecursiveVisitor.hpp @@ -0,0 +1,42 @@ +// Copyright (C) 2020 Jérôme Leclercq +// This file is part of the "Nazara Engine - Renderer module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_SHADER_RECURSIVE_VISITOR_HPP +#define NAZARA_SHADER_RECURSIVE_VISITOR_HPP + +#include +#include +#include + +namespace Nz +{ + class NAZARA_RENDERER_API ShaderRecursiveVisitor : public ShaderVisitor + { + public: + ShaderRecursiveVisitor() = default; + ~ShaderRecursiveVisitor() = default; + + using ShaderVisitor::Visit; + + void Visit(const ShaderNodes::AccessMember& node) override; + void Visit(const ShaderNodes::AssignOp& node) override; + void Visit(const ShaderNodes::BinaryOp& node) override; + void Visit(const ShaderNodes::Branch& node) override; + void Visit(const ShaderNodes::Cast& node) override; + void Visit(const ShaderNodes::Constant& node) override; + void Visit(const ShaderNodes::DeclareVariable& node) override; + void Visit(const ShaderNodes::ExpressionStatement& node) override; + void Visit(const ShaderNodes::Identifier& node) override; + void Visit(const ShaderNodes::IntrinsicCall& node) override; + void Visit(const ShaderNodes::Sample2D& node) override; + void Visit(const ShaderNodes::StatementBlock& node) override; + void Visit(const ShaderNodes::SwizzleOp& node) override; + }; +} + +#include + +#endif diff --git a/include/Nazara/Renderer/ShaderRecursiveVisitor.inl b/include/Nazara/Renderer/ShaderRecursiveVisitor.inl new file mode 100644 index 000000000..b107f06e7 --- /dev/null +++ b/include/Nazara/Renderer/ShaderRecursiveVisitor.inl @@ -0,0 +1,12 @@ +// Copyright (C) 2020 Jérôme Leclercq +// This file is part of the "Nazara Engine - Renderer module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ +} + +#include diff --git a/include/Nazara/Renderer/ShaderValidator.hpp b/include/Nazara/Renderer/ShaderValidator.hpp index 09015b073..237ecaa73 100644 --- a/include/Nazara/Renderer/ShaderValidator.hpp +++ b/include/Nazara/Renderer/ShaderValidator.hpp @@ -12,11 +12,11 @@ #include #include #include -#include +#include namespace Nz { - class NAZARA_RENDERER_API ShaderValidator : public ShaderVisitor + class NAZARA_RENDERER_API ShaderValidator : public ShaderRecursiveVisitor { public: inline ShaderValidator(const ShaderAst& shader); @@ -32,7 +32,7 @@ namespace Nz void TypeMustMatch(const ShaderNodes::ExpressionPtr& left, const ShaderNodes::ExpressionPtr& right); void TypeMustMatch(const ShaderExpressionType& left, const ShaderExpressionType& right); - using ShaderVisitor::Visit; + using ShaderRecursiveVisitor::Visit; void Visit(const ShaderNodes::AccessMember& node) override; void Visit(const ShaderNodes::AssignOp& node) override; void Visit(const ShaderNodes::BinaryOp& node) override; diff --git a/src/Nazara/Renderer/ShaderRecursiveVisitor.cpp b/src/Nazara/Renderer/ShaderRecursiveVisitor.cpp new file mode 100644 index 000000000..2116da21c --- /dev/null +++ b/src/Nazara/Renderer/ShaderRecursiveVisitor.cpp @@ -0,0 +1,93 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Renderer module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ + void ShaderRecursiveVisitor::Visit(const ShaderNodes::AccessMember& node) + { + Visit(node.structExpr); + } + + void ShaderRecursiveVisitor::Visit(const ShaderNodes::AssignOp& node) + { + Visit(node.left); + Visit(node.right); + } + + void ShaderRecursiveVisitor::Visit(const ShaderNodes::BinaryOp& node) + { + Visit(node.left); + Visit(node.right); + } + + void ShaderRecursiveVisitor::Visit(const ShaderNodes::Branch& node) + { + for (auto& cond : node.condStatements) + { + Visit(cond.condition); + Visit(cond.statement); + } + + if (node.elseStatement) + Visit(node.elseStatement); + } + + void ShaderRecursiveVisitor::Visit(const ShaderNodes::Cast& node) + { + for (auto& expr : node.expressions) + { + if (!expr) + break; + + Visit(expr); + } + } + + void ShaderRecursiveVisitor::Visit(const ShaderNodes::Constant& /*node*/) + { + /* Nothing to do */ + } + + void ShaderRecursiveVisitor::Visit(const ShaderNodes::DeclareVariable& node) + { + if (node.expression) + Visit(node.expression); + } + + void ShaderRecursiveVisitor::Visit(const ShaderNodes::ExpressionStatement& node) + { + Visit(node.expression); + } + + void ShaderRecursiveVisitor::Visit(const ShaderNodes::Identifier& /*node*/) + { + /* Nothing to do */ + } + + void ShaderRecursiveVisitor::Visit(const ShaderNodes::IntrinsicCall& node) + { + for (auto& param : node.parameters) + Visit(param); + } + + void ShaderRecursiveVisitor::Visit(const ShaderNodes::Sample2D& node) + { + Visit(node.sampler); + Visit(node.coordinates); + } + + void ShaderRecursiveVisitor::Visit(const ShaderNodes::StatementBlock& node) + { + for (auto& statement : node.statements) + Visit(statement); + } + + void ShaderRecursiveVisitor::Visit(const ShaderNodes::SwizzleOp& node) + { + Visit(node.expression); + } +} diff --git a/src/Nazara/Renderer/ShaderValidator.cpp b/src/Nazara/Renderer/ShaderValidator.cpp index c181ecd62..01f038217 100644 --- a/src/Nazara/Renderer/ShaderValidator.cpp +++ b/src/Nazara/Renderer/ShaderValidator.cpp @@ -114,8 +114,7 @@ namespace Nz if (node.left->GetExpressionCategory() != ShaderNodes::ExpressionCategory::LValue) throw AstError { "Assignation is only possible with a l-value" }; - Visit(node.left); - Visit(node.right); + ShaderRecursiveVisitor::Visit(node); } void ShaderValidator::Visit(const ShaderNodes::BinaryOp& node) @@ -187,17 +186,18 @@ namespace Nz } } - Visit(node.left); - Visit(node.right); + ShaderRecursiveVisitor::Visit(node); } void ShaderValidator::Visit(const ShaderNodes::Branch& node) { for (const auto& condStatement : node.condStatements) { - Visit(MandatoryNode(condStatement.condition)); - Visit(MandatoryNode(condStatement.statement)); + MandatoryNode(condStatement.condition); + MandatoryNode(condStatement.statement); } + + ShaderRecursiveVisitor::Visit(node); } void ShaderValidator::Visit(const ShaderNodes::Cast& node) @@ -214,11 +214,12 @@ namespace Nz throw AstError{ "incompatible type" }; componentCount += node.GetComponentCount(std::get(exprType)); - Visit(exprPtr); } if (componentCount != requiredComponents) throw AstError{ "Component count doesn't match required component count" }; + + ShaderRecursiveVisitor::Visit(node); } void ShaderValidator::Visit(const ShaderNodes::Constant& /*node*/) @@ -229,17 +230,18 @@ namespace Nz { assert(m_context); - if (node.expression) - Visit(node.expression); - auto& local = m_context->declaredLocals.emplace_back(); local.name = node.variable->name; local.type = node.variable->type; + + ShaderRecursiveVisitor::Visit(node); } void ShaderValidator::Visit(const ShaderNodes::ExpressionStatement& node) { - Visit(MandatoryNode(node.expression)); + MandatoryNode(node.expression); + + ShaderRecursiveVisitor::Visit(node); } void ShaderValidator::Visit(const ShaderNodes::Identifier& node) @@ -377,8 +379,7 @@ namespace Nz break; } - for (auto& param : node.parameters) - Visit(param); + ShaderRecursiveVisitor::Visit(node); } void ShaderValidator::Visit(const ShaderNodes::Sample2D& node) @@ -389,8 +390,7 @@ namespace Nz if (MandatoryExpr(node.coordinates)->GetExpressionType() != ShaderExpressionType{ ShaderNodes::BasicType::Float2 }) throw AstError{ "Coordinates must be a Float2" }; - Visit(node.sampler); - Visit(node.coordinates); + ShaderRecursiveVisitor::Visit(node); } void ShaderValidator::Visit(const ShaderNodes::StatementBlock& node) @@ -400,11 +400,13 @@ namespace Nz m_context->blockLocalIndex.push_back(m_context->declaredLocals.size()); for (const auto& statement : node.statements) - Visit(MandatoryNode(statement)); + MandatoryNode(statement); assert(m_context->declaredLocals.size() >= m_context->blockLocalIndex.back()); m_context->declaredLocals.resize(m_context->blockLocalIndex.back()); m_context->blockLocalIndex.pop_back(); + + ShaderRecursiveVisitor::Visit(node); } void ShaderValidator::Visit(const ShaderNodes::SwizzleOp& node) @@ -428,7 +430,7 @@ namespace Nz throw AstError{ "Cannot swizzle this type" }; } - Visit(node.expression); + ShaderRecursiveVisitor::Visit(node); } bool ValidateShader(const ShaderAst& shader, std::string* error)