writer/spirv: Validate arrayLength()
This was tested but the output was not run through the validator. Once the AST is actually correct, the output is validated correctly. Fixed: tint:266 Change-Id: I83bb53323c124c8fbaa3cd9b80524f89c2e30557 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/40601 Auto-Submit: Ben Clayton <bclayton@google.com> Commit-Queue: dan sinclair <dsinclair@chromium.org> Reviewed-by: dan sinclair <dsinclair@chromium.org>
This commit is contained in:
parent
7b7d69854d
commit
6f48851f27
|
@ -25,6 +25,7 @@
|
|||
#include "src/ast/sint_literal.h"
|
||||
#include "src/ast/stage_decoration.h"
|
||||
#include "src/ast/struct.h"
|
||||
#include "src/ast/struct_block_decoration.h"
|
||||
#include "src/ast/struct_member.h"
|
||||
#include "src/ast/type_constructor_expression.h"
|
||||
#include "src/ast/uint_literal.h"
|
||||
|
@ -1406,77 +1407,103 @@ OpFunctionEnd
|
|||
}
|
||||
|
||||
TEST_F(IntrinsicBuilderTest, Call_ArrayLength) {
|
||||
auto* s =
|
||||
create<ast::Struct>(ast::StructMemberList{Member("a", ty.array<f32>())},
|
||||
ast::StructDecorationList{});
|
||||
auto* s = create<ast::Struct>(
|
||||
ast::StructMemberList{Member(0, "a", ty.array<f32>(4))},
|
||||
ast::StructDecorationList{
|
||||
create<ast::StructBlockDecoration>(),
|
||||
});
|
||||
auto* s_type = ty.struct_("my_struct", s);
|
||||
auto* var = Global("b", ast::StorageClass::kPrivate, s_type);
|
||||
Global("b", ast::StorageClass::kStorage, s_type, nullptr,
|
||||
ast::VariableDecorationList{
|
||||
create<ast::BindingDecoration>(1),
|
||||
create<ast::GroupDecoration>(2),
|
||||
});
|
||||
|
||||
auto* expr = Call("arrayLength", MemberAccessor("b", "a"));
|
||||
WrapInFunction(expr);
|
||||
|
||||
auto* func = Func("a_func", ast::VariableList{}, ty.void_(),
|
||||
ast::StatementList{}, ast::FunctionDecorationList{});
|
||||
Func("a_func", ast::VariableList{}, ty.void_(),
|
||||
ast::StatementList{
|
||||
create<ast::CallStatement>(expr),
|
||||
},
|
||||
ast::FunctionDecorationList{
|
||||
create<ast::StageDecoration>(ast::PipelineStage::kVertex),
|
||||
});
|
||||
|
||||
spirv::Builder& b = Build();
|
||||
|
||||
ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
|
||||
ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
|
||||
EXPECT_EQ(b.GenerateExpression(expr), 11u) << b.error();
|
||||
ASSERT_TRUE(b.Build()) << b.error();
|
||||
|
||||
EXPECT_EQ(DumpInstructions(b.types()),
|
||||
R"(%2 = OpTypeVoid
|
||||
%1 = OpTypeFunction %2
|
||||
%9 = OpTypeFloat 32
|
||||
%8 = OpTypeRuntimeArray %9
|
||||
%7 = OpTypeStruct %8
|
||||
%6 = OpTypePointer Private %7
|
||||
%10 = OpConstantNull %7
|
||||
%5 = OpVariable %6 Private %10
|
||||
%12 = OpTypeInt 32 0
|
||||
)");
|
||||
ASSERT_EQ(b.functions().size(), 1u);
|
||||
|
||||
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
|
||||
R"(%11 = OpArrayLength %12 %5 0
|
||||
)");
|
||||
auto* expected_types = R"(%5 = OpTypeFloat 32
|
||||
%4 = OpTypeRuntimeArray %5
|
||||
%3 = OpTypeStruct %4
|
||||
%2 = OpTypePointer StorageBuffer %3
|
||||
%1 = OpVariable %2 StorageBuffer
|
||||
%7 = OpTypeVoid
|
||||
%6 = OpTypeFunction %7
|
||||
%11 = OpTypeInt 32 0
|
||||
)";
|
||||
auto got_types = DumpInstructions(b.types());
|
||||
EXPECT_EQ(expected_types, got_types);
|
||||
|
||||
auto* expected_instructions = R"(%10 = OpArrayLength %11 %1 0
|
||||
)";
|
||||
auto got_instructions = DumpInstructions(b.functions()[0].instructions());
|
||||
EXPECT_EQ(expected_instructions, got_instructions);
|
||||
|
||||
Validate(b);
|
||||
}
|
||||
|
||||
TEST_F(IntrinsicBuilderTest, Call_ArrayLength_OtherMembersInStruct) {
|
||||
auto* s =
|
||||
create<ast::Struct>(ast::StructMemberList{Member("z", ty.f32()),
|
||||
Member("a", ty.array<f32>())},
|
||||
ast::StructDecorationList{});
|
||||
auto* s = create<ast::Struct>(
|
||||
ast::StructMemberList{Member(0, "z", ty.f32()),
|
||||
Member(4, "a", ty.array<f32>(4))},
|
||||
ast::StructDecorationList{
|
||||
create<ast::StructBlockDecoration>(),
|
||||
});
|
||||
|
||||
auto* s_type = ty.struct_("my_struct", s);
|
||||
auto* var = Global("b", ast::StorageClass::kPrivate, s_type);
|
||||
Global("b", ast::StorageClass::kStorage, s_type, nullptr,
|
||||
ast::VariableDecorationList{
|
||||
create<ast::BindingDecoration>(1),
|
||||
create<ast::GroupDecoration>(2),
|
||||
});
|
||||
|
||||
auto* expr = Call("arrayLength", MemberAccessor("b", "a"));
|
||||
WrapInFunction(expr);
|
||||
|
||||
auto* func = Func("a_func", ast::VariableList{}, ty.void_(),
|
||||
ast::StatementList{}, ast::FunctionDecorationList{});
|
||||
Func("a_func", ast::VariableList{}, ty.void_(),
|
||||
ast::StatementList{
|
||||
create<ast::CallStatement>(expr),
|
||||
},
|
||||
ast::FunctionDecorationList{
|
||||
create<ast::StageDecoration>(ast::PipelineStage::kVertex),
|
||||
});
|
||||
|
||||
spirv::Builder& b = Build();
|
||||
|
||||
ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
|
||||
ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
|
||||
EXPECT_EQ(b.GenerateExpression(expr), 11u) << b.error();
|
||||
ASSERT_TRUE(b.Build()) << b.error();
|
||||
|
||||
EXPECT_EQ(DumpInstructions(b.types()),
|
||||
R"(%2 = OpTypeVoid
|
||||
%1 = OpTypeFunction %2
|
||||
%8 = OpTypeFloat 32
|
||||
%9 = OpTypeRuntimeArray %8
|
||||
%7 = OpTypeStruct %8 %9
|
||||
%6 = OpTypePointer Private %7
|
||||
%10 = OpConstantNull %7
|
||||
%5 = OpVariable %6 Private %10
|
||||
%12 = OpTypeInt 32 0
|
||||
)");
|
||||
ASSERT_EQ(b.functions().size(), 1u);
|
||||
|
||||
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
|
||||
R"(%11 = OpArrayLength %12 %5 1
|
||||
)");
|
||||
auto* expected_types = R"(%4 = OpTypeFloat 32
|
||||
%5 = OpTypeRuntimeArray %4
|
||||
%3 = OpTypeStruct %4 %5
|
||||
%2 = OpTypePointer StorageBuffer %3
|
||||
%1 = OpVariable %2 StorageBuffer
|
||||
%7 = OpTypeVoid
|
||||
%6 = OpTypeFunction %7
|
||||
%11 = OpTypeInt 32 0
|
||||
)";
|
||||
auto got_types = DumpInstructions(b.types());
|
||||
EXPECT_EQ(expected_types, got_types);
|
||||
|
||||
auto* expected_instructions = R"(%10 = OpArrayLength %11 %1 1
|
||||
)";
|
||||
auto got_instructions = DumpInstructions(b.functions()[0].instructions());
|
||||
EXPECT_EQ(expected_instructions, got_instructions);
|
||||
|
||||
Validate(b);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
Loading…
Reference in New Issue