Browse Source

[spirv] Fix DX layout struct base alignment (#1523)

For cbuffer/tbuffer, struct type's base alignment should be
rounded up to 16.
Lei Zhang 7 years ago
parent
commit
df1ee0c331

+ 2 - 2
tools/clang/lib/SPIRV/TypeTranslator.cpp

@@ -1790,7 +1790,6 @@ TypeTranslator::getAlignmentAndSize(QualType type, SpirvLayoutRule rule,
   // - Vector base alignment is set as its element type's base alignment.
   // - Arrays/structs do not need to have padding at the end; arrays/structs do
   //   not affect the base offset of the member following them.
-  // - Struct base alignment does not need to be rounded up to a multiple of 16.
   //
   // FxcSBuffer:
   // - Vector/matrix/array base alignment is set as its element type's base
@@ -1935,7 +1934,8 @@ TypeTranslator::getAlignmentAndSize(QualType type, SpirvLayoutRule rule,
     }
 
     if (rule == SpirvLayoutRule::GLSLStd140 ||
-        rule == SpirvLayoutRule::RelaxedGLSLStd140) {
+        rule == SpirvLayoutRule::RelaxedGLSLStd140 ||
+        rule == SpirvLayoutRule::FxcCTBuffer) {
       // ... and rounded up to the base alignment of a vec4.
       maxAlignment = roundToPow2(maxAlignment, kStd140Vec4Alignment);
     }

+ 33 - 0
tools/clang/test/CodeGenSPIRV/vk.layout.cbuffer.fxc.1.hlsl

@@ -0,0 +1,33 @@
+// Run: %dxc -T ps_6_0 -E main -fvk-use-dx-layout
+
+struct S {
+  float a;
+};
+
+// CHECK: OpMemberDecorate %T 0 Offset 0
+// CHECK: OpMemberDecorate %T 1 Offset 16
+// CHECK: OpMemberDecorate %T 2 Offset 20
+// CHECK: OpMemberDecorate %T 3 Offset 32
+
+struct T {
+  float a;
+  S     b;
+  float c;
+  S     d;
+};
+
+// CHECK: %type_CB = OpTypeStruct %T
+
+cbuffer CB {
+  T CB_T;
+};
+
+// CHECK: %type_TB = OpTypeStruct %T
+
+tbuffer TB {
+  T TB_T;
+};
+
+float4 main() : SV_Target {
+  return CB_T.a + TB_T.a;
+}

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

@@ -1604,6 +1604,12 @@ TEST_F(FileTest, VulkanLayoutFxcRulesCBuffer) {
   runFileTest("vk.layout.cbuffer.fxc.hlsl");
 }
 
+TEST_F(FileTest, VulkanLayoutFxcRulesCBuffer1) {
+  // cbuffer/tbuffer/ConstantBuffer/TextureBuffer with fxc layout rules
+  setDxLayout();
+  runFileTest("vk.layout.cbuffer.fxc.1.hlsl");
+}
+
 TEST_F(FileTest, VulkanSubpassInput) { runFileTest("vk.subpass-input.hlsl"); }
 TEST_F(FileTest, VulkanSubpassInputBinding) {
   runFileTest("vk.subpass-input.binding.hlsl");