Refactor SpirV classes
SpirvStatementVisitor was merged with SpirvExpressionLoad SpirvExpressionLoadAccessMember was renamed SpirvExpressionLoad
This commit is contained in:
parent
6c379eff68
commit
77b66620c9
|
|
@ -0,0 +1,58 @@
|
||||||
|
// Copyright (C) 2020 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Engine - Shader generator"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef NAZARA_SPIRVEXPRESSIONLOAD_HPP
|
||||||
|
#define NAZARA_SPIRVEXPRESSIONLOAD_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Prerequisites.hpp>
|
||||||
|
#include <Nazara/Shader/Config.hpp>
|
||||||
|
#include <Nazara/Shader/ShaderAstVisitorExcept.hpp>
|
||||||
|
#include <Nazara/Shader/ShaderVarVisitorExcept.hpp>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace Nz
|
||||||
|
{
|
||||||
|
class SpirvWriter;
|
||||||
|
|
||||||
|
class NAZARA_SHADER_API SpirvAstVisitor : public ShaderAstVisitorExcept
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
inline SpirvAstVisitor(SpirvWriter& writer);
|
||||||
|
SpirvAstVisitor(const SpirvAstVisitor&) = delete;
|
||||||
|
SpirvAstVisitor(SpirvAstVisitor&&) = delete;
|
||||||
|
~SpirvAstVisitor() = default;
|
||||||
|
|
||||||
|
UInt32 EvaluateExpression(const ShaderNodes::ExpressionPtr& expr);
|
||||||
|
|
||||||
|
using ShaderAstVisitorExcept::Visit;
|
||||||
|
void Visit(ShaderNodes::AccessMember& node) override;
|
||||||
|
void Visit(ShaderNodes::AssignOp& node) override;
|
||||||
|
void Visit(ShaderNodes::BinaryOp& node) override;
|
||||||
|
void Visit(ShaderNodes::Cast& node) override;
|
||||||
|
void Visit(ShaderNodes::Constant& node) override;
|
||||||
|
void Visit(ShaderNodes::DeclareVariable& node) override;
|
||||||
|
void Visit(ShaderNodes::ExpressionStatement& node) override;
|
||||||
|
void Visit(ShaderNodes::Identifier& node) override;
|
||||||
|
void Visit(ShaderNodes::IntrinsicCall& node) override;
|
||||||
|
void Visit(ShaderNodes::Sample2D& node) override;
|
||||||
|
void Visit(ShaderNodes::StatementBlock& node) override;
|
||||||
|
void Visit(ShaderNodes::SwizzleOp& node) override;
|
||||||
|
|
||||||
|
SpirvAstVisitor& operator=(const SpirvAstVisitor&) = delete;
|
||||||
|
SpirvAstVisitor& operator=(SpirvAstVisitor&&) = delete;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void PushResultId(UInt32 value);
|
||||||
|
UInt32 PopResultId();
|
||||||
|
|
||||||
|
std::vector<UInt32> m_resultIds;
|
||||||
|
SpirvWriter& m_writer;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <Nazara/Shader/SpirvAstVisitor.inl>
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -2,12 +2,12 @@
|
||||||
// This file is part of the "Nazara Engine - Shader generator"
|
// This file is part of the "Nazara Engine - Shader generator"
|
||||||
// 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/SpirvStatementVisitor.hpp>
|
#include <Nazara/Shader/SpirvAstVisitor.hpp>
|
||||||
#include <Nazara/Shader/Debug.hpp>
|
#include <Nazara/Shader/Debug.hpp>
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
inline SpirvStatementVisitor::SpirvStatementVisitor(SpirvWriter& writer) :
|
inline SpirvAstVisitor::SpirvAstVisitor(SpirvWriter& writer) :
|
||||||
m_writer(writer)
|
m_writer(writer)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -4,13 +4,14 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifndef NAZARA_SPIRVEXPRESSIONLOAD_HPP
|
#ifndef NAZARA_SPIRVEXPRESSIONLOADACCESSMEMBER_HPP
|
||||||
#define NAZARA_SPIRVEXPRESSIONLOAD_HPP
|
#define NAZARA_SPIRVEXPRESSIONLOADACCESSMEMBER_HPP
|
||||||
|
|
||||||
#include <Nazara/Prerequisites.hpp>
|
#include <Nazara/Prerequisites.hpp>
|
||||||
#include <Nazara/Shader/Config.hpp>
|
#include <Nazara/Shader/Config.hpp>
|
||||||
#include <Nazara/Shader/ShaderAstVisitorExcept.hpp>
|
#include <Nazara/Shader/ShaderAstVisitorExcept.hpp>
|
||||||
#include <Nazara/Shader/ShaderVarVisitorExcept.hpp>
|
#include <Nazara/Shader/ShaderVarVisitorExcept.hpp>
|
||||||
|
#include <Nazara/Shader/SpirvData.hpp>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
|
|
@ -25,37 +26,35 @@ namespace Nz
|
||||||
SpirvExpressionLoad(SpirvExpressionLoad&&) = delete;
|
SpirvExpressionLoad(SpirvExpressionLoad&&) = delete;
|
||||||
~SpirvExpressionLoad() = default;
|
~SpirvExpressionLoad() = default;
|
||||||
|
|
||||||
UInt32 EvaluateExpression(const ShaderNodes::ExpressionPtr& expr);
|
UInt32 Evaluate(ShaderNodes::Expression& node);
|
||||||
|
|
||||||
using ShaderAstVisitorExcept::Visit;
|
using ShaderAstVisitor::Visit;
|
||||||
void Visit(ShaderNodes::AccessMember& node) override;
|
void Visit(ShaderNodes::AccessMember& node) override;
|
||||||
void Visit(ShaderNodes::AssignOp& node) override;
|
|
||||||
void Visit(ShaderNodes::BinaryOp& node) override;
|
|
||||||
void Visit(ShaderNodes::Cast& node) override;
|
|
||||||
void Visit(ShaderNodes::Constant& node) override;
|
|
||||||
void Visit(ShaderNodes::DeclareVariable& node) override;
|
|
||||||
void Visit(ShaderNodes::ExpressionStatement& node) override;
|
|
||||||
void Visit(ShaderNodes::Identifier& node) override;
|
void Visit(ShaderNodes::Identifier& node) override;
|
||||||
void Visit(ShaderNodes::IntrinsicCall& node) override;
|
|
||||||
void Visit(ShaderNodes::Sample2D& node) override;
|
|
||||||
void Visit(ShaderNodes::SwizzleOp& node) override;
|
|
||||||
|
|
||||||
using ShaderVarVisitorExcept::Visit;
|
using ShaderVarVisitor::Visit;
|
||||||
void Visit(ShaderNodes::BuiltinVariable& var) override;
|
|
||||||
void Visit(ShaderNodes::InputVariable& var) override;
|
void Visit(ShaderNodes::InputVariable& var) override;
|
||||||
void Visit(ShaderNodes::LocalVariable& var) override;
|
void Visit(ShaderNodes::LocalVariable& var) override;
|
||||||
void Visit(ShaderNodes::ParameterVariable& var) override;
|
|
||||||
void Visit(ShaderNodes::UniformVariable& var) override;
|
void Visit(ShaderNodes::UniformVariable& var) override;
|
||||||
|
|
||||||
SpirvExpressionLoad& operator=(const SpirvExpressionLoad&) = delete;
|
SpirvExpressionLoad& operator=(const SpirvExpressionLoad&) = delete;
|
||||||
SpirvExpressionLoad& operator=(SpirvExpressionLoad&&) = delete;
|
SpirvExpressionLoad& operator=(SpirvExpressionLoad&&) = delete;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void PushResultId(UInt32 value);
|
struct Pointer
|
||||||
UInt32 PopResultId();
|
{
|
||||||
|
SpirvStorageClass storage;
|
||||||
|
UInt32 resultId;
|
||||||
|
UInt32 pointedTypeId;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Value
|
||||||
|
{
|
||||||
|
UInt32 resultId;
|
||||||
|
};
|
||||||
|
|
||||||
std::vector<UInt32> m_resultIds;
|
|
||||||
SpirvWriter& m_writer;
|
SpirvWriter& m_writer;
|
||||||
|
std::variant<std::monostate, Pointer, Value> m_value;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,62 +0,0 @@
|
||||||
// Copyright (C) 2020 Jérôme Leclercq
|
|
||||||
// This file is part of the "Nazara Engine - Shader generator"
|
|
||||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#ifndef NAZARA_SPIRVEXPRESSIONLOADACCESSMEMBER_HPP
|
|
||||||
#define NAZARA_SPIRVEXPRESSIONLOADACCESSMEMBER_HPP
|
|
||||||
|
|
||||||
#include <Nazara/Prerequisites.hpp>
|
|
||||||
#include <Nazara/Shader/Config.hpp>
|
|
||||||
#include <Nazara/Shader/ShaderAstVisitorExcept.hpp>
|
|
||||||
#include <Nazara/Shader/ShaderVarVisitorExcept.hpp>
|
|
||||||
#include <Nazara/Shader/SpirvData.hpp>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace Nz
|
|
||||||
{
|
|
||||||
class SpirvWriter;
|
|
||||||
|
|
||||||
class NAZARA_SHADER_API SpirvExpressionLoadAccessMember : public ShaderAstVisitorExcept, public ShaderVarVisitorExcept
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
inline SpirvExpressionLoadAccessMember(SpirvWriter& writer);
|
|
||||||
SpirvExpressionLoadAccessMember(const SpirvExpressionLoadAccessMember&) = delete;
|
|
||||||
SpirvExpressionLoadAccessMember(SpirvExpressionLoadAccessMember&&) = delete;
|
|
||||||
~SpirvExpressionLoadAccessMember() = default;
|
|
||||||
|
|
||||||
UInt32 EvaluateExpression(ShaderNodes::AccessMember& expr);
|
|
||||||
|
|
||||||
using ShaderAstVisitor::Visit;
|
|
||||||
void Visit(ShaderNodes::AccessMember& node) override;
|
|
||||||
void Visit(ShaderNodes::Identifier& node) override;
|
|
||||||
|
|
||||||
using ShaderVarVisitor::Visit;
|
|
||||||
void Visit(ShaderNodes::InputVariable& var) override;
|
|
||||||
void Visit(ShaderNodes::UniformVariable& var) override;
|
|
||||||
|
|
||||||
SpirvExpressionLoadAccessMember& operator=(const SpirvExpressionLoadAccessMember&) = delete;
|
|
||||||
SpirvExpressionLoadAccessMember& operator=(SpirvExpressionLoadAccessMember&&) = delete;
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct Pointer
|
|
||||||
{
|
|
||||||
SpirvStorageClass storage;
|
|
||||||
UInt32 resultId;
|
|
||||||
UInt32 pointedTypeId;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Value
|
|
||||||
{
|
|
||||||
UInt32 resultId;
|
|
||||||
};
|
|
||||||
|
|
||||||
SpirvWriter& m_writer;
|
|
||||||
std::variant<std::monostate, Pointer, Value> m_value;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#include <Nazara/Shader/SpirvExpressionLoadAccessMember.inl>
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
// Copyright (C) 2020 Jérôme Leclercq
|
|
||||||
// This file is part of the "Nazara Engine - Shader generator"
|
|
||||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
|
||||||
|
|
||||||
#include <Nazara/Shader/SpirvExpressionLoadAccessMember.hpp>
|
|
||||||
#include <Nazara/Shader/Debug.hpp>
|
|
||||||
|
|
||||||
namespace Nz
|
|
||||||
{
|
|
||||||
inline SpirvExpressionLoadAccessMember::SpirvExpressionLoadAccessMember(SpirvWriter& writer) :
|
|
||||||
m_writer(writer)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#include <Nazara/Shader/DebugOff.hpp>
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
||||||
// Copyright (C) 2020 Jérôme Leclercq
|
|
||||||
// This file is part of the "Nazara Engine - Shader generator"
|
|
||||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#ifndef NAZARA_SPIRVSTATEMENTVISITOR_HPP
|
|
||||||
#define NAZARA_SPIRVSTATEMENTVISITOR_HPP
|
|
||||||
|
|
||||||
#include <Nazara/Prerequisites.hpp>
|
|
||||||
#include <Nazara/Shader/Config.hpp>
|
|
||||||
#include <Nazara/Shader/ShaderAstVisitorExcept.hpp>
|
|
||||||
|
|
||||||
namespace Nz
|
|
||||||
{
|
|
||||||
class SpirvWriter;
|
|
||||||
|
|
||||||
class NAZARA_SHADER_API SpirvStatementVisitor : public ShaderAstVisitorExcept
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
inline SpirvStatementVisitor(SpirvWriter& writer);
|
|
||||||
SpirvStatementVisitor(const SpirvStatementVisitor&) = delete;
|
|
||||||
SpirvStatementVisitor(SpirvStatementVisitor&&) = delete;
|
|
||||||
~SpirvStatementVisitor() = default;
|
|
||||||
|
|
||||||
using ShaderAstVisitor::Visit;
|
|
||||||
void Visit(ShaderNodes::AssignOp& node) override;
|
|
||||||
void Visit(ShaderNodes::Branch& node) override;
|
|
||||||
void Visit(ShaderNodes::DeclareVariable& node) override;
|
|
||||||
void Visit(ShaderNodes::ExpressionStatement& node) override;
|
|
||||||
void Visit(ShaderNodes::StatementBlock& node) override;
|
|
||||||
|
|
||||||
SpirvStatementVisitor& operator=(const SpirvStatementVisitor&) = delete;
|
|
||||||
SpirvStatementVisitor& operator=(SpirvStatementVisitor&&) = delete;
|
|
||||||
|
|
||||||
private:
|
|
||||||
SpirvWriter& m_writer;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#include <Nazara/Shader/SpirvStatementVisitor.inl>
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -25,10 +25,10 @@ namespace Nz
|
||||||
|
|
||||||
class NAZARA_SHADER_API SpirvWriter
|
class NAZARA_SHADER_API SpirvWriter
|
||||||
{
|
{
|
||||||
|
friend class SpirvAstVisitor;
|
||||||
friend class SpirvExpressionLoad;
|
friend class SpirvExpressionLoad;
|
||||||
friend class SpirvExpressionLoadAccessMember;
|
|
||||||
friend class SpirvExpressionStore;
|
friend class SpirvExpressionStore;
|
||||||
friend class SpirvStatementVisitor;
|
friend class SpirvVisitor;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct Environment;
|
struct Environment;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,433 @@
|
||||||
|
// Copyright (C) 2020 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Engine - Shader generator"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#include <Nazara/Shader/SpirvAstVisitor.hpp>
|
||||||
|
#include <Nazara/Core/StackVector.hpp>
|
||||||
|
#include <Nazara/Shader/SpirvSection.hpp>
|
||||||
|
#include <Nazara/Shader/SpirvExpressionLoad.hpp>
|
||||||
|
#include <Nazara/Shader/SpirvExpressionStore.hpp>
|
||||||
|
#include <Nazara/Shader/SpirvWriter.hpp>
|
||||||
|
#include <Nazara/Shader/Debug.hpp>
|
||||||
|
|
||||||
|
namespace Nz
|
||||||
|
{
|
||||||
|
UInt32 SpirvAstVisitor::EvaluateExpression(const ShaderNodes::ExpressionPtr& expr)
|
||||||
|
{
|
||||||
|
Visit(expr);
|
||||||
|
return PopResultId();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpirvAstVisitor::Visit(ShaderNodes::AccessMember& node)
|
||||||
|
{
|
||||||
|
SpirvExpressionLoad accessMemberVisitor(m_writer);
|
||||||
|
PushResultId(accessMemberVisitor.Evaluate(node));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpirvAstVisitor::Visit(ShaderNodes::AssignOp& node)
|
||||||
|
{
|
||||||
|
UInt32 resultId = EvaluateExpression(node.right);
|
||||||
|
|
||||||
|
SpirvExpressionStore storeVisitor(m_writer);
|
||||||
|
storeVisitor.Store(node.left, resultId);
|
||||||
|
|
||||||
|
PushResultId(resultId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpirvAstVisitor::Visit(ShaderNodes::BinaryOp& node)
|
||||||
|
{
|
||||||
|
ShaderExpressionType resultExprType = node.GetExpressionType();
|
||||||
|
assert(std::holds_alternative<ShaderNodes::BasicType>(resultExprType));
|
||||||
|
|
||||||
|
const ShaderExpressionType& leftExprType = node.left->GetExpressionType();
|
||||||
|
assert(std::holds_alternative<ShaderNodes::BasicType>(leftExprType));
|
||||||
|
|
||||||
|
const ShaderExpressionType& rightExprType = node.right->GetExpressionType();
|
||||||
|
assert(std::holds_alternative<ShaderNodes::BasicType>(rightExprType));
|
||||||
|
|
||||||
|
ShaderNodes::BasicType resultType = std::get<ShaderNodes::BasicType>(resultExprType);
|
||||||
|
ShaderNodes::BasicType leftType = std::get<ShaderNodes::BasicType>(leftExprType);
|
||||||
|
ShaderNodes::BasicType rightType = std::get<ShaderNodes::BasicType>(rightExprType);
|
||||||
|
|
||||||
|
|
||||||
|
UInt32 leftOperand = EvaluateExpression(node.left);
|
||||||
|
UInt32 rightOperand = EvaluateExpression(node.right);
|
||||||
|
UInt32 resultId = m_writer.AllocateResultId();
|
||||||
|
|
||||||
|
bool swapOperands = false;
|
||||||
|
|
||||||
|
SpirvOp op = [&]
|
||||||
|
{
|
||||||
|
switch (node.op)
|
||||||
|
{
|
||||||
|
case ShaderNodes::BinaryType::Add:
|
||||||
|
{
|
||||||
|
switch (leftType)
|
||||||
|
{
|
||||||
|
case ShaderNodes::BasicType::Float1:
|
||||||
|
case ShaderNodes::BasicType::Float2:
|
||||||
|
case ShaderNodes::BasicType::Float3:
|
||||||
|
case ShaderNodes::BasicType::Float4:
|
||||||
|
case ShaderNodes::BasicType::Mat4x4:
|
||||||
|
return SpirvOp::OpFAdd;
|
||||||
|
|
||||||
|
case ShaderNodes::BasicType::Int1:
|
||||||
|
case ShaderNodes::BasicType::Int2:
|
||||||
|
case ShaderNodes::BasicType::Int3:
|
||||||
|
case ShaderNodes::BasicType::Int4:
|
||||||
|
case ShaderNodes::BasicType::UInt1:
|
||||||
|
case ShaderNodes::BasicType::UInt2:
|
||||||
|
case ShaderNodes::BasicType::UInt3:
|
||||||
|
case ShaderNodes::BasicType::UInt4:
|
||||||
|
return SpirvOp::OpIAdd;
|
||||||
|
|
||||||
|
case ShaderNodes::BasicType::Boolean:
|
||||||
|
case ShaderNodes::BasicType::Sampler2D:
|
||||||
|
case ShaderNodes::BasicType::Void:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case ShaderNodes::BinaryType::Substract:
|
||||||
|
{
|
||||||
|
switch (leftType)
|
||||||
|
{
|
||||||
|
case ShaderNodes::BasicType::Float1:
|
||||||
|
case ShaderNodes::BasicType::Float2:
|
||||||
|
case ShaderNodes::BasicType::Float3:
|
||||||
|
case ShaderNodes::BasicType::Float4:
|
||||||
|
case ShaderNodes::BasicType::Mat4x4:
|
||||||
|
return SpirvOp::OpFSub;
|
||||||
|
|
||||||
|
case ShaderNodes::BasicType::Int1:
|
||||||
|
case ShaderNodes::BasicType::Int2:
|
||||||
|
case ShaderNodes::BasicType::Int3:
|
||||||
|
case ShaderNodes::BasicType::Int4:
|
||||||
|
case ShaderNodes::BasicType::UInt1:
|
||||||
|
case ShaderNodes::BasicType::UInt2:
|
||||||
|
case ShaderNodes::BasicType::UInt3:
|
||||||
|
case ShaderNodes::BasicType::UInt4:
|
||||||
|
return SpirvOp::OpISub;
|
||||||
|
|
||||||
|
case ShaderNodes::BasicType::Boolean:
|
||||||
|
case ShaderNodes::BasicType::Sampler2D:
|
||||||
|
case ShaderNodes::BasicType::Void:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case ShaderNodes::BinaryType::Divide:
|
||||||
|
{
|
||||||
|
switch (leftType)
|
||||||
|
{
|
||||||
|
case ShaderNodes::BasicType::Float1:
|
||||||
|
case ShaderNodes::BasicType::Float2:
|
||||||
|
case ShaderNodes::BasicType::Float3:
|
||||||
|
case ShaderNodes::BasicType::Float4:
|
||||||
|
case ShaderNodes::BasicType::Mat4x4:
|
||||||
|
return SpirvOp::OpFDiv;
|
||||||
|
|
||||||
|
case ShaderNodes::BasicType::Int1:
|
||||||
|
case ShaderNodes::BasicType::Int2:
|
||||||
|
case ShaderNodes::BasicType::Int3:
|
||||||
|
case ShaderNodes::BasicType::Int4:
|
||||||
|
return SpirvOp::OpSDiv;
|
||||||
|
|
||||||
|
case ShaderNodes::BasicType::UInt1:
|
||||||
|
case ShaderNodes::BasicType::UInt2:
|
||||||
|
case ShaderNodes::BasicType::UInt3:
|
||||||
|
case ShaderNodes::BasicType::UInt4:
|
||||||
|
return SpirvOp::OpUDiv;
|
||||||
|
|
||||||
|
case ShaderNodes::BasicType::Boolean:
|
||||||
|
case ShaderNodes::BasicType::Sampler2D:
|
||||||
|
case ShaderNodes::BasicType::Void:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case ShaderNodes::BinaryType::Equality:
|
||||||
|
{
|
||||||
|
switch (leftType)
|
||||||
|
{
|
||||||
|
case ShaderNodes::BasicType::Boolean:
|
||||||
|
return SpirvOp::OpLogicalEqual;
|
||||||
|
|
||||||
|
case ShaderNodes::BasicType::Float1:
|
||||||
|
case ShaderNodes::BasicType::Float2:
|
||||||
|
case ShaderNodes::BasicType::Float3:
|
||||||
|
case ShaderNodes::BasicType::Float4:
|
||||||
|
case ShaderNodes::BasicType::Mat4x4:
|
||||||
|
return SpirvOp::OpFOrdEqual;
|
||||||
|
|
||||||
|
case ShaderNodes::BasicType::Int1:
|
||||||
|
case ShaderNodes::BasicType::Int2:
|
||||||
|
case ShaderNodes::BasicType::Int3:
|
||||||
|
case ShaderNodes::BasicType::Int4:
|
||||||
|
case ShaderNodes::BasicType::UInt1:
|
||||||
|
case ShaderNodes::BasicType::UInt2:
|
||||||
|
case ShaderNodes::BasicType::UInt3:
|
||||||
|
case ShaderNodes::BasicType::UInt4:
|
||||||
|
return SpirvOp::OpIEqual;
|
||||||
|
|
||||||
|
case ShaderNodes::BasicType::Sampler2D:
|
||||||
|
case ShaderNodes::BasicType::Void:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case ShaderNodes::BinaryType::Multiply:
|
||||||
|
{
|
||||||
|
switch (leftType)
|
||||||
|
{
|
||||||
|
case ShaderNodes::BasicType::Float1:
|
||||||
|
{
|
||||||
|
switch (rightType)
|
||||||
|
{
|
||||||
|
case ShaderNodes::BasicType::Float1:
|
||||||
|
return SpirvOp::OpFMul;
|
||||||
|
|
||||||
|
case ShaderNodes::BasicType::Float2:
|
||||||
|
case ShaderNodes::BasicType::Float3:
|
||||||
|
case ShaderNodes::BasicType::Float4:
|
||||||
|
swapOperands = true;
|
||||||
|
return SpirvOp::OpVectorTimesScalar;
|
||||||
|
|
||||||
|
case ShaderNodes::BasicType::Mat4x4:
|
||||||
|
swapOperands = true;
|
||||||
|
return SpirvOp::OpMatrixTimesScalar;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ShaderNodes::BasicType::Float2:
|
||||||
|
case ShaderNodes::BasicType::Float3:
|
||||||
|
case ShaderNodes::BasicType::Float4:
|
||||||
|
{
|
||||||
|
switch (rightType)
|
||||||
|
{
|
||||||
|
case ShaderNodes::BasicType::Float1:
|
||||||
|
return SpirvOp::OpVectorTimesScalar;
|
||||||
|
|
||||||
|
case ShaderNodes::BasicType::Float2:
|
||||||
|
case ShaderNodes::BasicType::Float3:
|
||||||
|
case ShaderNodes::BasicType::Float4:
|
||||||
|
return SpirvOp::OpFMul;
|
||||||
|
|
||||||
|
case ShaderNodes::BasicType::Mat4x4:
|
||||||
|
return SpirvOp::OpVectorTimesMatrix;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ShaderNodes::BasicType::Int1:
|
||||||
|
case ShaderNodes::BasicType::Int2:
|
||||||
|
case ShaderNodes::BasicType::Int3:
|
||||||
|
case ShaderNodes::BasicType::Int4:
|
||||||
|
case ShaderNodes::BasicType::UInt1:
|
||||||
|
case ShaderNodes::BasicType::UInt2:
|
||||||
|
case ShaderNodes::BasicType::UInt3:
|
||||||
|
case ShaderNodes::BasicType::UInt4:
|
||||||
|
return SpirvOp::OpIMul;
|
||||||
|
|
||||||
|
case ShaderNodes::BasicType::Mat4x4:
|
||||||
|
{
|
||||||
|
switch (rightType)
|
||||||
|
{
|
||||||
|
case ShaderNodes::BasicType::Float1: return SpirvOp::OpMatrixTimesScalar;
|
||||||
|
case ShaderNodes::BasicType::Float4: return SpirvOp::OpMatrixTimesVector;
|
||||||
|
case ShaderNodes::BasicType::Mat4x4: return SpirvOp::OpMatrixTimesMatrix;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(false);
|
||||||
|
throw std::runtime_error("unexpected binary operation");
|
||||||
|
}();
|
||||||
|
|
||||||
|
if (swapOperands)
|
||||||
|
std::swap(leftOperand, rightOperand);
|
||||||
|
|
||||||
|
m_writer.GetInstructions().Append(op, m_writer.GetTypeId(resultType), resultId, leftOperand, rightOperand);
|
||||||
|
PushResultId(resultId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpirvAstVisitor::Visit(ShaderNodes::Cast& node)
|
||||||
|
{
|
||||||
|
const ShaderExpressionType& targetExprType = node.exprType;
|
||||||
|
assert(std::holds_alternative<ShaderNodes::BasicType>(targetExprType));
|
||||||
|
|
||||||
|
ShaderNodes::BasicType targetType = std::get<ShaderNodes::BasicType>(targetExprType);
|
||||||
|
|
||||||
|
StackVector<UInt32> exprResults = NazaraStackVector(UInt32, node.expressions.size());
|
||||||
|
|
||||||
|
for (const auto& exprPtr : node.expressions)
|
||||||
|
{
|
||||||
|
if (!exprPtr)
|
||||||
|
break;
|
||||||
|
|
||||||
|
exprResults.push_back(EvaluateExpression(exprPtr));
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt32 resultId = m_writer.AllocateResultId();
|
||||||
|
|
||||||
|
m_writer.GetInstructions().AppendVariadic(SpirvOp::OpCompositeConstruct, [&](const auto& appender)
|
||||||
|
{
|
||||||
|
appender(m_writer.GetTypeId(targetType));
|
||||||
|
appender(resultId);
|
||||||
|
|
||||||
|
for (UInt32 exprResultId : exprResults)
|
||||||
|
appender(exprResultId);
|
||||||
|
});
|
||||||
|
|
||||||
|
PushResultId(resultId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpirvAstVisitor::Visit(ShaderNodes::Constant& node)
|
||||||
|
{
|
||||||
|
std::visit([&] (const auto& value)
|
||||||
|
{
|
||||||
|
PushResultId(m_writer.GetConstantId(value));
|
||||||
|
}, node.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpirvAstVisitor::Visit(ShaderNodes::DeclareVariable& node)
|
||||||
|
{
|
||||||
|
if (node.expression)
|
||||||
|
{
|
||||||
|
assert(node.variable->GetType() == ShaderNodes::VariableType::LocalVariable);
|
||||||
|
|
||||||
|
const auto& localVar = static_cast<const ShaderNodes::LocalVariable&>(*node.variable);
|
||||||
|
m_writer.WriteLocalVariable(localVar.name, EvaluateExpression(node.expression));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpirvAstVisitor::Visit(ShaderNodes::ExpressionStatement& node)
|
||||||
|
{
|
||||||
|
Visit(node.expression);
|
||||||
|
PopResultId();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpirvAstVisitor::Visit(ShaderNodes::Identifier& node)
|
||||||
|
{
|
||||||
|
SpirvExpressionLoad loadVisitor(m_writer);
|
||||||
|
PushResultId(loadVisitor.Evaluate(node));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpirvAstVisitor::Visit(ShaderNodes::IntrinsicCall& node)
|
||||||
|
{
|
||||||
|
switch (node.intrinsic)
|
||||||
|
{
|
||||||
|
case ShaderNodes::IntrinsicType::DotProduct:
|
||||||
|
{
|
||||||
|
const ShaderExpressionType& vecExprType = node.parameters[0]->GetExpressionType();
|
||||||
|
assert(std::holds_alternative<ShaderNodes::BasicType>(vecExprType));
|
||||||
|
|
||||||
|
ShaderNodes::BasicType vecType = std::get<ShaderNodes::BasicType>(vecExprType);
|
||||||
|
|
||||||
|
UInt32 typeId = m_writer.GetTypeId(node.GetComponentType(vecType));
|
||||||
|
|
||||||
|
UInt32 vec1 = EvaluateExpression(node.parameters[0]);
|
||||||
|
UInt32 vec2 = EvaluateExpression(node.parameters[1]);
|
||||||
|
|
||||||
|
UInt32 resultId = m_writer.AllocateResultId();
|
||||||
|
|
||||||
|
m_writer.GetInstructions().Append(SpirvOp::OpDot, typeId, resultId, vec1, vec2);
|
||||||
|
PushResultId(resultId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ShaderNodes::IntrinsicType::CrossProduct:
|
||||||
|
default:
|
||||||
|
throw std::runtime_error("not yet implemented");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpirvAstVisitor::Visit(ShaderNodes::Sample2D& node)
|
||||||
|
{
|
||||||
|
UInt32 typeId = m_writer.GetTypeId(ShaderNodes::BasicType::Float4);
|
||||||
|
|
||||||
|
UInt32 samplerId = EvaluateExpression(node.sampler);
|
||||||
|
UInt32 coordinatesId = EvaluateExpression(node.coordinates);
|
||||||
|
UInt32 resultId = m_writer.AllocateResultId();
|
||||||
|
|
||||||
|
m_writer.GetInstructions().Append(SpirvOp::OpImageSampleImplicitLod, typeId, resultId, samplerId, coordinatesId);
|
||||||
|
PushResultId(resultId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpirvAstVisitor::Visit(ShaderNodes::StatementBlock& node)
|
||||||
|
{
|
||||||
|
for (auto& statement : node.statements)
|
||||||
|
Visit(statement);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpirvAstVisitor::Visit(ShaderNodes::SwizzleOp& node)
|
||||||
|
{
|
||||||
|
const ShaderExpressionType& targetExprType = node.GetExpressionType();
|
||||||
|
assert(std::holds_alternative<ShaderNodes::BasicType>(targetExprType));
|
||||||
|
|
||||||
|
ShaderNodes::BasicType targetType = std::get<ShaderNodes::BasicType>(targetExprType);
|
||||||
|
|
||||||
|
UInt32 exprResultId = EvaluateExpression(node.expression);
|
||||||
|
UInt32 resultId = m_writer.AllocateResultId();
|
||||||
|
|
||||||
|
if (node.componentCount > 1)
|
||||||
|
{
|
||||||
|
// Swizzling is implemented via SpirvOp::OpVectorShuffle using the same vector twice as operands
|
||||||
|
m_writer.GetInstructions().AppendVariadic(SpirvOp::OpVectorShuffle, [&](const auto& appender)
|
||||||
|
{
|
||||||
|
appender(m_writer.GetTypeId(targetType));
|
||||||
|
appender(resultId);
|
||||||
|
appender(exprResultId);
|
||||||
|
appender(exprResultId);
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < node.componentCount; ++i)
|
||||||
|
appender(UInt32(node.components[0]) - UInt32(node.components[i]));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Extract a single component from the vector
|
||||||
|
assert(node.componentCount == 1);
|
||||||
|
|
||||||
|
m_writer.GetInstructions().Append(SpirvOp::OpCompositeExtract, m_writer.GetTypeId(targetType), resultId, exprResultId, UInt32(node.components[0]) - UInt32(ShaderNodes::SwizzleComponent::First) );
|
||||||
|
}
|
||||||
|
|
||||||
|
PushResultId(resultId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpirvAstVisitor::PushResultId(UInt32 value)
|
||||||
|
{
|
||||||
|
m_resultIds.push_back(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt32 SpirvAstVisitor::PopResultId()
|
||||||
|
{
|
||||||
|
if (m_resultIds.empty())
|
||||||
|
throw std::runtime_error("invalid operation");
|
||||||
|
|
||||||
|
UInt32 resultId = m_resultIds.back();
|
||||||
|
m_resultIds.pop_back();
|
||||||
|
|
||||||
|
return resultId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,317 +5,88 @@
|
||||||
#include <Nazara/Shader/SpirvExpressionLoad.hpp>
|
#include <Nazara/Shader/SpirvExpressionLoad.hpp>
|
||||||
#include <Nazara/Core/StackVector.hpp>
|
#include <Nazara/Core/StackVector.hpp>
|
||||||
#include <Nazara/Shader/SpirvSection.hpp>
|
#include <Nazara/Shader/SpirvSection.hpp>
|
||||||
#include <Nazara/Shader/SpirvExpressionLoadAccessMember.hpp>
|
|
||||||
#include <Nazara/Shader/SpirvExpressionStore.hpp>
|
|
||||||
#include <Nazara/Shader/SpirvWriter.hpp>
|
#include <Nazara/Shader/SpirvWriter.hpp>
|
||||||
#include <Nazara/Shader/Debug.hpp>
|
#include <Nazara/Shader/Debug.hpp>
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
|
||||||
|
template<class... Ts> overloaded(Ts...)->overloaded<Ts...>;
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt32 SpirvExpressionLoad::Evaluate(ShaderNodes::Expression& node)
|
||||||
|
{
|
||||||
|
node.Visit(*this);
|
||||||
|
|
||||||
|
return std::visit(overloaded
|
||||||
|
{
|
||||||
|
[&](const Pointer& pointer) -> UInt32
|
||||||
|
{
|
||||||
|
UInt32 resultId = m_writer.AllocateResultId();
|
||||||
|
|
||||||
|
m_writer.GetInstructions().Append(SpirvOp::OpLoad, pointer.pointedTypeId, resultId, pointer.resultId);
|
||||||
|
|
||||||
|
return resultId;
|
||||||
|
},
|
||||||
|
[&](const Value& value) -> UInt32
|
||||||
|
{
|
||||||
|
return value.resultId;
|
||||||
|
},
|
||||||
|
[this](std::monostate) -> UInt32
|
||||||
|
{
|
||||||
|
throw std::runtime_error("an internal error occurred");
|
||||||
|
}
|
||||||
|
}, m_value);
|
||||||
|
}
|
||||||
|
|
||||||
void SpirvExpressionLoad::Visit(ShaderNodes::AccessMember& node)
|
void SpirvExpressionLoad::Visit(ShaderNodes::AccessMember& node)
|
||||||
{
|
{
|
||||||
SpirvExpressionLoadAccessMember accessMemberVisitor(m_writer);
|
Visit(node.structExpr);
|
||||||
PushResultId(accessMemberVisitor.EvaluateExpression(node));
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpirvExpressionLoad::Visit(ShaderNodes::AssignOp& node)
|
std::visit(overloaded
|
||||||
{
|
{
|
||||||
SpirvExpressionLoad loadVisitor(m_writer);
|
[&](const Pointer& pointer)
|
||||||
SpirvExpressionStore storeVisitor(m_writer);
|
|
||||||
storeVisitor.Store(node.left, EvaluateExpression(node.right));
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpirvExpressionLoad::Visit(ShaderNodes::BinaryOp& node)
|
|
||||||
{
|
{
|
||||||
ShaderExpressionType resultExprType = node.GetExpressionType();
|
|
||||||
assert(std::holds_alternative<ShaderNodes::BasicType>(resultExprType));
|
|
||||||
|
|
||||||
const ShaderExpressionType& leftExprType = node.left->GetExpressionType();
|
|
||||||
assert(std::holds_alternative<ShaderNodes::BasicType>(leftExprType));
|
|
||||||
|
|
||||||
const ShaderExpressionType& rightExprType = node.right->GetExpressionType();
|
|
||||||
assert(std::holds_alternative<ShaderNodes::BasicType>(rightExprType));
|
|
||||||
|
|
||||||
ShaderNodes::BasicType resultType = std::get<ShaderNodes::BasicType>(resultExprType);
|
|
||||||
ShaderNodes::BasicType leftType = std::get<ShaderNodes::BasicType>(leftExprType);
|
|
||||||
ShaderNodes::BasicType rightType = std::get<ShaderNodes::BasicType>(rightExprType);
|
|
||||||
|
|
||||||
|
|
||||||
UInt32 leftOperand = EvaluateExpression(node.left);
|
|
||||||
UInt32 rightOperand = EvaluateExpression(node.right);
|
|
||||||
UInt32 resultId = m_writer.AllocateResultId();
|
UInt32 resultId = m_writer.AllocateResultId();
|
||||||
|
UInt32 pointerType = m_writer.RegisterPointerType(node.exprType, pointer.storage); //< FIXME
|
||||||
|
UInt32 typeId = m_writer.GetTypeId(node.exprType);
|
||||||
|
|
||||||
bool swapOperands = false;
|
m_writer.GetInstructions().AppendVariadic(SpirvOp::OpAccessChain, [&](const auto& appender)
|
||||||
|
|
||||||
SpirvOp op = [&]
|
|
||||||
{
|
{
|
||||||
switch (node.op)
|
appender(pointerType);
|
||||||
{
|
|
||||||
case ShaderNodes::BinaryType::Add:
|
|
||||||
{
|
|
||||||
switch (leftType)
|
|
||||||
{
|
|
||||||
case ShaderNodes::BasicType::Float1:
|
|
||||||
case ShaderNodes::BasicType::Float2:
|
|
||||||
case ShaderNodes::BasicType::Float3:
|
|
||||||
case ShaderNodes::BasicType::Float4:
|
|
||||||
case ShaderNodes::BasicType::Mat4x4:
|
|
||||||
return SpirvOp::OpFAdd;
|
|
||||||
|
|
||||||
case ShaderNodes::BasicType::Int1:
|
|
||||||
case ShaderNodes::BasicType::Int2:
|
|
||||||
case ShaderNodes::BasicType::Int3:
|
|
||||||
case ShaderNodes::BasicType::Int4:
|
|
||||||
case ShaderNodes::BasicType::UInt1:
|
|
||||||
case ShaderNodes::BasicType::UInt2:
|
|
||||||
case ShaderNodes::BasicType::UInt3:
|
|
||||||
case ShaderNodes::BasicType::UInt4:
|
|
||||||
return SpirvOp::OpIAdd;
|
|
||||||
|
|
||||||
case ShaderNodes::BasicType::Boolean:
|
|
||||||
case ShaderNodes::BasicType::Sampler2D:
|
|
||||||
case ShaderNodes::BasicType::Void:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case ShaderNodes::BinaryType::Substract:
|
|
||||||
{
|
|
||||||
switch (leftType)
|
|
||||||
{
|
|
||||||
case ShaderNodes::BasicType::Float1:
|
|
||||||
case ShaderNodes::BasicType::Float2:
|
|
||||||
case ShaderNodes::BasicType::Float3:
|
|
||||||
case ShaderNodes::BasicType::Float4:
|
|
||||||
case ShaderNodes::BasicType::Mat4x4:
|
|
||||||
return SpirvOp::OpFSub;
|
|
||||||
|
|
||||||
case ShaderNodes::BasicType::Int1:
|
|
||||||
case ShaderNodes::BasicType::Int2:
|
|
||||||
case ShaderNodes::BasicType::Int3:
|
|
||||||
case ShaderNodes::BasicType::Int4:
|
|
||||||
case ShaderNodes::BasicType::UInt1:
|
|
||||||
case ShaderNodes::BasicType::UInt2:
|
|
||||||
case ShaderNodes::BasicType::UInt3:
|
|
||||||
case ShaderNodes::BasicType::UInt4:
|
|
||||||
return SpirvOp::OpISub;
|
|
||||||
|
|
||||||
case ShaderNodes::BasicType::Boolean:
|
|
||||||
case ShaderNodes::BasicType::Sampler2D:
|
|
||||||
case ShaderNodes::BasicType::Void:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case ShaderNodes::BinaryType::Divide:
|
|
||||||
{
|
|
||||||
switch (leftType)
|
|
||||||
{
|
|
||||||
case ShaderNodes::BasicType::Float1:
|
|
||||||
case ShaderNodes::BasicType::Float2:
|
|
||||||
case ShaderNodes::BasicType::Float3:
|
|
||||||
case ShaderNodes::BasicType::Float4:
|
|
||||||
case ShaderNodes::BasicType::Mat4x4:
|
|
||||||
return SpirvOp::OpFDiv;
|
|
||||||
|
|
||||||
case ShaderNodes::BasicType::Int1:
|
|
||||||
case ShaderNodes::BasicType::Int2:
|
|
||||||
case ShaderNodes::BasicType::Int3:
|
|
||||||
case ShaderNodes::BasicType::Int4:
|
|
||||||
return SpirvOp::OpSDiv;
|
|
||||||
|
|
||||||
case ShaderNodes::BasicType::UInt1:
|
|
||||||
case ShaderNodes::BasicType::UInt2:
|
|
||||||
case ShaderNodes::BasicType::UInt3:
|
|
||||||
case ShaderNodes::BasicType::UInt4:
|
|
||||||
return SpirvOp::OpUDiv;
|
|
||||||
|
|
||||||
case ShaderNodes::BasicType::Boolean:
|
|
||||||
case ShaderNodes::BasicType::Sampler2D:
|
|
||||||
case ShaderNodes::BasicType::Void:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case ShaderNodes::BinaryType::Equality:
|
|
||||||
{
|
|
||||||
switch (leftType)
|
|
||||||
{
|
|
||||||
case ShaderNodes::BasicType::Boolean:
|
|
||||||
return SpirvOp::OpLogicalEqual;
|
|
||||||
|
|
||||||
case ShaderNodes::BasicType::Float1:
|
|
||||||
case ShaderNodes::BasicType::Float2:
|
|
||||||
case ShaderNodes::BasicType::Float3:
|
|
||||||
case ShaderNodes::BasicType::Float4:
|
|
||||||
case ShaderNodes::BasicType::Mat4x4:
|
|
||||||
return SpirvOp::OpFOrdEqual;
|
|
||||||
|
|
||||||
case ShaderNodes::BasicType::Int1:
|
|
||||||
case ShaderNodes::BasicType::Int2:
|
|
||||||
case ShaderNodes::BasicType::Int3:
|
|
||||||
case ShaderNodes::BasicType::Int4:
|
|
||||||
case ShaderNodes::BasicType::UInt1:
|
|
||||||
case ShaderNodes::BasicType::UInt2:
|
|
||||||
case ShaderNodes::BasicType::UInt3:
|
|
||||||
case ShaderNodes::BasicType::UInt4:
|
|
||||||
return SpirvOp::OpIEqual;
|
|
||||||
|
|
||||||
case ShaderNodes::BasicType::Sampler2D:
|
|
||||||
case ShaderNodes::BasicType::Void:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case ShaderNodes::BinaryType::Multiply:
|
|
||||||
{
|
|
||||||
switch (leftType)
|
|
||||||
{
|
|
||||||
case ShaderNodes::BasicType::Float1:
|
|
||||||
{
|
|
||||||
switch (rightType)
|
|
||||||
{
|
|
||||||
case ShaderNodes::BasicType::Float1:
|
|
||||||
return SpirvOp::OpFMul;
|
|
||||||
|
|
||||||
case ShaderNodes::BasicType::Float2:
|
|
||||||
case ShaderNodes::BasicType::Float3:
|
|
||||||
case ShaderNodes::BasicType::Float4:
|
|
||||||
swapOperands = true;
|
|
||||||
return SpirvOp::OpVectorTimesScalar;
|
|
||||||
|
|
||||||
case ShaderNodes::BasicType::Mat4x4:
|
|
||||||
swapOperands = true;
|
|
||||||
return SpirvOp::OpMatrixTimesScalar;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case ShaderNodes::BasicType::Float2:
|
|
||||||
case ShaderNodes::BasicType::Float3:
|
|
||||||
case ShaderNodes::BasicType::Float4:
|
|
||||||
{
|
|
||||||
switch (rightType)
|
|
||||||
{
|
|
||||||
case ShaderNodes::BasicType::Float1:
|
|
||||||
return SpirvOp::OpVectorTimesScalar;
|
|
||||||
|
|
||||||
case ShaderNodes::BasicType::Float2:
|
|
||||||
case ShaderNodes::BasicType::Float3:
|
|
||||||
case ShaderNodes::BasicType::Float4:
|
|
||||||
return SpirvOp::OpFMul;
|
|
||||||
|
|
||||||
case ShaderNodes::BasicType::Mat4x4:
|
|
||||||
return SpirvOp::OpVectorTimesMatrix;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case ShaderNodes::BasicType::Int1:
|
|
||||||
case ShaderNodes::BasicType::Int2:
|
|
||||||
case ShaderNodes::BasicType::Int3:
|
|
||||||
case ShaderNodes::BasicType::Int4:
|
|
||||||
case ShaderNodes::BasicType::UInt1:
|
|
||||||
case ShaderNodes::BasicType::UInt2:
|
|
||||||
case ShaderNodes::BasicType::UInt3:
|
|
||||||
case ShaderNodes::BasicType::UInt4:
|
|
||||||
return SpirvOp::OpIMul;
|
|
||||||
|
|
||||||
case ShaderNodes::BasicType::Mat4x4:
|
|
||||||
{
|
|
||||||
switch (rightType)
|
|
||||||
{
|
|
||||||
case ShaderNodes::BasicType::Float1: return SpirvOp::OpMatrixTimesScalar;
|
|
||||||
case ShaderNodes::BasicType::Float4: return SpirvOp::OpMatrixTimesVector;
|
|
||||||
case ShaderNodes::BasicType::Mat4x4: return SpirvOp::OpMatrixTimesMatrix;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(false);
|
|
||||||
throw std::runtime_error("unexpected binary operation");
|
|
||||||
}();
|
|
||||||
|
|
||||||
if (swapOperands)
|
|
||||||
std::swap(leftOperand, rightOperand);
|
|
||||||
|
|
||||||
m_writer.GetInstructions().Append(op, m_writer.GetTypeId(resultType), resultId, leftOperand, rightOperand);
|
|
||||||
PushResultId(resultId);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpirvExpressionLoad::Visit(ShaderNodes::Cast& node)
|
|
||||||
{
|
|
||||||
const ShaderExpressionType& targetExprType = node.exprType;
|
|
||||||
assert(std::holds_alternative<ShaderNodes::BasicType>(targetExprType));
|
|
||||||
|
|
||||||
ShaderNodes::BasicType targetType = std::get<ShaderNodes::BasicType>(targetExprType);
|
|
||||||
|
|
||||||
StackVector<UInt32> exprResults = NazaraStackVector(UInt32, node.expressions.size());
|
|
||||||
|
|
||||||
for (const auto& exprPtr : node.expressions)
|
|
||||||
{
|
|
||||||
if (!exprPtr)
|
|
||||||
break;
|
|
||||||
|
|
||||||
exprResults.push_back(EvaluateExpression(exprPtr));
|
|
||||||
}
|
|
||||||
|
|
||||||
UInt32 resultId = m_writer.AllocateResultId();
|
|
||||||
|
|
||||||
m_writer.GetInstructions().AppendVariadic(SpirvOp::OpCompositeConstruct, [&](const auto& appender)
|
|
||||||
{
|
|
||||||
appender(m_writer.GetTypeId(targetType));
|
|
||||||
appender(resultId);
|
appender(resultId);
|
||||||
|
appender(pointer.resultId);
|
||||||
|
|
||||||
for (UInt32 exprResultId : exprResults)
|
for (std::size_t index : node.memberIndices)
|
||||||
appender(exprResultId);
|
appender(m_writer.GetConstantId(Int32(index)));
|
||||||
});
|
});
|
||||||
|
|
||||||
PushResultId(resultId);
|
m_value = Pointer { pointer.storage, resultId, typeId };
|
||||||
}
|
},
|
||||||
|
[&](const Value& value)
|
||||||
|
{
|
||||||
|
UInt32 resultId = m_writer.AllocateResultId();
|
||||||
|
UInt32 typeId = m_writer.GetTypeId(node.exprType);
|
||||||
|
|
||||||
void SpirvExpressionLoad::Visit(ShaderNodes::Constant& node)
|
m_writer.GetInstructions().AppendVariadic(SpirvOp::OpCompositeExtract, [&](const auto& appender)
|
||||||
{
|
{
|
||||||
std::visit([&] (const auto& value)
|
appender(typeId);
|
||||||
{
|
appender(resultId);
|
||||||
PushResultId(m_writer.GetConstantId(value));
|
appender(value.resultId);
|
||||||
}, node.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpirvExpressionLoad::Visit(ShaderNodes::DeclareVariable& node)
|
for (std::size_t index : node.memberIndices)
|
||||||
{
|
appender(m_writer.GetConstantId(Int32(index)));
|
||||||
if (node.expression)
|
});
|
||||||
{
|
|
||||||
assert(node.variable->GetType() == ShaderNodes::VariableType::LocalVariable);
|
|
||||||
|
|
||||||
const auto& localVar = static_cast<const ShaderNodes::LocalVariable&>(*node.variable);
|
m_value = Value { resultId };
|
||||||
m_writer.WriteLocalVariable(localVar.name, EvaluateExpression(node.expression));
|
},
|
||||||
}
|
[this](std::monostate)
|
||||||
}
|
|
||||||
|
|
||||||
void SpirvExpressionLoad::Visit(ShaderNodes::ExpressionStatement& node)
|
|
||||||
{
|
{
|
||||||
Visit(node.expression);
|
throw std::runtime_error("an internal error occurred");
|
||||||
PopResultId();
|
}
|
||||||
|
}, m_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpirvExpressionLoad::Visit(ShaderNodes::Identifier& node)
|
void SpirvExpressionLoad::Visit(ShaderNodes::Identifier& node)
|
||||||
|
|
@ -323,126 +94,28 @@ namespace Nz
|
||||||
Visit(node.var);
|
Visit(node.var);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpirvExpressionLoad::Visit(ShaderNodes::IntrinsicCall& node)
|
|
||||||
{
|
|
||||||
switch (node.intrinsic)
|
|
||||||
{
|
|
||||||
case ShaderNodes::IntrinsicType::DotProduct:
|
|
||||||
{
|
|
||||||
const ShaderExpressionType& vecExprType = node.parameters[0]->GetExpressionType();
|
|
||||||
assert(std::holds_alternative<ShaderNodes::BasicType>(vecExprType));
|
|
||||||
|
|
||||||
ShaderNodes::BasicType vecType = std::get<ShaderNodes::BasicType>(vecExprType);
|
|
||||||
|
|
||||||
UInt32 typeId = m_writer.GetTypeId(node.GetComponentType(vecType));
|
|
||||||
|
|
||||||
UInt32 vec1 = EvaluateExpression(node.parameters[0]);
|
|
||||||
UInt32 vec2 = EvaluateExpression(node.parameters[1]);
|
|
||||||
|
|
||||||
UInt32 resultId = m_writer.AllocateResultId();
|
|
||||||
|
|
||||||
m_writer.GetInstructions().Append(SpirvOp::OpDot, typeId, resultId, vec1, vec2);
|
|
||||||
PushResultId(resultId);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case ShaderNodes::IntrinsicType::CrossProduct:
|
|
||||||
default:
|
|
||||||
throw std::runtime_error("not yet implemented");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpirvExpressionLoad::Visit(ShaderNodes::Sample2D& node)
|
|
||||||
{
|
|
||||||
UInt32 typeId = m_writer.GetTypeId(ShaderNodes::BasicType::Float4);
|
|
||||||
|
|
||||||
UInt32 samplerId = EvaluateExpression(node.sampler);
|
|
||||||
UInt32 coordinatesId = EvaluateExpression(node.coordinates);
|
|
||||||
UInt32 resultId = m_writer.AllocateResultId();
|
|
||||||
|
|
||||||
m_writer.GetInstructions().Append(SpirvOp::OpImageSampleImplicitLod, typeId, resultId, samplerId, coordinatesId);
|
|
||||||
PushResultId(resultId);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpirvExpressionLoad::Visit(ShaderNodes::SwizzleOp& node)
|
|
||||||
{
|
|
||||||
const ShaderExpressionType& targetExprType = node.GetExpressionType();
|
|
||||||
assert(std::holds_alternative<ShaderNodes::BasicType>(targetExprType));
|
|
||||||
|
|
||||||
ShaderNodes::BasicType targetType = std::get<ShaderNodes::BasicType>(targetExprType);
|
|
||||||
|
|
||||||
UInt32 exprResultId = EvaluateExpression(node.expression);
|
|
||||||
UInt32 resultId = m_writer.AllocateResultId();
|
|
||||||
|
|
||||||
if (node.componentCount > 1)
|
|
||||||
{
|
|
||||||
// Swizzling is implemented via SpirvOp::OpVectorShuffle using the same vector twice as operands
|
|
||||||
m_writer.GetInstructions().AppendVariadic(SpirvOp::OpVectorShuffle, [&](const auto& appender)
|
|
||||||
{
|
|
||||||
appender(m_writer.GetTypeId(targetType));
|
|
||||||
appender(resultId);
|
|
||||||
appender(exprResultId);
|
|
||||||
appender(exprResultId);
|
|
||||||
|
|
||||||
for (std::size_t i = 0; i < node.componentCount; ++i)
|
|
||||||
appender(UInt32(node.components[0]) - UInt32(node.components[i]));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Extract a single component from the vector
|
|
||||||
assert(node.componentCount == 1);
|
|
||||||
|
|
||||||
m_writer.GetInstructions().Append(SpirvOp::OpCompositeExtract, m_writer.GetTypeId(targetType), resultId, exprResultId, UInt32(node.components[0]) - UInt32(ShaderNodes::SwizzleComponent::First) );
|
|
||||||
}
|
|
||||||
|
|
||||||
PushResultId(resultId);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpirvExpressionLoad::Visit(ShaderNodes::BuiltinVariable& /*var*/)
|
|
||||||
{
|
|
||||||
throw std::runtime_error("not implemented yet");
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpirvExpressionLoad::Visit(ShaderNodes::InputVariable& var)
|
void SpirvExpressionLoad::Visit(ShaderNodes::InputVariable& var)
|
||||||
{
|
{
|
||||||
PushResultId(m_writer.ReadInputVariable(var.name));
|
auto inputVar = m_writer.GetInputVariable(var.name);
|
||||||
|
|
||||||
|
if (auto resultIdOpt = m_writer.ReadVariable(inputVar, SpirvWriter::OnlyCache{}))
|
||||||
|
m_value = Value{ *resultIdOpt };
|
||||||
|
else
|
||||||
|
m_value = Pointer{ SpirvStorageClass::Input, inputVar.varId, inputVar.typeId };
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpirvExpressionLoad::Visit(ShaderNodes::LocalVariable& var)
|
void SpirvExpressionLoad::Visit(ShaderNodes::LocalVariable& var)
|
||||||
{
|
{
|
||||||
PushResultId(m_writer.ReadLocalVariable(var.name));
|
m_value = Value{ m_writer.ReadLocalVariable(var.name) };
|
||||||
}
|
|
||||||
|
|
||||||
void SpirvExpressionLoad::Visit(ShaderNodes::ParameterVariable& /*var*/)
|
|
||||||
{
|
|
||||||
throw std::runtime_error("not implemented yet");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpirvExpressionLoad::Visit(ShaderNodes::UniformVariable& var)
|
void SpirvExpressionLoad::Visit(ShaderNodes::UniformVariable& var)
|
||||||
{
|
{
|
||||||
PushResultId(m_writer.ReadUniformVariable(var.name));
|
auto uniformVar = m_writer.GetUniformVariable(var.name);
|
||||||
}
|
|
||||||
|
|
||||||
UInt32 SpirvExpressionLoad::EvaluateExpression(const ShaderNodes::ExpressionPtr& expr)
|
if (auto resultIdOpt = m_writer.ReadVariable(uniformVar, SpirvWriter::OnlyCache{}))
|
||||||
{
|
m_value = Value{ *resultIdOpt };
|
||||||
Visit(expr);
|
else
|
||||||
return PopResultId();
|
m_value = Pointer{ SpirvStorageClass::Uniform, uniformVar.varId, uniformVar.typeId };
|
||||||
}
|
|
||||||
|
|
||||||
void SpirvExpressionLoad::PushResultId(UInt32 value)
|
|
||||||
{
|
|
||||||
m_resultIds.push_back(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
UInt32 SpirvExpressionLoad::PopResultId()
|
|
||||||
{
|
|
||||||
if (m_resultIds.empty())
|
|
||||||
throw std::runtime_error("invalid operation");
|
|
||||||
|
|
||||||
UInt32 resultId = m_resultIds.back();
|
|
||||||
m_resultIds.pop_back();
|
|
||||||
|
|
||||||
return resultId;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,116 +0,0 @@
|
||||||
// Copyright (C) 2020 Jérôme Leclercq
|
|
||||||
// This file is part of the "Nazara Engine - Shader generator"
|
|
||||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
|
||||||
|
|
||||||
#include <Nazara/Shader/SpirvExpressionLoadAccessMember.hpp>
|
|
||||||
#include <Nazara/Core/StackVector.hpp>
|
|
||||||
#include <Nazara/Shader/SpirvSection.hpp>
|
|
||||||
#include <Nazara/Shader/SpirvWriter.hpp>
|
|
||||||
#include <Nazara/Shader/Debug.hpp>
|
|
||||||
|
|
||||||
namespace Nz
|
|
||||||
{
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
|
|
||||||
template<class... Ts> overloaded(Ts...)->overloaded<Ts...>;
|
|
||||||
}
|
|
||||||
|
|
||||||
UInt32 SpirvExpressionLoadAccessMember::EvaluateExpression(ShaderNodes::AccessMember& expr)
|
|
||||||
{
|
|
||||||
Visit(expr);
|
|
||||||
|
|
||||||
return std::visit(overloaded
|
|
||||||
{
|
|
||||||
[&](const Pointer& pointer) -> UInt32
|
|
||||||
{
|
|
||||||
UInt32 resultId = m_writer.AllocateResultId();
|
|
||||||
|
|
||||||
m_writer.GetInstructions().Append(SpirvOp::OpLoad, pointer.pointedTypeId, resultId, pointer.resultId);
|
|
||||||
|
|
||||||
return resultId;
|
|
||||||
},
|
|
||||||
[&](const Value& value) -> UInt32
|
|
||||||
{
|
|
||||||
return value.resultId;
|
|
||||||
},
|
|
||||||
[this](std::monostate) -> UInt32
|
|
||||||
{
|
|
||||||
throw std::runtime_error("an internal error occurred");
|
|
||||||
}
|
|
||||||
}, m_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpirvExpressionLoadAccessMember::Visit(ShaderNodes::AccessMember& node)
|
|
||||||
{
|
|
||||||
Visit(node.structExpr);
|
|
||||||
|
|
||||||
std::visit(overloaded
|
|
||||||
{
|
|
||||||
[&](const Pointer& pointer)
|
|
||||||
{
|
|
||||||
UInt32 resultId = m_writer.AllocateResultId();
|
|
||||||
UInt32 pointerType = m_writer.RegisterPointerType(node.exprType, pointer.storage); //< FIXME
|
|
||||||
UInt32 typeId = m_writer.GetTypeId(node.exprType);
|
|
||||||
|
|
||||||
m_writer.GetInstructions().AppendVariadic(SpirvOp::OpAccessChain, [&](const auto& appender)
|
|
||||||
{
|
|
||||||
appender(pointerType);
|
|
||||||
appender(resultId);
|
|
||||||
appender(pointer.resultId);
|
|
||||||
|
|
||||||
for (std::size_t index : node.memberIndices)
|
|
||||||
appender(m_writer.GetConstantId(Int32(index)));
|
|
||||||
});
|
|
||||||
|
|
||||||
m_value = Pointer { pointer.storage, resultId, typeId };
|
|
||||||
},
|
|
||||||
[&](const Value& value)
|
|
||||||
{
|
|
||||||
UInt32 resultId = m_writer.AllocateResultId();
|
|
||||||
UInt32 typeId = m_writer.GetTypeId(node.exprType);
|
|
||||||
|
|
||||||
m_writer.GetInstructions().AppendVariadic(SpirvOp::OpCompositeExtract, [&](const auto& appender)
|
|
||||||
{
|
|
||||||
appender(typeId);
|
|
||||||
appender(resultId);
|
|
||||||
appender(value.resultId);
|
|
||||||
|
|
||||||
for (std::size_t index : node.memberIndices)
|
|
||||||
appender(m_writer.GetConstantId(Int32(index)));
|
|
||||||
});
|
|
||||||
|
|
||||||
m_value = Value { resultId };
|
|
||||||
},
|
|
||||||
[this](std::monostate)
|
|
||||||
{
|
|
||||||
throw std::runtime_error("an internal error occurred");
|
|
||||||
}
|
|
||||||
}, m_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpirvExpressionLoadAccessMember::Visit(ShaderNodes::Identifier& node)
|
|
||||||
{
|
|
||||||
Visit(node.var);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpirvExpressionLoadAccessMember::Visit(ShaderNodes::InputVariable& var)
|
|
||||||
{
|
|
||||||
auto inputVar = m_writer.GetInputVariable(var.name);
|
|
||||||
|
|
||||||
if (auto resultIdOpt = m_writer.ReadVariable(inputVar, SpirvWriter::OnlyCache{}))
|
|
||||||
m_value = Value{ *resultIdOpt };
|
|
||||||
else
|
|
||||||
m_value = Pointer{ SpirvStorageClass::Input, inputVar.varId, inputVar.typeId };
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpirvExpressionLoadAccessMember::Visit(ShaderNodes::UniformVariable& var)
|
|
||||||
{
|
|
||||||
auto uniformVar = m_writer.GetUniformVariable(var.name);
|
|
||||||
|
|
||||||
if (auto resultIdOpt = m_writer.ReadVariable(uniformVar, SpirvWriter::OnlyCache{}))
|
|
||||||
m_value = Value{ *resultIdOpt };
|
|
||||||
else
|
|
||||||
m_value = Pointer{ SpirvStorageClass::Uniform, uniformVar.varId, uniformVar.typeId };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,49 +0,0 @@
|
||||||
// Copyright (C) 2020 Jérôme Leclercq
|
|
||||||
// This file is part of the "Nazara Engine - Shader generator"
|
|
||||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
|
||||||
|
|
||||||
#include <Nazara/Shader/SpirvStatementVisitor.hpp>
|
|
||||||
#include <Nazara/Shader/SpirvExpressionLoad.hpp>
|
|
||||||
#include <Nazara/Shader/SpirvExpressionStore.hpp>
|
|
||||||
#include <Nazara/Shader/SpirvWriter.hpp>
|
|
||||||
#include <Nazara/Shader/Debug.hpp>
|
|
||||||
|
|
||||||
namespace Nz
|
|
||||||
{
|
|
||||||
void SpirvStatementVisitor::Visit(ShaderNodes::AssignOp& node)
|
|
||||||
{
|
|
||||||
SpirvExpressionLoad loadVisitor(m_writer);
|
|
||||||
SpirvExpressionStore storeVisitor(m_writer);
|
|
||||||
storeVisitor.Store(node.left, loadVisitor.EvaluateExpression(node.right));
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpirvStatementVisitor::Visit(ShaderNodes::Branch& node)
|
|
||||||
{
|
|
||||||
throw std::runtime_error("not yet implemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpirvStatementVisitor::Visit(ShaderNodes::DeclareVariable& node)
|
|
||||||
{
|
|
||||||
if (node.expression)
|
|
||||||
{
|
|
||||||
assert(node.variable->GetType() == ShaderNodes::VariableType::LocalVariable);
|
|
||||||
|
|
||||||
const auto& localVar = static_cast<const ShaderNodes::LocalVariable&>(*node.variable);
|
|
||||||
|
|
||||||
SpirvExpressionLoad loadVisitor(m_writer);
|
|
||||||
m_writer.WriteLocalVariable(localVar.name, loadVisitor.EvaluateExpression(node.expression));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpirvStatementVisitor::Visit(ShaderNodes::ExpressionStatement& node)
|
|
||||||
{
|
|
||||||
SpirvExpressionLoad loadVisitor(m_writer);
|
|
||||||
loadVisitor.Visit(node.expression);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpirvStatementVisitor::Visit(ShaderNodes::StatementBlock& node)
|
|
||||||
{
|
|
||||||
for (auto& statement : node.statements)
|
|
||||||
Visit(statement);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -7,10 +7,10 @@
|
||||||
#include <Nazara/Core/StackVector.hpp>
|
#include <Nazara/Core/StackVector.hpp>
|
||||||
#include <Nazara/Shader/ShaderAstCloner.hpp>
|
#include <Nazara/Shader/ShaderAstCloner.hpp>
|
||||||
#include <Nazara/Shader/ShaderAstValidator.hpp>
|
#include <Nazara/Shader/ShaderAstValidator.hpp>
|
||||||
|
#include <Nazara/Shader/SpirvAstVisitor.hpp>
|
||||||
#include <Nazara/Shader/SpirvConstantCache.hpp>
|
#include <Nazara/Shader/SpirvConstantCache.hpp>
|
||||||
#include <Nazara/Shader/SpirvData.hpp>
|
#include <Nazara/Shader/SpirvData.hpp>
|
||||||
#include <Nazara/Shader/SpirvSection.hpp>
|
#include <Nazara/Shader/SpirvSection.hpp>
|
||||||
#include <Nazara/Shader/SpirvStatementVisitor.hpp>
|
|
||||||
#include <tsl/ordered_map.h>
|
#include <tsl/ordered_map.h>
|
||||||
#include <tsl/ordered_set.h>
|
#include <tsl/ordered_set.h>
|
||||||
#include <SpirV/spirv.h>
|
#include <SpirV/spirv.h>
|
||||||
|
|
@ -380,7 +380,7 @@ namespace Nz
|
||||||
state.instructions.Append(SpirvOp::OpFunctionParameter, GetTypeId(param.type), paramResultId);
|
state.instructions.Append(SpirvOp::OpFunctionParameter, GetTypeId(param.type), paramResultId);
|
||||||
}
|
}
|
||||||
|
|
||||||
SpirvStatementVisitor visitor(*this);
|
SpirvAstVisitor visitor(*this);
|
||||||
visitor.Visit(functionStatements[funcIndex]);
|
visitor.Visit(functionStatements[funcIndex]);
|
||||||
|
|
||||||
if (func.returnType == ShaderNodes::BasicType::Void)
|
if (func.returnType == ShaderNodes::BasicType::Void)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue