ShaderNodes: Replace union by std::variant

This commit is contained in:
Jérôme Leclercq 2020-08-04 01:33:31 +02:00
parent 50bd150345
commit 7736312c2f
5 changed files with 66 additions and 96 deletions

View File

@ -220,22 +220,17 @@ namespace Nz
ShaderExpressionType GetExpressionType() const override;
void Visit(ShaderVisitor& visitor) override;
BasicType exprType;
using Variant = std::variant<
bool,
float,
Vector2f,
Vector3f,
Vector4f
>;
union
{
bool bool1;
float vec1;
Vector2f vec2;
Vector3f vec3;
Vector4f vec4;
} values;
Variant value;
static inline std::shared_ptr<Constant> Build(bool value);
static inline std::shared_ptr<Constant> Build(float value);
static inline std::shared_ptr<Constant> Build(const Vector2f& value);
static inline std::shared_ptr<Constant> Build(const Vector3f& value);
static inline std::shared_ptr<Constant> Build(const Vector4f& value);
template<typename T> static std::shared_ptr<Constant> Build(const T& value);
};
struct NAZARA_RENDERER_API SwizzleOp : public Expression

View File

@ -239,47 +239,11 @@ namespace Nz::ShaderNodes
{
}
inline std::shared_ptr<Constant> Constant::Build(bool value)
template<typename T>
std::shared_ptr<Constant> Nz::ShaderNodes::Constant::Build(const T& value)
{
auto node = std::make_shared<Constant>();
node->exprType = BasicType::Boolean;
node->values.bool1 = value;
return node;
}
inline std::shared_ptr<Constant> Constant::Build(float value)
{
auto node = std::make_shared<Constant>();
node->exprType = BasicType::Float1;
node->values.vec1 = value;
return node;
}
inline std::shared_ptr<Constant> Constant::Build(const Vector2f& value)
{
auto node = std::make_shared<Constant>();
node->exprType = BasicType::Float2;
node->values.vec2 = value;
return node;
}
inline std::shared_ptr<Constant> Constant::Build(const Vector3f& value)
{
auto node = std::make_shared<Constant>();
node->exprType = BasicType::Float3;
node->values.vec3 = value;
return node;
}
inline std::shared_ptr<Constant> Constant::Build(const Vector4f& value)
{
auto node = std::make_shared<Constant>();
node->exprType = BasicType::Float4;
node->values.vec4 = value;
node->value = value;
return node;
}

View File

@ -3,6 +3,7 @@
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Renderer/GlslWriter.hpp>
#include <Nazara/Core/Algorithm.hpp>
#include <Nazara/Core/CallOnExit.hpp>
#include <Nazara/Renderer/ShaderValidator.hpp>
#include <stdexcept>
@ -426,31 +427,23 @@ namespace Nz
void GlslWriter::Visit(const ShaderNodes::Constant& node)
{
switch (node.exprType)
std::visit([&](auto&& arg)
{
case ShaderNodes::BasicType::Boolean:
Append((node.values.bool1) ? "true" : "false");
break;
using T = std::decay_t<decltype(arg)>;
case ShaderNodes::BasicType::Float1:
Append(std::to_string(node.values.vec1));
break;
case ShaderNodes::BasicType::Float2:
Append("vec2(" + std::to_string(node.values.vec2.x) + ", " + std::to_string(node.values.vec2.y) + ")");
break;
case ShaderNodes::BasicType::Float3:
Append("vec3(" + std::to_string(node.values.vec3.x) + ", " + std::to_string(node.values.vec3.y) + ", " + std::to_string(node.values.vec3.z) + ")");
break;
case ShaderNodes::BasicType::Float4:
Append("vec4(" + std::to_string(node.values.vec4.x) + ", " + std::to_string(node.values.vec4.y) + ", " + std::to_string(node.values.vec4.z) + ", " + std::to_string(node.values.vec4.w) + ")");
break;
default:
throw std::runtime_error("Unhandled expression type");
}
if constexpr (std::is_same_v<T, bool>)
Append((arg) ? "true" : "false");
else if constexpr (std::is_same_v<T, float>)
Append(std::to_string(arg));
else if constexpr (std::is_same_v<T, Vector2f>)
Append("vec2(" + std::to_string(arg.x) + ", " + std::to_string(arg.y) + ")");
else if constexpr (std::is_same_v<T, Vector3f>)
Append("vec3(" + std::to_string(arg.x) + ", " + std::to_string(arg.y) + ", " + std::to_string(arg.z) + ")");
else if constexpr (std::is_same_v<T, Vector4f>)
Append("vec4(" + std::to_string(arg.x) + ", " + std::to_string(arg.y) + ", " + std::to_string(arg.z) + ", " + std::to_string(arg.w) + ")");
else
static_assert(AlwaysFalse<T>::value, "non-exhaustive visitor");
}, node.value);
}
void GlslWriter::Visit(const ShaderNodes::DeclareVariable& node)

View File

@ -3,6 +3,7 @@
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Renderer/ShaderNodes.hpp>
#include <Nazara/Core/Algorithm.hpp>
#include <Nazara/Renderer/ShaderSerializer.hpp>
#include <Nazara/Renderer/ShaderVisitor.hpp>
#include <Nazara/Renderer/ShaderWriter.hpp>
@ -150,7 +151,23 @@ namespace Nz::ShaderNodes
ShaderExpressionType Constant::GetExpressionType() const
{
return exprType;
return std::visit([&](auto&& arg)
{
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, bool>)
return ShaderNodes::BasicType::Boolean;
else if constexpr (std::is_same_v<T, float>)
return ShaderNodes::BasicType::Float1;
else if constexpr (std::is_same_v<T, Vector2f>)
return ShaderNodes::BasicType::Float2;
else if constexpr (std::is_same_v<T, Vector3f>)
return ShaderNodes::BasicType::Float3;
else if constexpr (std::is_same_v<T, Vector4f>)
return ShaderNodes::BasicType::Float4;
else
static_assert(AlwaysFalse<T>::value, "non-exhaustive visitor");
}, value);
}
void Constant::Visit(ShaderVisitor& visitor)

View File

@ -178,29 +178,30 @@ namespace Nz
void ShaderSerializerBase::Serialize(ShaderNodes::Constant& node)
{
Enum(node.exprType);
UInt32 typeIndex;
if (IsWriting())
typeIndex = UInt32(node.value.index());
switch (node.exprType)
Value(typeIndex);
// Waiting for template lambda in C++20
auto SerializeValue = [&](auto dummyType)
{
case ShaderNodes::BasicType::Boolean:
Value(node.values.bool1);
break;
using T = std::decay_t<decltype(dummyType)>;
case ShaderNodes::BasicType::Float1:
Value(node.values.vec1);
break;
auto& value = (IsWriting()) ? std::get<T>(node.value) : node.value.emplace<T>();
Value(value);
};
case ShaderNodes::BasicType::Float2:
Value(node.values.vec2);
break;
case ShaderNodes::BasicType::Float3:
Value(node.values.vec3);
break;
case ShaderNodes::BasicType::Float4:
Value(node.values.vec4);
break;
static_assert(std::variant_size_v<decltype(node.value)> == 5);
switch (typeIndex)
{
case 0: SerializeValue(bool()); break;
case 1: SerializeValue(float()); break;
case 2: SerializeValue(Vector2f()); break;
case 3: SerializeValue(Vector3f()); break;
case 4: SerializeValue(Vector4f()); break;
default: throw std::runtime_error("unexpected data type");
}
}