NazaraEngine/include/Nazara/Renderer/ShaderAst.inl

247 lines
6.1 KiB
C++

// 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 <Nazara/Renderer/ShaderAst.hpp>
#include <Nazara/Renderer/Debug.hpp>
namespace Nz
{
namespace ShaderAst
{
inline unsigned int Node::GetComponentCount(ExpressionType type)
{
switch (type)
{
case ExpressionType::Float2:
return 2;
case ExpressionType::Float3:
return 3;
case ExpressionType::Float4:
return 4;
case ExpressionType::Mat4x4:
return 4;
default:
return 1;
}
}
inline ExpressionType Node::GetComponentType(ExpressionType type)
{
switch (type)
{
case ExpressionType::Float2:
case ExpressionType::Float3:
case ExpressionType::Float4:
return ExpressionType::Float1;
case ExpressionType::Mat4x4:
return ExpressionType::Float4;
default:
return type;
}
}
inline ExpressionStatement::ExpressionStatement(ExpressionPtr expr) :
expression(std::move(expr))
{
}
inline ConditionalStatement::ConditionalStatement(const String& condition, StatementPtr statementPtr) :
conditionName(condition),
statement(std::move(statementPtr))
{
}
template<typename... Args>
StatementBlock::StatementBlock(Args&& ...args) :
statements({std::forward<Args>(args)...})
{
}
inline Variable::Variable(VariableType varKind, ExpressionType varType) :
type(varType),
kind(varKind)
{
}
inline BuiltinVariable::BuiltinVariable(BuiltinEntry variable, ExpressionType varType) :
Variable(VariableType::Builtin, varType),
var(variable)
{
}
inline NamedVariable::NamedVariable(VariableType varKind, const Nz::String& varName, ExpressionType varType) :
Variable(varKind, varType),
name(varName)
{
}
inline AssignOp::AssignOp(AssignType Op, ExpressionPtr Left, ExpressionPtr Right) :
op(Op),
left(std::move(Left)),
right(std::move(Right))
{
if (left->GetExpressionCategory() != ExpressionCategory::LValue)
//TODO: AstParseError
throw std::runtime_error("Assignation is only possible with lvalues");
}
inline BinaryOp::BinaryOp(BinaryType Op, ExpressionPtr Left, ExpressionPtr Right) :
op(Op),
left(std::move(Left)),
right(std::move(Right))
{
ExpressionType leftType = left->GetExpressionType();
ExpressionType rightType = right->GetExpressionType();
if (leftType != rightType)
{
switch (op)
{
case BinaryType::Add:
case BinaryType::Equality:
case BinaryType::Substract:
{
//TODO: AstParseError
throw std::runtime_error("Left expression type must match right expression type");
}
case BinaryType::Multiply:
case BinaryType::Divide:
{
switch (leftType)
{
case ExpressionType::Float2:
case ExpressionType::Float3:
case ExpressionType::Float4:
{
if (rightType != ExpressionType::Float1)
throw std::runtime_error("Left expression type is not compatible with right expression type");
break;
}
case ExpressionType::Mat4x4:
{
switch (rightType)
{
case ExpressionType::Float1:
case ExpressionType::Float4:
case ExpressionType::Mat4x4:
break;
//TODO: AstParseError
default:
throw std::runtime_error("Left expression type is not compatible with right expression type");
}
break;
}
default:
//TODO: AstParseError
throw std::runtime_error("Left expression type must match right expression type");
}
}
}
}
}
inline Branch::Branch(ExpressionPtr condition, StatementPtr trueStatement, StatementPtr falseStatement)
{
condStatements.emplace_back(ConditionalStatement{ std::move(condition), std::move(trueStatement) });
elseStatement = std::move(falseStatement);
}
inline Cast::Cast(ExpressionType castTo, ExpressionPtr first, ExpressionPtr second, ExpressionPtr third, ExpressionPtr fourth) :
exprType(castTo),
expressions({ {first, second, third, fourth} })
{
unsigned int componentCount = 0;
unsigned int requiredComponents = GetComponentCount(exprType);
for (const auto& exprPtr : expressions)
{
if (!exprPtr)
break;
componentCount += GetComponentCount(exprPtr->GetExpressionType());
}
//TODO: AstParseError
if (componentCount != requiredComponents)
throw std::runtime_error("Component count doesn't match required component count");
}
inline Constant::Constant(bool value) :
exprType(ExpressionType::Boolean)
{
values.bool1 = value;
}
inline Constant::Constant(float value) :
exprType(ExpressionType::Float1)
{
values.vec1 = value;
}
inline Constant::Constant(const Vector2f& value) :
exprType(ExpressionType::Float2)
{
values.vec2 = value;
}
inline Constant::Constant(const Vector3f& value) :
exprType(ExpressionType::Float3)
{
values.vec3 = value;
}
inline Constant::Constant(const Vector4f& value) :
exprType(ExpressionType::Float4)
{
values.vec4 = value;
}
inline SwizzleOp::SwizzleOp(ExpressionPtr expressionPtr, std::initializer_list<SwizzleComponent> swizzleComponents) :
componentCount(swizzleComponents.size()),
expression(expressionPtr)
{
if (componentCount > 4)
throw std::runtime_error("Cannot swizzle more than four elements");
switch (expressionPtr->GetExpressionType())
{
case ExpressionType::Float1:
case ExpressionType::Float2:
case ExpressionType::Float3:
case ExpressionType::Float4:
break;
default:
throw std::runtime_error("Cannot swizzle this type");
}
std::copy(swizzleComponents.begin(), swizzleComponents.end(), components.begin());
}
inline Sample2D::Sample2D(ExpressionPtr samplerPtr, ExpressionPtr coordinatesPtr) :
sampler(std::move(samplerPtr)),
coordinates(std::move(coordinatesPtr))
{
if (sampler->GetExpressionType() != ExpressionType::Sampler2D)
throw std::runtime_error("Sampler must be a Sampler2D");
if (coordinates->GetExpressionType() != ExpressionType::Float2)
throw std::runtime_error("Coordinates must be a Float2");
}
}
}
#include <Nazara/Renderer/DebugOff.hpp>