Browse Source

[spirv] Handle alignment & offset of empty structs (#774)

Ehsan 7 years ago
parent
commit
d756ff5094

+ 5 - 0
tools/clang/lib/SPIRV/TypeTranslator.cpp

@@ -885,6 +885,11 @@ TypeTranslator::getAlignmentAndSize(QualType type, LayoutRule rule,
 
 
   // Rule 9
   // Rule 9
   if (const auto *structType = type->getAs<RecordType>()) {
   if (const auto *structType = type->getAs<RecordType>()) {
+    // Special case for handling empty structs, whose size is 0 and has no
+    // requirement over alignment (thus 1).
+    if (structType->getDecl()->field_empty())
+      return {1, 0};
+
     uint32_t maxAlignment = 0;
     uint32_t maxAlignment = 0;
     uint32_t structSize = 0;
     uint32_t structSize = 0;
 
 

+ 43 - 0
tools/clang/test/CodeGenSPIRV/vk.layout.cbuffer.nested.empty.std140.hlsl

@@ -0,0 +1,43 @@
+// Run: %dxc -T vs_6_0 -E main
+
+// CHECK: OpMemberDecorate %OuterStruct 0 Offset 0
+// CHECK: OpMemberDecorate %OuterStruct 1 Offset 0
+// CHECK: OpMemberDecorate %type_Params_cbuffer 0 Offset 0
+
+// CHECK:        %InnerStruct0 = OpTypeStruct
+// CHECK:         %OuterStruct = OpTypeStruct %InnerStruct0 %InnerStruct0
+// CHECK: %type_Params_cbuffer = OpTypeStruct %OuterStruct
+
+struct InnerStruct0 {};
+
+struct InnerStruct1 {};
+
+struct OuterStruct
+{
+  InnerStruct0 s0;
+  InnerStruct1 s1;
+};
+
+struct MyParams
+{
+  OuterStruct constants;
+};
+
+cbuffer Params_cbuffer : register(b0)
+{
+  OuterStruct constants;
+};
+
+MyParams CreateParams()
+{
+  MyParams i;
+  i.constants = constants;
+  return i;
+}
+
+static const MyParams params_vars = CreateParams();
+
+float4 main(float4 pos : POSITION) : SV_POSITION
+{
+  return float4(0, 0, 0, 0);
+}

+ 3 - 0
tools/clang/unittests/SPIRV/CodeGenSPIRVTest.cpp

@@ -811,6 +811,9 @@ TEST_F(FileTest, VulkanLayoutCBufferStd140) {
 TEST_F(FileTest, VulkanLayoutCBufferNestedStd140) {
 TEST_F(FileTest, VulkanLayoutCBufferNestedStd140) {
   runFileTest("vk.layout.cbuffer.nested.std140.hlsl");
   runFileTest("vk.layout.cbuffer.nested.std140.hlsl");
 }
 }
+TEST_F(FileTest, VulkanLayoutCBufferNestedEmptyStd140) {
+  runFileTest("vk.layout.cbuffer.nested.empty.std140.hlsl");
+}
 TEST_F(FileTest, VulkanLayoutSBufferStd430) {
 TEST_F(FileTest, VulkanLayoutSBufferStd430) {
   runFileTest("vk.layout.sbuffer.std430.hlsl");
   runFileTest("vk.layout.sbuffer.std430.hlsl");
 }
 }