writer/hlsl: Don't emit structs for storage buffer usage
Use the semantic StorageClassUsage() to determine whether the structure is used only for storage buffer usage. If it is, don't emit a struct definition for it. This fixes issues with attempting to generate runtime arrays - they're only legal for storage buffer usage. Storage buffers use ByteAddressBuffer instead of structured loads / stores. Bug: tint:185 Fixed: tint:682 Change-Id: I5b58a133eee2fe036a84e028fa85b611e4895b1a Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/46382 Commit-Queue: Ben Clayton <bclayton@google.com> Reviewed-by: James Price <jrprice@google.com>
This commit is contained in:
parent
96a57f65dd
commit
0f02a6de00
|
@ -2590,9 +2590,17 @@ bool GeneratorImpl::EmitType(std::ostream& out,
|
||||||
bool GeneratorImpl::EmitStructType(std::ostream& out,
|
bool GeneratorImpl::EmitStructType(std::ostream& out,
|
||||||
const type::Struct* str,
|
const type::Struct* str,
|
||||||
const std::string& name) {
|
const std::string& name) {
|
||||||
// TODO(dsinclair): Block decoration?
|
auto* sem_str = builder_.Sem().Get(str);
|
||||||
// if (str->impl()->decoration() != ast::Decoration::kNone) {
|
|
||||||
// }
|
auto storage_class_uses = sem_str->StorageClassUsage();
|
||||||
|
if (storage_class_uses.size() ==
|
||||||
|
storage_class_uses.count(ast::StorageClass::kStorage)) {
|
||||||
|
// The only use of the structure is as a storage buffer.
|
||||||
|
// Structures used as storage buffer are read and written to via a
|
||||||
|
// ByteAddressBuffer instead of true structure.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
out << "struct " << name << " {" << std::endl;
|
out << "struct " << name << " {" << std::endl;
|
||||||
|
|
||||||
increment_indent();
|
increment_indent();
|
||||||
|
|
|
@ -42,15 +42,13 @@ TEST_F(HlslGeneratorImplTest_Alias, EmitAlias_NameCollision) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(HlslGeneratorImplTest_Alias, EmitAlias_Struct) {
|
TEST_F(HlslGeneratorImplTest_Alias, EmitAlias_Struct) {
|
||||||
auto* str = create<ast::Struct>(
|
auto* s = Structure("A", {
|
||||||
ast::StructMemberList{
|
Member("a", ty.f32()),
|
||||||
Member("a", ty.f32()),
|
Member("b", ty.i32()),
|
||||||
Member("b", ty.i32()),
|
});
|
||||||
},
|
|
||||||
ast::DecorationList{});
|
|
||||||
|
|
||||||
auto* s = ty.struct_("A", str);
|
|
||||||
auto* alias = ty.alias("B", s);
|
auto* alias = ty.alias("B", s);
|
||||||
|
AST().AddConstructedType(alias);
|
||||||
|
Global("g", alias, ast::StorageClass::kPrivate);
|
||||||
|
|
||||||
GeneratorImpl& gen = Build();
|
GeneratorImpl& gen = Build();
|
||||||
|
|
||||||
|
|
|
@ -916,10 +916,7 @@ TEST_F(HlslGeneratorImplTest_Function,
|
||||||
GeneratorImpl& gen = Build();
|
GeneratorImpl& gen = Build();
|
||||||
|
|
||||||
ASSERT_TRUE(gen.Generate(out)) << gen.error();
|
ASSERT_TRUE(gen.Generate(out)) << gen.error();
|
||||||
EXPECT_EQ(result(), R"(struct Data {
|
EXPECT_EQ(result(), R"(
|
||||||
float d;
|
|
||||||
};
|
|
||||||
|
|
||||||
RWByteAddressBuffer data : register(u0, space0);
|
RWByteAddressBuffer data : register(u0, space0);
|
||||||
|
|
||||||
[numthreads(1, 1, 1)]
|
[numthreads(1, 1, 1)]
|
||||||
|
|
|
@ -171,6 +171,7 @@ TEST_F(HlslGeneratorImplTest_Type, EmitType_StructDecl) {
|
||||||
Member("a", ty.i32()),
|
Member("a", ty.i32()),
|
||||||
Member("b", ty.f32()),
|
Member("b", ty.f32()),
|
||||||
});
|
});
|
||||||
|
Global("g", s, ast::StorageClass::kPrivate);
|
||||||
|
|
||||||
GeneratorImpl& gen = Build();
|
GeneratorImpl& gen = Build();
|
||||||
|
|
||||||
|
@ -182,11 +183,25 @@ TEST_F(HlslGeneratorImplTest_Type, EmitType_StructDecl) {
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(HlslGeneratorImplTest_Type, EmitType_StructDecl_OmittedIfStorageBuffer) {
|
||||||
|
auto* s = Structure("S", {
|
||||||
|
Member("a", ty.i32()),
|
||||||
|
Member("b", ty.f32()),
|
||||||
|
});
|
||||||
|
Global("g", s, ast::StorageClass::kStorage);
|
||||||
|
|
||||||
|
GeneratorImpl& gen = Build();
|
||||||
|
|
||||||
|
ASSERT_TRUE(gen.EmitStructType(out, s, "S")) << gen.error();
|
||||||
|
EXPECT_EQ(result(), "");
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(HlslGeneratorImplTest_Type, EmitType_Struct) {
|
TEST_F(HlslGeneratorImplTest_Type, EmitType_Struct) {
|
||||||
auto* s = Structure("S", {
|
auto* s = Structure("S", {
|
||||||
Member("a", ty.i32()),
|
Member("a", ty.i32()),
|
||||||
Member("b", ty.f32()),
|
Member("b", ty.f32()),
|
||||||
});
|
});
|
||||||
|
Global("g", s, ast::StorageClass::kPrivate);
|
||||||
|
|
||||||
GeneratorImpl& gen = Build();
|
GeneratorImpl& gen = Build();
|
||||||
|
|
||||||
|
@ -203,6 +218,7 @@ TEST_F(HlslGeneratorImplTest_Type, DISABLED_EmitType_Struct_InjectPadding) {
|
||||||
Member("b", ty.f32()),
|
Member("b", ty.f32()),
|
||||||
Member("c", ty.f32(), {MemberAlign(128), MemberSize(128)}),
|
Member("c", ty.f32(), {MemberAlign(128), MemberSize(128)}),
|
||||||
});
|
});
|
||||||
|
Global("g", s, ast::StorageClass::kPrivate);
|
||||||
|
|
||||||
GeneratorImpl& gen = Build();
|
GeneratorImpl& gen = Build();
|
||||||
|
|
||||||
|
@ -223,6 +239,7 @@ TEST_F(HlslGeneratorImplTest_Type, EmitType_Struct_NameCollision) {
|
||||||
Member("double", ty.i32()),
|
Member("double", ty.i32()),
|
||||||
Member("float", ty.f32()),
|
Member("float", ty.f32()),
|
||||||
});
|
});
|
||||||
|
Global("g", s, ast::StorageClass::kPrivate);
|
||||||
|
|
||||||
GeneratorImpl& gen = Build();
|
GeneratorImpl& gen = Build();
|
||||||
|
|
||||||
|
@ -242,6 +259,7 @@ TEST_F(HlslGeneratorImplTest_Type, DISABLED_EmitType_Struct_WithDecoration) {
|
||||||
Member("b", ty.f32()),
|
Member("b", ty.f32()),
|
||||||
},
|
},
|
||||||
{create<ast::StructBlockDecoration>()});
|
{create<ast::StructBlockDecoration>()});
|
||||||
|
Global("g", s, ast::StorageClass::kPrivate);
|
||||||
|
|
||||||
GeneratorImpl& gen = Build();
|
GeneratorImpl& gen = Build();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue