Shader: Add initial support for arrays

This commit is contained in:
Jérôme Leclercq
2022-01-01 23:01:31 +01:00
parent 89c7bbf197
commit 1f15328fdd
22 changed files with 781 additions and 57 deletions

View File

@@ -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>

View File

@@ -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;

View 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
{
}

View File

@@ -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;
}

View File

@@ -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

View 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;
}
}

View File

@@ -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 })

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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

View File

@@ -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>)
{