Просмотр исходного кода

[spirv] Implement relaxed layout for vector types (#1092)

Based on GLSL std140/std430 layout rules, relaxed layout allows
using vector's element type's alignment as the vector types's
alignment, so that we can pack a float value and a float3 value
tightly. This is the default right now.

Also add an option, -fvk-use-glsl-layout, to turn off the relaxed
layout for vectors and use conventional GLSL std140/std430 layout
rules.
Lei Zhang 7 лет назад
Родитель
Сommit
70990344ed

+ 30 - 16
docs/SPIR-V.rst

@@ -555,18 +555,30 @@ Please see the following sections for the details of each type. As a summary:
 =========================== ================== ========================== ==================== =================
          HLSL Type          Vulkan Buffer Type Default Memory Layout Rule SPIR-V Storage Class SPIR-V Decoration
 =========================== ================== ========================== ==================== =================
-``cbuffer``                   Uniform Buffer      GLSL ``std140``            ``Uniform``        ``Block``
-``ConstantBuffer``            Uniform Buffer      GLSL ``std140``            ``Uniform``        ``Block``
-``tbuffer``                   Storage Buffer      GLSL ``std430``            ``Uniform``        ``BufferBlock``
-``TextureBuffer``             Storage Buffer      GLSL ``std430``            ``Uniform``        ``BufferBlock``
-``StructuredBuffer``          Storage Buffer      GLSL ``std430``            ``Uniform``        ``BufferBlock``
-``RWStructuredBuffer``        Storage Buffer      GLSL ``std430``            ``Uniform``        ``BufferBlock``
-``AppendStructuredBuffer``    Storage Buffer      GLSL ``std430``            ``Uniform``        ``BufferBlock``
-``ConsumeStructuredBuffer``   Storage Buffer      GLSL ``std430``            ``Uniform``        ``BufferBlock``
-``ByteAddressBuffer``         Storage Buffer      GLSL ``std430``            ``Uniform``        ``BufferBlock``
-``RWByteAddressBuffer``       Storage Buffer      GLSL ``std430``            ``Uniform``        ``BufferBlock``
+``cbuffer``                   Uniform Buffer    Relaxed GLSL ``std140``      ``Uniform``        ``Block``
+``ConstantBuffer``            Uniform Buffer    Relaxed GLSL ``std140``      ``Uniform``        ``Block``
+``tbuffer``                   Storage Buffer    Relaxed GLSL ``std430``      ``Uniform``        ``BufferBlock``
+``TextureBuffer``             Storage Buffer    Relaxed GLSL ``std430``      ``Uniform``        ``BufferBlock``
+``StructuredBuffer``          Storage Buffer    Relaxed GLSL ``std430``      ``Uniform``        ``BufferBlock``
+``RWStructuredBuffer``        Storage Buffer    Relaxed GLSL ``std430``      ``Uniform``        ``BufferBlock``
+``AppendStructuredBuffer``    Storage Buffer    Relaxed GLSL ``std430``      ``Uniform``        ``BufferBlock``
+``ConsumeStructuredBuffer``   Storage Buffer    Relaxed GLSL ``std430``      ``Uniform``        ``BufferBlock``
+``ByteAddressBuffer``         Storage Buffer    Relaxed GLSL ``std430``      ``Uniform``        ``BufferBlock``
+``RWByteAddressBuffer``       Storage Buffer    Relaxed GLSL ``std430``      ``Uniform``        ``BufferBlock``
 =========================== ================== ========================== ==================== =================
 
+In the above, "relaxed" GLSL ``std140``/``std430`` rules mean GLSL
+``std140``/``std430`` rules with the following modification for vector type
+alignment:
+
+1. The alignment of a vector type is set to be the alignment of its element type
+2. If the above causes an improper straddle (see Vulkan spec
+   `14.5.4. Offset and Stride Assignment <https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#interfaces-resources-layout>`_),
+   the alignment will be set to 16 bytes.
+
+To use the conventional GLSL ``std140``/``std430`` rules for resources,
+you can use the ``-fvk-use-glsl-layout`` option.
+
 To know more about the Vulkan buffer types, please refer to the Vulkan spec
 `13.1 Descriptor Types <https://www.khronos.org/registry/vulkan/specs/1.0-wsi_extensions/html/vkspec.html#descriptorsets-types>`_.
 
@@ -577,8 +589,8 @@ These two buffer types are treated as uniform buffers using Vulkan's
 terminology. They are translated into an ``OpTypeStruct`` with the
 necessary layout decorations (``Offset``, ``ArrayStride``, ``MatrixStride``,
 ``RowMajor``, ``ColMajor``) and the ``Block`` decoration. The layout rule
-used is GLSL ``std140`` (by default). A variable declared as one of these
-types will be placed in the ``Uniform`` storage class.
+used is relaxed GLSL ``std140`` (by default). A variable declared as one of
+these types will be placed in the ``Uniform`` storage class.
 
 For example, for the following HLSL source code:
 
@@ -616,8 +628,8 @@ terminology. They are translated into an ``OpTypeStruct`` with the
 necessary layout decorations (``Offset``, ``ArrayStride``, ``MatrixStride``,
 ``RowMajor``, ``ColMajor``) and the ``BufferBlock`` decoration. All the struct
 members are also decorated with ``NonWritable`` decoration. The layout rule
-used is GLSL ``std430`` (by default). A variable declared as one of these
-types will be placed in the ``Uniform`` storage class.
+used is relaxed GLSL ``std430`` (by default). A variable declared as one of
+these types will be placed in the ``Uniform`` storage class.
 
 
 ``StructuredBuffer`` and ``RWStructuredBuffer``
@@ -627,7 +639,7 @@ types will be placed in the ``Uniform`` storage class.
 using Vulkan's terminology. It is translated into an ``OpTypeStruct`` containing
 an ``OpTypeRuntimeArray`` of type ``T``, with necessary layout decorations
 (``Offset``, ``ArrayStride``, ``MatrixStride``, ``RowMajor``, ``ColMajor``) and
-the ``BufferBlock`` decoration.  The default layout rule used is GLSL
+the ``BufferBlock`` decoration.  The default layout rule used is relaxed GLSL
 ``std430``. A variable declared as one of these types will be placed in the
 ``Uniform`` storage class.
 
@@ -678,7 +690,7 @@ storage buffer using Vulkan's terminology. It is translated into an
 ``OpTypeStruct`` containing an ``OpTypeRuntimeArray`` of type ``T``, with
 necessary layout decorations (``Offset``, ``ArrayStride``, ``MatrixStride``,
 ``RowMajor``, ``ColMajor``) and the ``BufferBlock`` decoration. The default
-layout rule used is GLSL ``std430``.
+layout rule used is relaxed GLSL ``std430``.
 
 A variable declared as one of these types will be placed in the ``Uniform``
 storage class. Besides, each variable will have an associated counter variable
@@ -2519,6 +2531,8 @@ codegen for Vulkan:
 - ``-fvk-ignore-unused-resources``: Avoids emitting SPIR-V code for resources
   defined but not statically referenced by the call tree of the entry point
   in question.
+- ``-fvk-use-glsl-layout``: Uses conventional GLSL ``std140``/``std430`` layout
+  rules for resources.
 - ``-fvk-invert-y``: Inverts SV_Position.y before writing to stage output.
   Used to accommodate the difference between Vulkan's coordinate system and
   DirectX's. Only allowed in VS/DS/GS.

+ 1 - 0
include/dxc/Support/HLSLOptions.h

@@ -162,6 +162,7 @@ public:
   bool GenSPIRV; // OPT_spirv
   bool VkIgnoreUnusedResources; // OPT_fvk_ignore_used_resources
   bool VkInvertY; // OPT_fvk_invert_y
+  bool VkUseGlslLayout; // OPT_fvk_use_glsl_layout
   llvm::StringRef VkStageIoOrder; // OPT_fvk_stage_io_order
   llvm::SmallVector<uint32_t, 4> VkBShift; // OPT_fvk_b_shift
   llvm::SmallVector<uint32_t, 4> VkTShift; // OPT_fvk_t_shift

+ 2 - 0
include/dxc/Support/HLSLOptions.td

@@ -250,6 +250,8 @@ def fvk_u_shift : MultiArg<["-"], "fvk-u-shift", 2>, MetaVarName<"<shift> <space
   HelpText<"Specify Vulkan binding number shift for u-type register">;
 def fvk_invert_y: Flag<["-"], "fvk-invert-y">, Group<spirv_Group>, Flags<[CoreOption, DriverOption]>,
   HelpText<"Invert SV_Position.y in VS/DS/GS to accommodate Vulkan's coordinate system">;
+def fvk_use_glsl_layout: Flag<["-"], "fvk-use-glsl-layout">, Group<spirv_Group>, Flags<[CoreOption, DriverOption]>,
+  HelpText<"Use conventional GLSL std140/std430 layout for resources">;
 // SPIRV Change Ends
 
 //////////////////////////////////////////////////////////////////////////////

+ 2 - 0
lib/DxcSupport/HLSLOptions.cpp

@@ -483,6 +483,7 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude,
 #ifdef ENABLE_SPIRV_CODEGEN
   const bool genSpirv = opts.GenSPIRV = Args.hasFlag(OPT_spirv, OPT_INVALID, false);
   opts.VkInvertY = Args.hasFlag(OPT_fvk_invert_y, OPT_INVALID, false);
+  opts.VkUseGlslLayout = Args.hasFlag(OPT_fvk_use_glsl_layout, OPT_INVALID, false);
   opts.VkIgnoreUnusedResources = Args.hasFlag(OPT_fvk_ignore_unused_resources, OPT_INVALID, false);
 
   // Collects the arguments for -fvk-{b|s|t|u}-shift.
@@ -522,6 +523,7 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude,
 #else
   if (Args.hasFlag(OPT_spirv, OPT_INVALID, false) ||
       Args.hasFlag(OPT_fvk_invert_y, OPT_INVALID, false) ||
+      Args.hasFlag(OPT_fvk_use_glsl_layout, OPT_INVALID, false) ||
       Args.hasFlag(OPT_fvk_ignore_unused_resources, OPT_INVALID, false) ||
       !Args.getLastArgValue(OPT_fvk_stage_io_order_EQ).empty() ||
       !Args.getLastArgValue(OPT_fvk_b_shift).empty() ||

+ 1 - 0
tools/clang/include/clang/SPIRV/EmitSPIRVOptions.h

@@ -20,6 +20,7 @@ struct EmitSPIRVOptions {
   bool defaultRowMajor;
   bool disableValidation;
   bool invertY;
+  bool useGlslLayout;
   bool ignoreUnusedResources;
   bool enable16BitTypes;
   llvm::StringRef stageIoOrder;

+ 50 - 6
tools/clang/lib/SPIRV/TypeTranslator.cpp

@@ -32,6 +32,15 @@ inline void roundToPow2(uint32_t *val, uint32_t pow2) {
   assert(pow2 != 0);
   *val = (*val + pow2 - 1) & ~(pow2 - 1);
 }
+
+/// Returns true if the given vector type (of the given size) crosses the
+/// 4-component vector boundary if placed at the given offset.
+bool improperStraddle(QualType type, int size, int offset) {
+  assert(TypeTranslator::isVectorType(type));
+  return size <= 16 ? offset / 16 != (offset + size - 1) / 16
+                    : offset % 16 != 0;
+}
+
 } // anonymous namespace
 
 bool TypeTranslator::isRelaxedPrecisionType(QualType type,
@@ -1079,11 +1088,13 @@ TypeTranslator::getLayoutDecorations(const DeclContext *decl, LayoutRule rule) {
     std::tie(memberAlignment, memberSize) =
         getAlignmentAndSize(fieldType, rule, isRowMajor, &stride);
 
+    alignUsingHLSLRelaxedLayout(fieldType, memberSize, &memberAlignment,
+                                &offset);
+
     // Each structure-type member must have an Offset Decoration.
     if (const auto *offsetAttr = field->getAttr<VKOffsetAttr>())
       offset = offsetAttr->getOffset();
-    else
-      roundToPow2(&offset, memberAlignment);
+
     decorations.push_back(Decoration::getOffset(*spirvContext, offset, index));
     offset += memberSize;
 
@@ -1330,6 +1341,37 @@ TypeTranslator::translateSampledTypeToImageFormat(QualType sampledType) {
   return spv::ImageFormat::Unknown;
 }
 
+void TypeTranslator::alignUsingHLSLRelaxedLayout(QualType fieldType,
+                                                 uint32_t fieldSize,
+                                                 uint32_t *fieldAlignment,
+                                                 uint32_t *currentOffset) {
+  bool fieldIsVecType = false;
+
+  if (!spirvOptions.useGlslLayout) {
+    // Adjust according to HLSL relaxed layout rules.
+    // Aligning vectors as their element types so that we can pack a float
+    // and a float3 tightly together.
+    QualType vecElemType = {};
+    if (fieldIsVecType = isVectorType(fieldType, &vecElemType)) {
+      uint32_t scalarAlignment = 0;
+      std::tie(scalarAlignment, std::ignore) =
+          getAlignmentAndSize(vecElemType, LayoutRule::Void, false, nullptr);
+      if (scalarAlignment <= 4)
+        *fieldAlignment = scalarAlignment;
+    }
+  }
+
+  roundToPow2(currentOffset, *fieldAlignment);
+
+  // Adjust according to HLSL relaxed layout rules.
+  // Bump to 4-component vector alignment if there is a bad straddle
+  if (!spirvOptions.useGlslLayout && fieldIsVecType &&
+      improperStraddle(fieldType, fieldSize, *currentOffset)) {
+    *fieldAlignment = kStd140Vec4Alignment;
+    roundToPow2(currentOffset, *fieldAlignment);
+  }
+}
+
 std::pair<uint32_t, uint32_t>
 TypeTranslator::getAlignmentAndSize(QualType type, LayoutRule rule,
                                     const bool isRowMajor, uint32_t *stride) {
@@ -1405,8 +1447,8 @@ TypeTranslator::getAlignmentAndSize(QualType type, LayoutRule rule,
         case BuiltinType::ULongLong:
           return {8, 8};
         default:
-          emitError("primitive type %0 unimplemented")
-              << builtinType->getTypeClassName();
+          emitError("alignment and size calculation for type %0 unimplemented")
+              << type;
           return {0, 0};
         }
   }
@@ -1463,10 +1505,12 @@ TypeTranslator::getAlignmentAndSize(QualType type, LayoutRule rule,
       std::tie(memberAlignment, memberSize) =
           getAlignmentAndSize(field->getType(), rule, isRowMajor, stride);
 
+      alignUsingHLSLRelaxedLayout(field->getType(), memberSize,
+                                  &memberAlignment, &structSize);
+
       // The base alignment of the structure is N, where N is the largest
       // base alignment value of any of its members...
       maxAlignment = std::max(maxAlignment, memberAlignment);
-      roundToPow2(&structSize, memberAlignment);
       structSize += memberSize;
     }
 
@@ -1504,7 +1548,7 @@ TypeTranslator::getAlignmentAndSize(QualType type, LayoutRule rule,
     return {alignment, size};
   }
 
-  emitError("type %0 unimplemented") << type->getTypeClassName();
+  emitError("alignment and size calculation for type %0 unimplemented") << type;
   return {0, 0};
 }
 

+ 10 - 1
tools/clang/lib/SPIRV/TypeTranslator.h

@@ -261,10 +261,19 @@ private:
   /// instructions and returns the <result-id>. Returns 0 on failure.
   uint32_t translateResourceType(QualType type, LayoutRule rule);
 
-  /// \bried For the given sampled type, returns the corresponding image format
+  /// \brief For the given sampled type, returns the corresponding image format
   /// that can be used to create an image object.
   spv::ImageFormat translateSampledTypeToImageFormat(QualType type);
 
+  /// \brief Aligns currentOffset properly to allow packing vectors in the HLSL
+  /// way: using the element type's alignment as the vector alignment, as long
+  /// as there is no improper straddle.
+  /// fieldSize and fieldAlignment are the original size and alignment
+  /// calculated without considering the HLSL vector relaxed rule.
+  void alignUsingHLSLRelaxedLayout(QualType fieldType, uint32_t fieldSize,
+                                   uint32_t *fieldAlignment,
+                                   uint32_t *currentOffset);
+
 public:
   /// \brief Returns the alignment and size in bytes for the given type
   /// according to the given LayoutRule.

+ 1 - 1
tools/clang/test/CodeGenSPIRV/method.append-structured-buffer.get-dimensions.hlsl

@@ -1,4 +1,4 @@
-// Run: %dxc -T vs_6_0 -E main
+// Run: %dxc -T vs_6_0 -E main -fvk-use-glsl-layout
 
 struct S {
     float a;

+ 1 - 1
tools/clang/test/CodeGenSPIRV/method.consume-structured-buffer.get-dimensions.hlsl

@@ -1,4 +1,4 @@
-// Run: %dxc -T vs_6_0 -E main
+// Run: %dxc -T vs_6_0 -E main -fvk-use-glsl-layout
 
 struct S {
     float a;

+ 1 - 1
tools/clang/test/CodeGenSPIRV/method.structured-buffer.get-dimensions.hlsl

@@ -1,4 +1,4 @@
-// Run: %dxc -T ps_6_0 -E main
+// Run: %dxc -T ps_6_0 -E main -fvk-use-glsl-layout
 
 struct SBuffer {
   float4   f1;

+ 1 - 1
tools/clang/test/CodeGenSPIRV/vk.layout.cbuffer.std140.hlsl

@@ -1,4 +1,4 @@
-// Run: %dxc -T vs_6_0 -E main
+// Run: %dxc -T vs_6_0 -E main -fvk-use-glsl-layout
 
 struct R {     // Alignment                           Offset     Size       Next
     float2 rf; // 8(vec2)                          -> 0        + 8(vec2)  = 8

+ 1 - 1
tools/clang/test/CodeGenSPIRV/vk.layout.push-constant.std430.hlsl

@@ -1,4 +1,4 @@
-// Run: %dxc -T vs_6_0 -E main
+// Run: %dxc -T vs_6_0 -E main -fvk-use-glsl-layout
 
 // CHECK: OpDecorate %_arr_v2float_uint_3 ArrayStride 8
 // CHECK: OpDecorate %_arr_mat3v2float_uint_2 ArrayStride 32

+ 1 - 1
tools/clang/test/CodeGenSPIRV/vk.layout.sbuffer.std430.hlsl

@@ -1,4 +1,4 @@
-// Run: %dxc -T ps_6_0 -E main
+// Run: %dxc -T ps_6_0 -E main -fvk-use-glsl-layout
 
 struct R {     // Alignment       Offset     Size       Next
     float2 rf; // 8(vec2)      -> 0        + 8(vec2)  = 8

+ 124 - 0
tools/clang/test/CodeGenSPIRV/vk.layout.vector.relaxed.hlsl

@@ -0,0 +1,124 @@
+// Run: %dxc -T ps_6_0 -E main
+
+    // For ConstantBuffer & cbuffer
+// CHECK: OpMemberDecorate %S 0 Offset 0
+// CHECK: OpMemberDecorate %S 1 Offset 4
+// CHECK: OpMemberDecorate %S 2 Offset 16
+// CHECK: OpMemberDecorate %S 3 Offset 28
+// CHECK: OpMemberDecorate %S 4 Offset 32
+// CHECK: OpMemberDecorate %S 5 Offset 36
+// CHECK: OpMemberDecorate %S 6 Offset 44
+// CHECK: OpMemberDecorate %S 7 Offset 48
+// CHECK: OpMemberDecorate %S 8 Offset 56
+// CHECK: OpMemberDecorate %S 9 Offset 64
+// CHECK: OpMemberDecorate %S 10 Offset 80
+// CHECK: OpMemberDecorate %S 11 Offset 92
+// CHECK: OpMemberDecorate %S 12 Offset 96
+// CHECK: OpMemberDecorate %S 13 Offset 112
+// CHECK: OpMemberDecorate %S 14 Offset 128
+// CHECK: OpMemberDecorate %S 15 Offset 140
+// CHECK: OpMemberDecorate %S 16 Offset 144
+// CHECK: OpMemberDecorate %S 17 Offset 160
+// CHECK: OpMemberDecorate %S 18 Offset 176
+// CHECK: OpMemberDecorate %S 19 Offset 192
+// CHECK: OpMemberDecorate %S 20 Offset 208
+// CHECK: OpMemberDecorate %S 21 Offset 240
+// CHECK: OpMemberDecorate %S 22 Offset 272
+// CHECK: OpMemberDecorate %S 23 Offset 304
+
+    // For StructuredBuffer & tbuffer
+// CHECK: OpMemberDecorate %S_0 0 Offset 0
+// CHECK: OpMemberDecorate %S_0 1 Offset 4
+// CHECK: OpMemberDecorate %S_0 2 Offset 16
+// CHECK: OpMemberDecorate %S_0 3 Offset 28
+// CHECK: OpMemberDecorate %S_0 4 Offset 32
+// CHECK: OpMemberDecorate %S_0 5 Offset 36
+// CHECK: OpMemberDecorate %S_0 6 Offset 44
+// CHECK: OpMemberDecorate %S_0 7 Offset 48
+// CHECK: OpMemberDecorate %S_0 8 Offset 56
+// CHECK: OpMemberDecorate %S_0 9 Offset 64
+// CHECK: OpMemberDecorate %S_0 10 Offset 80
+// CHECK: OpMemberDecorate %S_0 11 Offset 92
+// CHECK: OpMemberDecorate %S_0 12 Offset 96
+// CHECK: OpMemberDecorate %S_0 13 Offset 112
+// CHECK: OpMemberDecorate %S_0 14 Offset 128
+// CHECK: OpMemberDecorate %S_0 15 Offset 140
+// CHECK: OpMemberDecorate %S_0 16 Offset 144
+// CHECK: OpMemberDecorate %S_0 17 Offset 160
+// CHECK: OpMemberDecorate %S_0 18 Offset 176
+// CHECK: OpMemberDecorate %S_0 19 Offset 192
+// CHECK: OpMemberDecorate %S_0 20 Offset 196
+// CHECK: OpMemberDecorate %S_0 21 Offset 208
+// CHECK: OpMemberDecorate %S_0 22 Offset 240
+// CHECK: OpMemberDecorate %S_0 23 Offset 272
+
+// CHECK: OpDecorate %_runtimearr_T ArrayStride 288
+
+// CHECK:     %type_ConstantBuffer_T = OpTypeStruct %S
+// CHECK:                         %T = OpTypeStruct %S_0
+// CHECK:   %type_StructuredBuffer_T = OpTypeStruct %_runtimearr_T
+// CHECK: %type_RWStructuredBuffer_T = OpTypeStruct %_runtimearr_T
+// CHECK:              %type_TBuffer = OpTypeStruct %S_0
+
+// CHECK:   %MyCBuffer = OpVariable %_ptr_Uniform_type_ConstantBuffer_T Uniform
+// CHECK:   %MySBuffer = OpVariable %_ptr_Uniform_type_StructuredBuffer_T Uniform
+// CHECK: %MyRWSBuffer = OpVariable %_ptr_Uniform_type_RWStructuredBuffer_T Uniform
+// CHECK:     %CBuffer = OpVariable %_ptr_Uniform_type_ConstantBuffer_T Uniform
+// CHECK:     %TBuffer = OpVariable %_ptr_Uniform_type_TBuffer Uniform
+
+struct S {
+    float  f0;
+    float3 f1;
+
+    float3 f2;
+    float1 f3;
+
+    float  f4;
+    float2 f5;
+    float1 f6;
+
+    float2 f7;
+    float2 f8;
+
+    float2 f9;
+    float3 f10;
+    float  f11;
+
+    float1 f12;
+    float4 f13;
+    float3 f14;
+    float  f15;
+
+    float1 f16[1];
+    float3 f17[1];
+
+    float3 f18[1];
+    float  f19[1];
+
+    float1 f20[2];
+    float3 f21[2];
+
+    float3 f22[2];
+    float  f23[2];
+};
+
+struct T {
+    S s;
+};
+
+
+    ConstantBuffer<T> MyCBuffer;
+  StructuredBuffer<T> MySBuffer;
+RWStructuredBuffer<T> MyRWSBuffer;
+
+cbuffer CBuffer {
+    S CB_s;
+};
+
+tbuffer TBuffer {
+    S TB_s;
+};
+
+float4 main() : SV_Target {
+    return MyCBuffer.s.f0 + MySBuffer[0].s.f4 + CB_s.f11 + TB_s.f15;
+}

+ 1 - 0
tools/clang/tools/dxcompiler/dxcompilerobj.cpp

@@ -469,6 +469,7 @@ public:
           spirvOpts.codeGenHighLevel = opts.CodeGenHighLevel;
           spirvOpts.disableValidation = opts.DisableValidation;
           spirvOpts.invertY = opts.VkInvertY;
+          spirvOpts.useGlslLayout = opts.VkUseGlslLayout;
           spirvOpts.ignoreUnusedResources = opts.VkIgnoreUnusedResources;
           spirvOpts.defaultRowMajor = opts.DefaultRowMajor;
           spirvOpts.stageIoOrder = opts.VkStageIoOrder;

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

@@ -1217,6 +1217,11 @@ TEST_F(FileTest, VulkanLayout64BitTypesStd430) {
 TEST_F(FileTest, VulkanLayout64BitTypesStd140) {
   runFileTest("vk.layout.64bit-types.std140.hlsl");
 }
+TEST_F(FileTest, VulkanLayoutVectorRelaxedLayout) {
+  // Allows vectors to be aligned according to their element types, if not
+  // causing improper straddle
+  runFileTest("vk.layout.vector.relaxed.hlsl");
+}
 
 TEST_F(FileTest, VulkanLayoutPushConstantStd430) {
   runFileTest("vk.layout.push-constant.std430.hlsl");