diff --git a/tools/clang/lib/SPIRV/AstTypeProbe.cpp b/tools/clang/lib/SPIRV/AstTypeProbe.cpp index 3c0f4e1958..0e88c6dc14 100644 --- a/tools/clang/lib/SPIRV/AstTypeProbe.cpp +++ b/tools/clang/lib/SPIRV/AstTypeProbe.cpp @@ -996,6 +996,14 @@ bool isOrContainsAKindOfStructuredOrByteBuffer(QualType type) { if (isOrContainsAKindOfStructuredOrByteBuffer(field->getType())) return true; } + + if (const auto *cxxDecl = type->getAsCXXRecordDecl()) { + for (const auto &base : cxxDecl->bases()) { + if (isOrContainsAKindOfStructuredOrByteBuffer(base.getType())) { + return true; + } + } + } } return false; } diff --git a/tools/clang/test/CodeGenSPIRV/oo.inheritance.base-with-byte-address-buffer.hlsl b/tools/clang/test/CodeGenSPIRV/oo.inheritance.base-with-byte-address-buffer.hlsl new file mode 100644 index 0000000000..be62028e94 --- /dev/null +++ b/tools/clang/test/CodeGenSPIRV/oo.inheritance.base-with-byte-address-buffer.hlsl @@ -0,0 +1,30 @@ +// RUN: %dxc -T ps_6_0 -E main -fvk-use-dx-layout -fspv-reflect -fspv-target-env=vulkan1.1 + +// We want to check that we correctly set "contains-alias-component" when the +// class has a parent with ByteAddressBuffer, which later affects the result of +// `loadIfAliasVarRef(..)` by letting it emit a load instruction of the pointer. +// As a result, it prevents users of `loadIfAliasVarRef(..)` from just +// referencing an access chain without a proper load. + +struct Base { + ByteAddressBuffer buffer; +}; + +struct Child : Base { + float load(in uint offset) { +// CHECK: %param_this = OpFunctionParameter %_ptr_Function_Child +// CHECK: [[base:%\w+]] = OpAccessChain %_ptr_Function_Base %param_this %uint_0 +// CHECK: [[ptrToBuffer:%\w+]] = OpAccessChain %_ptr_Function__ptr_Uniform_type_ByteAddressBuffer [[base]] %int_0 + +// This test case is mainly intended to confirm that we emit the following instruction +// CHECK: [[buffer:%\w+]] = OpLoad %_ptr_Uniform_type_ByteAddressBuffer [[ptrToBuffer]] + +// CHECK: OpAccessChain %_ptr_Uniform_uint [[buffer]] %uint_0 + return asfloat(buffer.Load(offset)); + } +}; + +void main(out float target : SV_Target) { + Child foo; + target = foo.load(0); +} diff --git a/tools/clang/unittests/SPIRV/CodeGenSpirvTest.cpp b/tools/clang/unittests/SPIRV/CodeGenSpirvTest.cpp index 1b8ec26bdc..278c109c9a 100644 --- a/tools/clang/unittests/SPIRV/CodeGenSpirvTest.cpp +++ b/tools/clang/unittests/SPIRV/CodeGenSpirvTest.cpp @@ -699,6 +699,9 @@ TEST_F(FileTest, InheritanceCallMethodOfBase) { runFileTest("oo.inheritance.call.base.method.hlsl", Expect::Success, /* runValidation */ false); } +TEST_F(FileTest, InheritanceBaseWithByteAddressBuffer) { + runFileTest("oo.inheritance.base-with-byte-address-buffer.hlsl"); +} TEST_F(FileTest, InheritanceCallMethodWithSameBaseMethodName) { runFileTest("oo.call.method.with.same.base.method.name.hlsl"); }