Skip to content

Commit

Permalink
Add std430 memory layout
Browse files Browse the repository at this point in the history
  • Loading branch information
SirLynix committed Mar 10, 2024
1 parent 0042633 commit 45e5c43
Show file tree
Hide file tree
Showing 9 changed files with 93 additions and 16 deletions.
3 changes: 2 additions & 1 deletion include/NZSL/Ast/Enums.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,8 @@ namespace nzsl::Ast

enum class MemoryLayout
{
Std140 = 0
Std140 = 0,
Std430 = 1
};

enum class ModuleFeature
Expand Down
3 changes: 2 additions & 1 deletion include/NZSL/Enums.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,9 @@ namespace nzsl
{
Packed,
Std140,
Std430,

Max = Std140
Max = Std430
};
}

Expand Down
1 change: 1 addition & 0 deletions include/NZSL/Math/FieldOffsets.inl
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ namespace nzsl
return 1;

case StructLayout::Std140:
case StructLayout::Std430:
{
switch (fieldType)
{
Expand Down
25 changes: 20 additions & 5 deletions src/NZSL/Ast/SanitizeVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1860,18 +1860,33 @@ namespace nzsl::Ast
}

const ExpressionType& memberType = member.type.GetResultingValue();
if (clone->description.layout.IsResultingValue() && clone->description.layout.GetResultingValue() == Ast::MemoryLayout::Std140)
if (clone->description.layout.IsResultingValue())
{
Ast::MemoryLayout structLayout = clone->description.layout.GetResultingValue();
auto LayoutName = [&](Ast::MemoryLayout layout)
{
auto it = LangData::s_memoryLayouts.find(layout);
if (it == LangData::s_memoryLayouts.end())
throw AstInternalError{ node.sourceLocation, "missing layout data" };

return it->second.identifier;
};

const ExpressionType& targetType = ResolveAlias(member.type.GetResultingValue());

if (IsPrimitiveType(targetType) && std::get<PrimitiveType>(targetType) == PrimitiveType::Boolean)
throw CompilerStructLayoutTypeNotAllowedError{ member.sourceLocation, "bool", "std140" };
if (IsPrimitiveType(targetType))
{
if (std::get<PrimitiveType>(targetType) == PrimitiveType::Boolean)
throw CompilerStructLayoutTypeNotAllowedError{ member.sourceLocation, "bool", LayoutName(structLayout) };
}
else if (IsStructType(targetType))
{
std::size_t structIndex = std::get<StructType>(targetType).structIndex;
const StructDescription* desc = m_context->structs.Retrieve(structIndex, member.sourceLocation);
if (!desc->layout.HasValue() || desc->layout.GetResultingValue() != clone->description.layout.GetResultingValue())
throw CompilerStructLayoutInnerMismatchError{ member.sourceLocation, "std140", "<TODO>" };
if (!desc->layout.HasValue())
throw CompilerStructLayoutInnerMismatchError{ member.sourceLocation, LayoutName(structLayout), "<no layout>" };
else if (Ast::MemoryLayout memberLayout = desc->layout.GetResultingValue(); memberLayout != structLayout)
throw CompilerStructLayoutInnerMismatchError{ member.sourceLocation, LayoutName(structLayout), LayoutName(memberLayout) };
}
}

Expand Down
19 changes: 12 additions & 7 deletions src/NZSL/GlslWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -792,9 +792,8 @@ namespace nzsl
{
switch (layout)
{
case Ast::MemoryLayout::Std140:
Append("std140");
break;
case Ast::MemoryLayout::Std140: Append("std140"); break;
case Ast::MemoryLayout::Std430: Append("std430"); break;
}
}

Expand Down Expand Up @@ -2222,7 +2221,7 @@ namespace nzsl

bool isUniformOrStorageBuffer = IsStorageType(exprType) || IsUniformType(exprType);

bool isStd140 = false;
const char* memoryLayout = nullptr;
if (isUniformOrStorageBuffer)
{
std::size_t structIndex;
Expand All @@ -2237,7 +2236,13 @@ namespace nzsl

const auto& structInfo = Nz::Retrieve(m_currentState->structs, structIndex);
if (structInfo.desc->layout.HasValue())
isStd140 = structInfo.desc->layout.GetResultingValue() == Ast::MemoryLayout::Std140;
{
switch (structInfo.desc->layout.GetResultingValue())
{
case Ast::MemoryLayout::Std140: memoryLayout = "std140"; break;
case Ast::MemoryLayout::Std430: memoryLayout = "std430"; break;
}
}

if (!structInfo.desc->tag.empty() && m_currentState->states->debugLevel >= DebugLevel::Minimal)
AppendComment("struct tag: " + structInfo.desc->tag);
Expand Down Expand Up @@ -2309,10 +2314,10 @@ namespace nzsl
}
}

if (isStd140)
if (memoryLayout)
{
BeginLayout();
Append("std140");
Append(memoryLayout);
}

EndLayout();
Expand Down
3 changes: 2 additions & 1 deletion src/NZSL/Lang/LangData.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,8 @@ namespace nzsl::LangData
};

constexpr auto s_memoryLayouts = frozen::make_unordered_map<Ast::MemoryLayout, MemoryLayoutData>({
{ Ast::MemoryLayout::Std140, { "std140", StructLayout::Std140 } }
{ Ast::MemoryLayout::Std140, { "std140", StructLayout::Std140 } },
{ Ast::MemoryLayout::Std430, { "std430", StructLayout::Std140 } }
});

constexpr auto s_moduleFeatures = frozen::make_unordered_map<Ast::ModuleFeature, ModuleFeatureData>({
Expand Down
34 changes: 34 additions & 0 deletions tests/src/Tests/ErrorsTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,40 @@ fn main()

/************************************************************************/

SECTION("Layouts")
{
CHECK_THROWS_WITH(Compile(R"(
[nzsl_version("1.0")]
module;
[layout(std140)]
struct Foo
{
a: bool
}
)"), "(8, 2): CStructLayoutTypeNotAllowed error: bool type is not allowed in std140 layout");

CHECK_THROWS_WITH(Compile(R"(
[nzsl_version("1.0")]
module;
[layout(std140)]
struct Foo
{
a: i32
}
[layout(std430)]
struct Bar
{
a: Foo
}
)"), "(14, 2): CStructLayoutInnerMismatch error: inner struct layout mismatch, struct is declared with std430 but field has layout std140");

}

/************************************************************************/

SECTION("Loops")
{
CHECK_THROWS_WITH(Compile(R"(
Expand Down
4 changes: 3 additions & 1 deletion tests/src/Tests/ExternalTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,7 @@ fn main()
[nzsl_version("1.0")]
module;
[layout(std430)]
struct Data
{
data: u32,
Expand Down Expand Up @@ -444,7 +445,7 @@ fn main()
glslEnv.glMinorVersion = 1;

ExpectGLSL(*shaderModule, R"(
buffer _nzslBindingdata
layout(std430) buffer _nzslBindingdata
{
uint data;
float values[];
Expand All @@ -458,6 +459,7 @@ void main()
)", {}, glslEnv);

ExpectNZSL(*shaderModule, R"(
[layout(std430)]
struct Data
{
data: u32,
Expand Down
17 changes: 17 additions & 0 deletions tests/src/Tests/FieldOffsetsTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,23 @@ TEST_CASE("Field offsets", "[FieldOffsets]")
REQUIRE(fieldOffsets.AddField(nzsl::StructFieldType::Float3) == 416);
REQUIRE(fieldOffsets.GetAlignedSize() == 432);
}

// From https://github.com/shader-slang/slang/blob/master/tests/reflection/std430-layout.glsl
SECTION("std430")
{
nzsl::FieldOffsets innerStruct(nzsl::StructLayout::Std430);
innerStruct.AddField(nzsl::StructFieldType::Float2);

nzsl::FieldOffsets fieldOffsets(nzsl::StructLayout::Std430);
REQUIRE(fieldOffsets.AddField(nzsl::StructFieldType::Float1) == 0);
REQUIRE(fieldOffsets.AddField(nzsl::StructFieldType::Float3) == 16);
REQUIRE(fieldOffsets.AddFieldArray(nzsl::StructFieldType::Float1, 4) == 28);
REQUIRE(fieldOffsets.AddField(nzsl::StructFieldType::Float2) == 48);
REQUIRE(fieldOffsets.AddStruct(innerStruct) == 56);
REQUIRE(fieldOffsets.AddField(nzsl::StructFieldType::Float3) == 64);
REQUIRE(fieldOffsets.AddField(nzsl::StructFieldType::Float1) == 76);
REQUIRE(fieldOffsets.GetAlignedSize() == 80);
}
}

TEST_CASE("RegisterStructField", "[FieldOffsets]")
Expand Down

0 comments on commit 45e5c43

Please sign in to comment.