Shader: Add initial support for arrays
This commit is contained in:
@@ -8,9 +8,7 @@
|
||||
#include <Nazara/Graphics/PredefinedShaderStructs.hpp>
|
||||
#include <Nazara/Graphics/UberShader.hpp>
|
||||
#include <Nazara/Renderer/Renderer.hpp>
|
||||
#include <Nazara/Shader/ShaderLangLexer.hpp>
|
||||
#include <Nazara/Shader/ShaderLangParser.hpp>
|
||||
#include <Nazara/Shader/Ast/AstSerializer.hpp>
|
||||
#include <Nazara/Utility/BufferMapper.hpp>
|
||||
#include <Nazara/Utility/FieldOffsets.hpp>
|
||||
#include <Nazara/Utility/MaterialData.hpp>
|
||||
|
||||
@@ -79,7 +79,7 @@ namespace Nz::ShaderAst
|
||||
auto clone = std::make_unique<DeclareExternalStatement>();
|
||||
clone->varIndex = node.varIndex;
|
||||
|
||||
clone->bindingSet = CloneAttribute(node.bindingSet);
|
||||
clone->bindingSet = Clone(node.bindingSet);
|
||||
|
||||
clone->externalVars.reserve(node.externalVars.size());
|
||||
for (const auto& var : node.externalVars)
|
||||
@@ -87,8 +87,8 @@ namespace Nz::ShaderAst
|
||||
auto& cloneVar = clone->externalVars.emplace_back();
|
||||
cloneVar.name = var.name;
|
||||
cloneVar.type = var.type;
|
||||
cloneVar.bindingIndex = CloneAttribute(var.bindingIndex);
|
||||
cloneVar.bindingSet = CloneAttribute(var.bindingSet);
|
||||
cloneVar.bindingIndex = Clone(var.bindingIndex);
|
||||
cloneVar.bindingSet = Clone(var.bindingSet);
|
||||
}
|
||||
|
||||
return clone;
|
||||
@@ -97,9 +97,9 @@ namespace Nz::ShaderAst
|
||||
StatementPtr AstCloner::Clone(DeclareFunctionStatement& node)
|
||||
{
|
||||
auto clone = std::make_unique<DeclareFunctionStatement>();
|
||||
clone->depthWrite = CloneAttribute(node.depthWrite);
|
||||
clone->earlyFragmentTests = CloneAttribute(node.earlyFragmentTests);
|
||||
clone->entryStage = CloneAttribute(node.entryStage);
|
||||
clone->depthWrite = Clone(node.depthWrite);
|
||||
clone->earlyFragmentTests = Clone(node.earlyFragmentTests);
|
||||
clone->entryStage = Clone(node.entryStage);
|
||||
clone->funcIndex = node.funcIndex;
|
||||
clone->name = node.name;
|
||||
clone->parameters = node.parameters;
|
||||
@@ -129,7 +129,7 @@ namespace Nz::ShaderAst
|
||||
auto clone = std::make_unique<DeclareStructStatement>();
|
||||
clone->structIndex = node.structIndex;
|
||||
|
||||
clone->description.layout = CloneAttribute(node.description.layout);
|
||||
clone->description.layout = Clone(node.description.layout);
|
||||
clone->description.name = node.description.name;
|
||||
|
||||
clone->description.members.reserve(node.description.members.size());
|
||||
@@ -138,9 +138,9 @@ namespace Nz::ShaderAst
|
||||
auto& cloneMember = clone->description.members.emplace_back();
|
||||
cloneMember.name = member.name;
|
||||
cloneMember.type = member.type;
|
||||
cloneMember.builtin = CloneAttribute(member.builtin);
|
||||
cloneMember.cond = CloneAttribute(member.cond);
|
||||
cloneMember.locationIndex = CloneAttribute(member.locationIndex);
|
||||
cloneMember.builtin = Clone(member.builtin);
|
||||
cloneMember.cond = Clone(member.cond);
|
||||
cloneMember.locationIndex = Clone(member.locationIndex);
|
||||
}
|
||||
|
||||
return clone;
|
||||
|
||||
10
src/Nazara/Shader/Ast/AstCompare.cpp
Normal file
10
src/Nazara/Shader/Ast/AstCompare.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
|
||||
// This file is part of the "Nazara Engine - Shader module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Shader/Ast/AstCompare.hpp>
|
||||
#include <Nazara/Shader/Debug.hpp>
|
||||
|
||||
namespace Nz::ShaderAst
|
||||
{
|
||||
}
|
||||
@@ -409,6 +409,12 @@ namespace Nz::ShaderAst
|
||||
m_stream << UInt32(arg.componentCount);
|
||||
m_stream << UInt32(arg.type);
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, ArrayType>)
|
||||
{
|
||||
m_stream << UInt8(8);
|
||||
Attribute(arg.length);
|
||||
Type(arg.containedType->type);
|
||||
}
|
||||
else
|
||||
static_assert(AlwaysFalse<T>::value, "non-exhaustive visitor");
|
||||
}, type);
|
||||
@@ -569,40 +575,6 @@ namespace Nz::ShaderAst
|
||||
|
||||
switch (typeIndex)
|
||||
{
|
||||
/*
|
||||
if constexpr (std::is_same_v<T, NoType>)
|
||||
m_stream << UInt8(0);
|
||||
else if constexpr (std::is_same_v<T, PrimitiveType>)
|
||||
{
|
||||
m_stream << UInt8(1);
|
||||
m_stream << UInt32(arg);
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, IdentifierType>)
|
||||
{
|
||||
m_stream << UInt8(2);
|
||||
m_stream << arg.name;
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, MatrixType>)
|
||||
{
|
||||
m_stream << UInt8(3);
|
||||
m_stream << UInt32(arg.columnCount);
|
||||
m_stream << UInt32(arg.rowCount);
|
||||
m_stream << UInt32(arg.type);
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, SamplerType>)
|
||||
{
|
||||
m_stream << UInt8(4);
|
||||
m_stream << UInt32(arg.dim);
|
||||
m_stream << UInt32(arg.sampledType);
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, VectorType>)
|
||||
{
|
||||
m_stream << UInt8(5);
|
||||
m_stream << UInt32(arg.componentCount);
|
||||
m_stream << UInt32(arg.type);
|
||||
}
|
||||
*/
|
||||
|
||||
case 0: //< NoType
|
||||
type = NoType{};
|
||||
break;
|
||||
@@ -693,6 +665,22 @@ namespace Nz::ShaderAst
|
||||
break;
|
||||
}
|
||||
|
||||
case 8: //< ArrayType
|
||||
{
|
||||
AttributeValue<UInt32> length;
|
||||
ExpressionType containedType;
|
||||
Attribute(length);
|
||||
Type(containedType);
|
||||
|
||||
ArrayType arrayType;
|
||||
arrayType.length = std::move(length);
|
||||
arrayType.containedType = std::make_unique<ContainedType>();
|
||||
arrayType.containedType->type = std::move(containedType);
|
||||
|
||||
type = std::move(arrayType);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Shader/Ast/ConstantValue.hpp>
|
||||
#include <Nazara/Shader/Ast/Nodes.hpp>
|
||||
#include <Nazara/Shader/Debug.hpp>
|
||||
|
||||
namespace Nz::ShaderAst
|
||||
|
||||
42
src/Nazara/Shader/Ast/ExpressionType.cpp
Normal file
42
src/Nazara/Shader/Ast/ExpressionType.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
|
||||
// This file is part of the "Nazara Engine - Shader module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Shader/Ast/ExpressionType.hpp>
|
||||
#include <Nazara/Shader/Ast/AstCloner.hpp>
|
||||
#include <Nazara/Shader/Ast/AstCompare.hpp>
|
||||
#include <Nazara/Shader/Debug.hpp>
|
||||
|
||||
namespace Nz::ShaderAst
|
||||
{
|
||||
ArrayType::ArrayType(const ArrayType& array)
|
||||
{
|
||||
assert(array.containedType);
|
||||
containedType = std::make_unique<ContainedType>(*array.containedType);
|
||||
length = Clone(length);
|
||||
}
|
||||
|
||||
ArrayType& ArrayType::operator=(const ArrayType& array)
|
||||
{
|
||||
assert(array.containedType);
|
||||
|
||||
containedType = std::make_unique<ContainedType>(*array.containedType);
|
||||
length = Clone(length);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool ArrayType::operator==(const ArrayType& rhs) const
|
||||
{
|
||||
assert(containedType);
|
||||
assert(rhs.containedType);
|
||||
|
||||
if (containedType->type != rhs.containedType->type)
|
||||
return false;
|
||||
|
||||
if (!Compare(length, rhs.length))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1156,6 +1156,7 @@ namespace Nz::ShaderAst
|
||||
if constexpr (std::is_same_v<T, IdentifierType> || std::is_same_v<T, StructType> || std::is_same_v<T, UniformType>)
|
||||
return ResolveStruct(arg);
|
||||
else if constexpr (std::is_same_v<T, NoType> ||
|
||||
std::is_same_v<T, ArrayType> ||
|
||||
std::is_same_v<T, PrimitiveType> ||
|
||||
std::is_same_v<T, MatrixType> ||
|
||||
std::is_same_v<T, SamplerType> ||
|
||||
@@ -1205,6 +1206,7 @@ namespace Nz::ShaderAst
|
||||
using T = std::decay_t<decltype(arg)>;
|
||||
|
||||
if constexpr (std::is_same_v<T, NoType> ||
|
||||
std::is_same_v<T, ArrayType> ||
|
||||
std::is_same_v<T, PrimitiveType> ||
|
||||
std::is_same_v<T, MatrixType> ||
|
||||
std::is_same_v<T, SamplerType> ||
|
||||
@@ -1267,7 +1269,13 @@ namespace Nz::ShaderAst
|
||||
ExpressionType exprType = GetExpressionType(*node.expr);
|
||||
for (const auto& indexExpr : node.indices)
|
||||
{
|
||||
if (IsStructType(exprType))
|
||||
if (IsArrayType(exprType))
|
||||
{
|
||||
const ArrayType& arrayType = std::get<ArrayType>(exprType);
|
||||
|
||||
exprType = arrayType.containedType->type;
|
||||
}
|
||||
else if (IsStructType(exprType))
|
||||
{
|
||||
const ShaderAst::ExpressionType& indexType = GetExpressionType(*indexExpr);
|
||||
if (indexExpr->GetType() != NodeType::ConstantValueExpression || indexType != ExpressionType{ PrimitiveType::Int32 })
|
||||
|
||||
@@ -219,6 +219,18 @@ namespace Nz
|
||||
return ShaderAst::Sanitize(ast, options, error);
|
||||
}
|
||||
|
||||
void GlslWriter::Append(const ShaderAst::ArrayType& type)
|
||||
{
|
||||
Append(type.containedType->type, "[");
|
||||
|
||||
if (type.length.IsResultingValue())
|
||||
Append(type.length.GetResultingValue());
|
||||
else
|
||||
type.length.GetExpression()->Visit(*this);
|
||||
|
||||
Append("]");
|
||||
}
|
||||
|
||||
void GlslWriter::Append(const ShaderAst::ExpressionType& type)
|
||||
{
|
||||
std::visit([&](auto&& arg)
|
||||
@@ -963,7 +975,7 @@ namespace Nz
|
||||
std::size_t structIndex = std::get<ShaderAst::StructType>(uniform.containedType).structIndex;
|
||||
ShaderAst::StructDescription* structInfo = Retrieve(m_currentState->structs, structIndex);
|
||||
if (structInfo->layout.HasValue())
|
||||
isStd140 = structInfo->layout.GetResultingValue() == StructLayout::Std140;
|
||||
isStd140 = structInfo->layout.GetResultingValue() == StructLayout::Std140;
|
||||
}
|
||||
|
||||
if (!m_currentState->bindingMapping.empty() || isStd140)
|
||||
|
||||
@@ -120,6 +120,18 @@ namespace Nz
|
||||
m_environment = std::move(environment);
|
||||
}
|
||||
|
||||
void LangWriter::Append(const ShaderAst::ArrayType& type)
|
||||
{
|
||||
Append("[", type.containedType->type, "; ");
|
||||
|
||||
if (type.length.IsResultingValue())
|
||||
Append(type.length.GetResultingValue());
|
||||
else
|
||||
type.length.GetExpression()->Visit(*this);
|
||||
|
||||
Append("]");
|
||||
}
|
||||
|
||||
void LangWriter::Append(const ShaderAst::ExpressionType& type)
|
||||
{
|
||||
std::visit([&](auto&& arg)
|
||||
|
||||
@@ -680,7 +680,7 @@ namespace Nz::ShaderLang
|
||||
|
||||
ShaderAst::ExpressionType parameterType = ParseType();
|
||||
|
||||
return { parameterName, parameterType };
|
||||
return { parameterName, std::move(parameterType) };
|
||||
}
|
||||
|
||||
ShaderAst::StatementPtr Parser::ParseOptionDeclaration()
|
||||
@@ -1088,7 +1088,7 @@ namespace Nz::ShaderLang
|
||||
ShaderAst::ExpressionPtr Parser::ParseIntegerExpression()
|
||||
{
|
||||
const Token& integerToken = Expect(Advance(), TokenType::IntegerValue);
|
||||
return ShaderBuilder::Constant(static_cast<Nz::Int32>(std::get<long long>(integerToken.data))); //< FIXME
|
||||
return ShaderBuilder::Constant(SafeCast<Int32>(std::get<long long>(integerToken.data))); //< FIXME
|
||||
}
|
||||
|
||||
std::vector<ShaderAst::ExpressionPtr> Parser::ParseParameters()
|
||||
@@ -1193,6 +1193,24 @@ namespace Nz::ShaderLang
|
||||
}
|
||||
}
|
||||
|
||||
ShaderAst::ExpressionType Parser::ParseArrayType()
|
||||
{
|
||||
ShaderAst::ArrayType arrayType;
|
||||
|
||||
Expect(Advance(), TokenType::OpenSquareBracket);
|
||||
|
||||
arrayType.containedType = std::make_unique<ShaderAst::ContainedType>();
|
||||
arrayType.containedType->type = ParseType();
|
||||
|
||||
Expect(Advance(), TokenType::Semicolon);
|
||||
|
||||
arrayType.length = ParseExpression();
|
||||
|
||||
Expect(Advance(), TokenType::ClosingSquareBracket);
|
||||
|
||||
return arrayType;
|
||||
}
|
||||
|
||||
ShaderAst::AttributeType Parser::ParseIdentifierAsAttributeType()
|
||||
{
|
||||
const Token& identifierToken = Expect(Advance(), TokenType::Identifier);
|
||||
@@ -1240,6 +1258,9 @@ namespace Nz::ShaderLang
|
||||
return ShaderAst::NoType{};
|
||||
}
|
||||
|
||||
if (Peek().type == TokenType::OpenSquareBracket)
|
||||
return ParseArrayType();
|
||||
|
||||
const Token& identifierToken = Expect(Peek(), TokenType::Identifier);
|
||||
const std::string& identifier = std::get<std::string>(identifierToken.data);
|
||||
|
||||
@@ -1250,7 +1271,7 @@ namespace Nz::ShaderLang
|
||||
return ShaderAst::IdentifierType{ identifier };
|
||||
}
|
||||
|
||||
return *type;
|
||||
return *std::move(type);
|
||||
}
|
||||
|
||||
int Parser::GetTokenPrecedence(TokenType token)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Shader/ShaderWriter.hpp>
|
||||
#include <Nazara/Shader/Ast/Nodes.hpp>
|
||||
#include <Nazara/Shader/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <Nazara/Shader/SpirvConstantCache.hpp>
|
||||
#include <Nazara/Shader/SpirvSection.hpp>
|
||||
#include <Nazara/Shader/Ast/Nodes.hpp>
|
||||
#include <Nazara/Utility/FieldOffsets.hpp>
|
||||
#include <tsl/ordered_map.h>
|
||||
#include <stdexcept>
|
||||
@@ -35,6 +36,11 @@ namespace Nz
|
||||
return lhs.value == rhs.value;
|
||||
}
|
||||
|
||||
bool Compare(const Array& lhs, const Array& rhs) const
|
||||
{
|
||||
return lhs.length == rhs.length && Compare(lhs.elementType, rhs.elementType);
|
||||
}
|
||||
|
||||
bool Compare(const Bool& /*lhs*/, const Bool& /*rhs*/) const
|
||||
{
|
||||
return true;
|
||||
@@ -227,6 +233,12 @@ namespace Nz
|
||||
{
|
||||
}
|
||||
|
||||
void Register(const Array& array)
|
||||
{
|
||||
assert(array.elementType);
|
||||
cache.Register(*array.elementType);
|
||||
}
|
||||
|
||||
void Register(const Bool&) {}
|
||||
void Register(const Float&) {}
|
||||
void Register(const Integer&) {}
|
||||
@@ -801,7 +813,9 @@ namespace Nz
|
||||
{
|
||||
using T = std::decay_t<decltype(arg)>;
|
||||
|
||||
if constexpr (std::is_same_v<T, Bool>)
|
||||
if constexpr (std::is_same_v<T, Array>)
|
||||
constants.Append(SpirvOp::OpTypeArray, resultId, GetId(*arg.elementType), arg.length);
|
||||
else if constexpr (std::is_same_v<T, Bool>)
|
||||
constants.Append(SpirvOp::OpTypeBool, resultId);
|
||||
else if constexpr (std::is_same_v<T, Float>)
|
||||
constants.Append(SpirvOp::OpTypeFloat, resultId, arg.width);
|
||||
@@ -892,7 +906,12 @@ namespace Nz
|
||||
{
|
||||
using T = std::decay_t<decltype(arg)>;
|
||||
|
||||
if constexpr (std::is_same_v<T, Bool>)
|
||||
if constexpr (std::is_same_v<T, Array>)
|
||||
{
|
||||
// TODO
|
||||
throw std::runtime_error("todo");
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, Bool>)
|
||||
return structOffsets.AddField(StructFieldType::Bool1);
|
||||
else if constexpr (std::is_same_v<T, Float>)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user