فهرست منبع

[spirv] Add support for .GatherRGBA() methods on texture types (#682)

Also extended tests for .Gather() tests to cover scalar element
types and vector element types with less than 4 components.
Lei Zhang 8 سال پیش
والد
کامیت
3a6f80eb1b

+ 31 - 3
docs/SPIR-V.rst

@@ -1346,6 +1346,8 @@ image and the ``location`` passed to the function are used as arguments to
 ``OpImageSampleImplicitLod``, with the optional ``offset`` tranlated into
 ``OpImageSampleImplicitLod``, with the optional ``offset`` tranlated into
 addtional SPIR-V image operands ``ConstOffset`` or ``Offset`` on it.
 addtional SPIR-V image operands ``ConstOffset`` or ``Offset`` on it.
 
 
+The overload with the status parameter are not supported.
+
 ``.SampleLevel(sampler, location, lod[, offset])``
 ``.SampleLevel(sampler, location, lod[, offset])``
 ++++++++++++++++++++++++++++++++++++++++++++++++++
 ++++++++++++++++++++++++++++++++++++++++++++++++++
 
 
@@ -1359,6 +1361,8 @@ is attached to the instruction as an SPIR-V image operands ``Lod``. The optional
 ``offset`` is also tranlated into addtional SPIR-V image operands ``ConstOffset``
 ``offset`` is also tranlated into addtional SPIR-V image operands ``ConstOffset``
 or ``Offset`` on it.
 or ``Offset`` on it.
 
 
+The overload with the status parameter are not supported.
+
 ``.SampleGrad(sampler, location, ddx, ddy[, offset])``
 ``.SampleGrad(sampler, location, ddx, ddy[, offset])``
 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
 
@@ -1368,6 +1372,8 @@ Similarly to ``.SampleLevel``, the ``ddx`` and ``ddy`` parameter are attached to
 the ``OpImageSampleExplicitLod`` instruction as an SPIR-V image operands
 the ``OpImageSampleExplicitLod`` instruction as an SPIR-V image operands
 ``Grad``.
 ``Grad``.
 
 
+The overload with the status parameter are not supported.
+
 ``.SampleBias(sampler, location, bias[, offset])``
 ``.SampleBias(sampler, location, bias[, offset])``
 ++++++++++++++++++++++++++++++++++++++++++++++++++
 ++++++++++++++++++++++++++++++++++++++++++++++++++
 
 
@@ -1377,14 +1383,34 @@ The translation is similar to ``.Sample()``, with the ``bias`` parameter
 attached to the ``OpImageSampleImplicitLod`` instruction as an SPIR-V image
 attached to the ``OpImageSampleImplicitLod`` instruction as an SPIR-V image
 operands ``Bias``.
 operands ``Bias``.
 
 
-``.Gather(sampler, location[, offset])``
-++++++++++++++++++++++++++++++++++++++++
+The overload with the status parameter are not supported.
+
+``.Gather()``
++++++++++++++
 
 
 Available to ``Texture2D``, ``Texture2DArray``, ``TextureCube``, and
 Available to ``Texture2D``, ``Texture2DArray``, ``TextureCube``, and
 ``TextureCubeArray``.
 ``TextureCubeArray``.
 
 
 The translation is similar to ``.Sample()``, but the ``OpImageGather``
 The translation is similar to ``.Sample()``, but the ``OpImageGather``
-instruction is used.
+instruction is used, with component setting to 0.
+
+The overload with the status parameter are not supported.
+
+``.GatherRed()``, ``.GatherGreen()``, ``.GatherBlue()``, ``.GatherAlpha()``
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+Available to ``Texture2D``, ``Texture2DArray``, ``TextureCube``, and
+``TextureCubeArray``.
+
+The ``OpImageGather`` instruction is used to translate these functions, with
+component setting to 0, 1, 2, and 3 respectively.
+
+There are a few overloads for these functions:
+
+- For those overloads taking 4 offset parameters, those offset parameters will
+  be conveyed as an additional ``ConstOffsets`` image operands to the
+  instruction. So those offset parameters must all be constant values.
+- Those overloads with the status parameter are not supported.
 
 
 ``.Load(location[, sampleIndex][, offset])``
 ``.Load(location[, sampleIndex][, offset])``
 ++++++++++++++++++++++++++++++++++++++++++++
 ++++++++++++++++++++++++++++++++++++++++++++
@@ -1398,6 +1424,8 @@ The return value of ``OpImageFetch`` is always a four-component vector; so
 proper additional instructions are generated to truncate the vector and return
 proper additional instructions are generated to truncate the vector and return
 the desired number of elements.
 the desired number of elements.
 
 
+The overload with the status parameter are not supported.
+
 ``operator[]``
 ``operator[]``
 ++++++++++++++
 ++++++++++++++
 Handled similarly as ``.Load()``.
 Handled similarly as ``.Load()``.

+ 72 - 0
tools/clang/lib/SPIRV/SPIRVEmitter.cpp

@@ -1691,6 +1691,70 @@ SPIRVEmitter::processTextureLevelOfDetail(const CXXMemberCallExpr *expr) {
                                            {0});
                                            {0});
 }
 }
 
 
+uint32_t SPIRVEmitter::processTextureGatherRGBA(const CXXMemberCallExpr *expr,
+                                                const uint32_t component) {
+  // Parameters for .Gather{Red|Green|Blue|Alpha}() are one of the following two
+  // sets:
+  // * SamplerState s, float2 location, int2 offset
+  // * SamplerState s, float2 location, int2 offset0, int2 offset1,
+  //   int offset2, int2 offset3
+  // An additional out uint status parameter can appear in both of the above,
+  // which we does not support yet.
+  // Return type is always a 4-component vector.
+  const FunctionDecl *callee = expr->getDirectCallee();
+  const auto numArgs = expr->getNumArgs();
+
+  if (numArgs != 3 && numArgs != 6) {
+    emitError("unsupported '%0' method call with status parameter",
+              expr->getExprLoc())
+        << callee->getName() << expr->getSourceRange();
+    return 0;
+  }
+
+  const auto *imageExpr = expr->getImplicitObjectArgument();
+
+  const uint32_t image = loadIfGLValue(imageExpr);
+  const uint32_t sampler = doExpr(expr->getArg(0));
+  const uint32_t coordinate = doExpr(expr->getArg(1));
+
+  uint32_t constOffset = 0, varOffset = 0, constOffsets = 0;
+  if (numArgs == 3) {
+    // One offset parameter
+    const uint32_t offset = tryToEvaluateAsConst(expr->getArg(2));
+    if (offset)
+      constOffset = offset;
+    else
+      varOffset = offset;
+  } else {
+    // Four offset parameters
+    const auto offset0 = tryToEvaluateAsConst(expr->getArg(2));
+    const auto offset1 = tryToEvaluateAsConst(expr->getArg(3));
+    const auto offset2 = tryToEvaluateAsConst(expr->getArg(4));
+    const auto offset3 = tryToEvaluateAsConst(expr->getArg(5));
+
+    // Make sure we can generate the ConstOffsets image operands in SPIR-V.
+    if (!offset0 || !offset1 || !offset2 || !offset3) {
+      emitError("all offset parameters to '%0' method call must be constants",
+                expr->getExprLoc())
+          << callee->getName() << expr->getSourceRange();
+      return 0;
+    }
+    const uint32_t v2i32 = theBuilder.getVecType(theBuilder.getInt32Type(), 2);
+    const uint32_t offsetType =
+        theBuilder.getArrayType(v2i32, theBuilder.getConstantUint32(4));
+    constOffsets = theBuilder.getConstantComposite(
+        offsetType, {offset0, offset1, offset2, offset3});
+  }
+
+  const auto retType = typeTranslator.translateType(callee->getReturnType());
+  const auto imageType = typeTranslator.translateType(imageExpr->getType());
+
+  return theBuilder.createImageGather(
+      retType, imageType, image, sampler, coordinate,
+      theBuilder.getConstantInt32(component), constOffset, varOffset,
+      constOffsets, /*sampleNumber=*/0);
+}
+
 uint32_t SPIRVEmitter::processBufferTextureLoad(const Expr *object,
 uint32_t SPIRVEmitter::processBufferTextureLoad(const Expr *object,
                                                 const uint32_t locationId,
                                                 const uint32_t locationId,
                                                 uint32_t constOffset,
                                                 uint32_t constOffset,
@@ -2008,6 +2072,14 @@ SPIRVEmitter::processIntrinsicMemberCall(const CXXMemberCallExpr *expr,
           /*constOffsets*/ 0, /*sampleNumber*/ 0);
           /*constOffsets*/ 0, /*sampleNumber*/ 0);
     }
     }
   }
   }
+  case IntrinsicOp::MOP_GatherRed:
+    return processTextureGatherRGBA(expr, 0);
+  case IntrinsicOp::MOP_GatherGreen:
+    return processTextureGatherRGBA(expr, 1);
+  case IntrinsicOp::MOP_GatherBlue:
+    return processTextureGatherRGBA(expr, 2);
+  case IntrinsicOp::MOP_GatherAlpha:
+    return processTextureGatherRGBA(expr, 3);
   case IntrinsicOp::MOP_SampleBias:
   case IntrinsicOp::MOP_SampleBias:
   case IntrinsicOp::MOP_SampleLevel: {
   case IntrinsicOp::MOP_SampleLevel: {
     // Signatures:
     // Signatures:

+ 8 - 2
tools/clang/lib/SPIRV/SPIRVEmitter.h

@@ -495,6 +495,10 @@ private:
   /// the given texture. Handles intrinsic HLSL CalculateLevelOfDetail function.
   /// the given texture. Handles intrinsic HLSL CalculateLevelOfDetail function.
   uint32_t processTextureLevelOfDetail(const CXXMemberCallExpr *expr);
   uint32_t processTextureLevelOfDetail(const CXXMemberCallExpr *expr);
 
 
+  /// \brief Handles .Gather{Red|Green|Blue|Alpha}() calls on texture types.
+  uint32_t processTextureGatherRGBA(const CXXMemberCallExpr *expr,
+                                    uint32_t component);
+
   /// \brief Queries the given (RW)Buffer/(RW)Texture image in the given expr
   /// \brief Queries the given (RW)Buffer/(RW)Texture image in the given expr
   /// for the requested information. Based on the dimension of the image, the
   /// for the requested information. Based on the dimension of the image, the
   /// following info can be queried: width, height, depth, number of mipmap
   /// following info can be queried: width, height, depth, number of mipmap
@@ -523,10 +527,12 @@ private:
 
 
   /// \brief Wrapper method to create an error message and report it
   /// \brief Wrapper method to create an error message and report it
   /// in the diagnostic engine associated with this consumer.
   /// in the diagnostic engine associated with this consumer.
-  template <unsigned N> DiagnosticBuilder emitError(const char (&message)[N]) {
+  template <unsigned N>
+  DiagnosticBuilder emitError(const char (&message)[N],
+                              SourceLocation loc = {}) {
     const auto diagId =
     const auto diagId =
         diags.getCustomDiagID(clang::DiagnosticsEngine::Error, message);
         diags.getCustomDiagID(clang::DiagnosticsEngine::Error, message);
-    return diags.Report(diagId);
+    return diags.Report(loc, diagId);
   }
   }
 
 
   /// \brief Wrapper method to create a warning message and report it
   /// \brief Wrapper method to create a warning message and report it

+ 48 - 0
tools/clang/test/CodeGenSPIRV/texture.array.gather-alpha.hlsl

@@ -0,0 +1,48 @@
+// Run: %dxc -T ps_6_0 -E main
+
+SamplerState gSampler : register(s1);
+
+Texture2DArray<float4> t2f4 : register(t1);
+Texture2DArray<uint4>  t2u4 : register(t2);
+// .GatherAlpha() does not support Texture1DArray.
+// .GatherAlpha() for TextureCubeArray only has one signature that takes the status parameter.
+
+// CHECK: [[c12:%\d+]] = OpConstantComposite %v2int %int_1 %int_2
+// CHECK: [[c34:%\d+]] = OpConstantComposite %v2int %int_3 %int_4
+// CHECK: [[c56:%\d+]] = OpConstantComposite %v2int %int_5 %int_6
+// CHECK: [[c78:%\d+]] = OpConstantComposite %v2int %int_7 %int_8
+// CHECK: [[c1to8:%\d+]] = OpConstantComposite %_arr_v2int_uint_4 [[c12]] [[c34]] [[c56]] [[c78]]
+
+float4 main(float3 location: A) : SV_Target {
+// CHECK:            [[t2f4:%\d+]] = OpLoad %type_2d_image_array %t2f4
+// CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
+// CHECK-NEXT:        [[loc:%\d+]] = OpLoad %v3float %location
+// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image [[t2f4]] [[gSampler]]
+// CHECK-NEXT:        [[res:%\d+]] = OpImageGather %v4float [[sampledImg]] [[loc]] %int_3 ConstOffset [[c12]]
+// CHECK-NEXT:                       OpStore %a [[res]]
+    float4 a = t2f4.GatherAlpha(gSampler, location, int2(1, 2));
+// CHECK:            [[t2f4:%\d+]] = OpLoad %type_2d_image_array %t2f4
+// CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
+// CHECK-NEXT:        [[loc:%\d+]] = OpLoad %v3float %location
+// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image [[t2f4]] [[gSampler]]
+// CHECK-NEXT:        [[res:%\d+]] = OpImageGather %v4float [[sampledImg]] [[loc]] %int_3 ConstOffsets [[c1to8]]
+// CHECK-NEXT:                       OpStore %b [[res]]
+    float4 b = t2f4.GatherAlpha(gSampler, location, int2(1, 2), int2(3, 4), int2(5, 6), int2(7, 8));
+
+// CHECK:            [[t2u4:%\d+]] = OpLoad %type_2d_image_array_0 %t2u4
+// CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
+// CHECK-NEXT:        [[loc:%\d+]] = OpLoad %v3float %location
+// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2u4]] [[gSampler]]
+// CHECK-NEXT:        [[res:%\d+]] = OpImageGather %v4uint [[sampledImg]] [[loc]] %int_3 ConstOffset [[c12]]
+// CHECK-NEXT:                       OpStore %c [[res]]
+    uint4 c = t2u4.GatherAlpha(gSampler, location, int2(1, 2));
+// CHECK:            [[t2u4:%\d+]] = OpLoad %type_2d_image_array_0 %t2u4
+// CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
+// CHECK-NEXT:        [[loc:%\d+]] = OpLoad %v3float %location
+// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2u4]] [[gSampler]]
+// CHECK-NEXT:        [[res:%\d+]] = OpImageGather %v4uint [[sampledImg]] [[loc]] %int_3 ConstOffsets [[c1to8]]
+// CHECK-NEXT:                       OpStore %d [[res]]
+    uint4 d = t2u4.GatherAlpha(gSampler, location, int2(1, 2), int2(3, 4), int2(5, 6), int2(7, 8));
+
+    return 1.0;
+}

+ 48 - 0
tools/clang/test/CodeGenSPIRV/texture.array.gather-blue.hlsl

@@ -0,0 +1,48 @@
+// Run: %dxc -T ps_6_0 -E main
+
+SamplerState gSampler : register(s1);
+
+Texture2DArray<float4> t2f4 : register(t1);
+Texture2DArray<int3>   t2i3 : register(t2);
+// .GatherBlue() does not support Texture1DArray.
+// .GatherBlue() for TextureCubeArray only has one signature that takes the status parameter.
+
+// CHECK: [[c12:%\d+]] = OpConstantComposite %v2int %int_1 %int_2
+// CHECK: [[c34:%\d+]] = OpConstantComposite %v2int %int_3 %int_4
+// CHECK: [[c56:%\d+]] = OpConstantComposite %v2int %int_5 %int_6
+// CHECK: [[c78:%\d+]] = OpConstantComposite %v2int %int_7 %int_8
+// CHECK: [[c1to8:%\d+]] = OpConstantComposite %_arr_v2int_uint_4 [[c12]] [[c34]] [[c56]] [[c78]]
+
+float4 main(float3 location: A) : SV_Target {
+// CHECK:            [[t2f4:%\d+]] = OpLoad %type_2d_image_array %t2f4
+// CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
+// CHECK-NEXT:        [[loc:%\d+]] = OpLoad %v3float %location
+// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image [[t2f4]] [[gSampler]]
+// CHECK-NEXT:        [[res:%\d+]] = OpImageGather %v4float [[sampledImg]] [[loc]] %int_2 ConstOffset [[c12]]
+// CHECK-NEXT:                       OpStore %a [[res]]
+    float4 a = t2f4.GatherBlue(gSampler, location, int2(1, 2));
+// CHECK:            [[t2f4:%\d+]] = OpLoad %type_2d_image_array %t2f4
+// CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
+// CHECK-NEXT:        [[loc:%\d+]] = OpLoad %v3float %location
+// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image [[t2f4]] [[gSampler]]
+// CHECK-NEXT:        [[res:%\d+]] = OpImageGather %v4float [[sampledImg]] [[loc]] %int_2 ConstOffsets [[c1to8]]
+// CHECK-NEXT:                       OpStore %b [[res]]
+    float4 b = t2f4.GatherBlue(gSampler, location, int2(1, 2), int2(3, 4), int2(5, 6), int2(7, 8));
+
+// CHECK:            [[t2i3:%\d+]] = OpLoad %type_2d_image_array_0 %t2i3
+// CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
+// CHECK-NEXT:        [[loc:%\d+]] = OpLoad %v3float %location
+// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2i3]] [[gSampler]]
+// CHECK-NEXT:        [[res:%\d+]] = OpImageGather %v4int [[sampledImg]] [[loc]] %int_2 ConstOffset [[c12]]
+// CHECK-NEXT:                       OpStore %c [[res]]
+    int4 c = t2i3.GatherBlue(gSampler, location, int2(1, 2));
+// CHECK:            [[t2i3:%\d+]] = OpLoad %type_2d_image_array_0 %t2i3
+// CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
+// CHECK-NEXT:        [[loc:%\d+]] = OpLoad %v3float %location
+// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2i3]] [[gSampler]]
+// CHECK-NEXT:        [[res:%\d+]] = OpImageGather %v4int [[sampledImg]] [[loc]] %int_2 ConstOffsets [[c1to8]]
+// CHECK-NEXT:                       OpStore %d [[res]]
+    int4 d = t2i3.GatherBlue(gSampler, location, int2(1, 2), int2(3, 4), int2(5, 6), int2(7, 8));
+
+    return 1.0;
+}

+ 48 - 0
tools/clang/test/CodeGenSPIRV/texture.array.gather-green.hlsl

@@ -0,0 +1,48 @@
+// Run: %dxc -T ps_6_0 -E main
+
+SamplerState gSampler : register(s1);
+
+Texture2DArray<float4> t2f4 : register(t1);
+Texture2DArray<uint2>  t2u2 : register(t2);
+// .GatherGreen() does not support Texture1DArray.
+// .GatherGreen() for TextureCubeArray only has one signature that takes the status parameter.
+
+// CHECK: [[c12:%\d+]] = OpConstantComposite %v2int %int_1 %int_2
+// CHECK: [[c34:%\d+]] = OpConstantComposite %v2int %int_3 %int_4
+// CHECK: [[c56:%\d+]] = OpConstantComposite %v2int %int_5 %int_6
+// CHECK: [[c78:%\d+]] = OpConstantComposite %v2int %int_7 %int_8
+// CHECK: [[c1to8:%\d+]] = OpConstantComposite %_arr_v2int_uint_4 [[c12]] [[c34]] [[c56]] [[c78]]
+
+float4 main(float3 location: A) : SV_Target {
+// CHECK:            [[t2f4:%\d+]] = OpLoad %type_2d_image_array %t2f4
+// CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
+// CHECK-NEXT:        [[loc:%\d+]] = OpLoad %v3float %location
+// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image [[t2f4]] [[gSampler]]
+// CHECK-NEXT:        [[res:%\d+]] = OpImageGather %v4float [[sampledImg]] [[loc]] %int_1 ConstOffset [[c12]]
+// CHECK-NEXT:                       OpStore %a [[res]]
+    float4 a = t2f4.GatherGreen(gSampler, location, int2(1, 2));
+// CHECK:            [[t2f4:%\d+]] = OpLoad %type_2d_image_array %t2f4
+// CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
+// CHECK-NEXT:        [[loc:%\d+]] = OpLoad %v3float %location
+// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image [[t2f4]] [[gSampler]]
+// CHECK-NEXT:        [[res:%\d+]] = OpImageGather %v4float [[sampledImg]] [[loc]] %int_1 ConstOffsets [[c1to8]]
+// CHECK-NEXT:                       OpStore %b [[res]]
+    float4 b = t2f4.GatherGreen(gSampler, location, int2(1, 2), int2(3, 4), int2(5, 6), int2(7, 8));
+
+// CHECK:            [[t2u2:%\d+]] = OpLoad %type_2d_image_array_0 %t2u2
+// CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
+// CHECK-NEXT:        [[loc:%\d+]] = OpLoad %v3float %location
+// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2u2]] [[gSampler]]
+// CHECK-NEXT:        [[res:%\d+]] = OpImageGather %v4uint [[sampledImg]] [[loc]] %int_1 ConstOffset [[c12]]
+// CHECK-NEXT:                       OpStore %c [[res]]
+    uint4 c = t2u2.GatherGreen(gSampler, location, int2(1, 2));
+// CHECK:            [[t2u2:%\d+]] = OpLoad %type_2d_image_array_0 %t2u2
+// CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
+// CHECK-NEXT:        [[loc:%\d+]] = OpLoad %v3float %location
+// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2u2]] [[gSampler]]
+// CHECK-NEXT:        [[res:%\d+]] = OpImageGather %v4uint [[sampledImg]] [[loc]] %int_1 ConstOffsets [[c1to8]]
+// CHECK-NEXT:                       OpStore %d [[res]]
+    uint4 d = t2u2.GatherGreen(gSampler, location, int2(1, 2), int2(3, 4), int2(5, 6), int2(7, 8));
+
+    return 1.0;
+}

+ 48 - 0
tools/clang/test/CodeGenSPIRV/texture.array.gather-red.hlsl

@@ -0,0 +1,48 @@
+// Run: %dxc -T ps_6_0 -E main
+
+SamplerState gSampler : register(s1);
+
+Texture2DArray<float4> t2f4 : register(t1);
+Texture2DArray<uint>   t2u1 : register(t2);
+// .GatherRed() does not support Texture1DArray.
+// .GatherRed() for TextureCubeArray only has one signature that takes the status parameter.
+
+// CHECK: [[c12:%\d+]] = OpConstantComposite %v2int %int_1 %int_2
+// CHECK: [[c34:%\d+]] = OpConstantComposite %v2int %int_3 %int_4
+// CHECK: [[c56:%\d+]] = OpConstantComposite %v2int %int_5 %int_6
+// CHECK: [[c78:%\d+]] = OpConstantComposite %v2int %int_7 %int_8
+// CHECK: [[c1to8:%\d+]] = OpConstantComposite %_arr_v2int_uint_4 [[c12]] [[c34]] [[c56]] [[c78]]
+
+float4 main(float3 location: A) : SV_Target {
+// CHECK:            [[t2f4:%\d+]] = OpLoad %type_2d_image_array %t2f4
+// CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
+// CHECK-NEXT:        [[loc:%\d+]] = OpLoad %v3float %location
+// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image [[t2f4]] [[gSampler]]
+// CHECK-NEXT:        [[res:%\d+]] = OpImageGather %v4float [[sampledImg]] [[loc]] %int_0 ConstOffset [[c12]]
+// CHECK-NEXT:                       OpStore %a [[res]]
+    float4 a = t2f4.GatherRed(gSampler, location, int2(1, 2));
+// CHECK:            [[t2f4:%\d+]] = OpLoad %type_2d_image_array %t2f4
+// CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
+// CHECK-NEXT:        [[loc:%\d+]] = OpLoad %v3float %location
+// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image [[t2f4]] [[gSampler]]
+// CHECK-NEXT:        [[res:%\d+]] = OpImageGather %v4float [[sampledImg]] [[loc]] %int_0 ConstOffsets [[c1to8]]
+// CHECK-NEXT:                       OpStore %b [[res]]
+    float4 b = t2f4.GatherRed(gSampler, location, int2(1, 2), int2(3, 4), int2(5, 6), int2(7, 8));
+
+// CHECK:            [[t2u1:%\d+]] = OpLoad %type_2d_image_array_0 %t2u1
+// CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
+// CHECK-NEXT:        [[loc:%\d+]] = OpLoad %v3float %location
+// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2u1]] [[gSampler]]
+// CHECK-NEXT:        [[res:%\d+]] = OpImageGather %v4uint [[sampledImg]] [[loc]] %int_0 ConstOffset [[c12]]
+// CHECK-NEXT:                       OpStore %c [[res]]
+    uint4 c = t2u1.GatherRed(gSampler, location, int2(1, 2));
+// CHECK:            [[t2u1:%\d+]] = OpLoad %type_2d_image_array_0 %t2u1
+// CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
+// CHECK-NEXT:        [[loc:%\d+]] = OpLoad %v3float %location
+// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2u1]] [[gSampler]]
+// CHECK-NEXT:        [[res:%\d+]] = OpImageGather %v4uint [[sampledImg]] [[loc]] %int_0 ConstOffsets [[c1to8]]
+// CHECK-NEXT:                       OpStore %d [[res]]
+    uint4 d = t2u1.GatherRed(gSampler, location, int2(1, 2), int2(3, 4), int2(5, 6), int2(7, 8));
+
+    return 1.0;
+}

+ 18 - 2
tools/clang/test/CodeGenSPIRV/texture.array.gather.hlsl

@@ -3,7 +3,9 @@
 SamplerState gSampler : register(s1);
 SamplerState gSampler : register(s1);
 
 
 Texture2DArray   <float4> t2 : register(t2);
 Texture2DArray   <float4> t2 : register(t2);
-TextureCubeArray <float4> t4 : register(t4);
+TextureCubeArray <uint3>  t4 : register(t4);
+Texture2DArray   <int3>   t6 : register(t6);
+TextureCubeArray <float>  t8 : register(t8);
 // .Gather() does not support Texture1DArray.
 // .Gather() does not support Texture1DArray.
 
 
 // CHECK: OpCapability ImageGatherExtended
 // CHECK: OpCapability ImageGatherExtended
@@ -23,8 +25,22 @@ float4 main(float3 location: A, int2 offset: B) : SV_Target {
 // CHECK:              [[t4:%\d+]] = OpLoad %type_cube_image_array %t4
 // CHECK:              [[t4:%\d+]] = OpLoad %type_cube_image_array %t4
 // CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
 // CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
 // CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t4]] [[gSampler]]
 // CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t4]] [[gSampler]]
+// CHECK-NEXT:            {{%\d+}} = OpImageGather %v4uint [[sampledImg]] [[v4fc]] %int_0
+    uint4 val4 = t4.Gather(gSampler, float4(0.1, 0.2, 0.3, 0.4));
+
+// CHECK:              [[t6:%\d+]] = OpLoad %type_2d_image_array_0 %t6
+// CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
+// CHECK-NEXT:        [[loc:%\d+]] = OpLoad %v3float %location
+// CHECK-NEXT:     [[offset:%\d+]] = OpLoad %v2int %offset
+// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_1 [[t6]] [[gSampler]]
+// CHECK-NEXT:            {{%\d+}} = OpImageGather %v4int [[sampledImg]] [[loc]] %int_0 Offset [[offset]]
+    int4 val6 = t6.Gather(gSampler, location, offset);
+
+// CHECK:              [[t8:%\d+]] = OpLoad %type_cube_image_array_0 %t8
+// CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
+// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_2 [[t8]] [[gSampler]]
 // CHECK-NEXT:            {{%\d+}} = OpImageGather %v4float [[sampledImg]] [[v4fc]] %int_0
 // CHECK-NEXT:            {{%\d+}} = OpImageGather %v4float [[sampledImg]] [[v4fc]] %int_0
-    float4 val4 = t4.Gather(gSampler, float4(0.1, 0.2, 0.3, 0.4));
+    float4 val8 = t8.Gather(gSampler, float4(0.1, 0.2, 0.3, 0.4));
 
 
     return 1.0;
     return 1.0;
 }
 }

+ 49 - 0
tools/clang/test/CodeGenSPIRV/texture.gather-alpha.hlsl

@@ -0,0 +1,49 @@
+// Run: %dxc -T ps_6_0 -E main
+
+SamplerState gSampler : register(s1);
+
+Texture2D<float4> t2f4 : register(t1);
+Texture2D<int4>   t2i4 : register(t2);
+// .GatherAlpha() does not support Texture1D and Texture3D.
+// .GatherAlpha() for TextureCube only has one signature that takes the status parameter.
+
+// CHECK: [[c12:%\d+]] = OpConstantComposite %v2int %int_1 %int_2
+// CHECK: [[c34:%\d+]] = OpConstantComposite %v2int %int_3 %int_4
+// CHECK: [[c56:%\d+]] = OpConstantComposite %v2int %int_5 %int_6
+// CHECK: [[c78:%\d+]] = OpConstantComposite %v2int %int_7 %int_8
+// CHECK: [[c1to8:%\d+]] = OpConstantComposite %_arr_v2int_uint_4 [[c12]] [[c34]] [[c56]] [[c78]]
+
+float4 main(float2 location: A) : SV_Target {
+// CHECK:            [[t2f4:%\d+]] = OpLoad %type_2d_image %t2f4
+// CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
+// CHECK-NEXT:        [[loc:%\d+]] = OpLoad %v2float %location
+// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image [[t2f4]] [[gSampler]]
+// CHECK-NEXT:        [[res:%\d+]] = OpImageGather %v4float [[sampledImg]] [[loc]] %int_3 ConstOffset [[c12]]
+// CHECK-NEXT:                       OpStore %a [[res]]
+    float4 a = t2f4.GatherAlpha(gSampler, location, int2(1, 2));
+// CHECK:            [[t2f4:%\d+]] = OpLoad %type_2d_image %t2f4
+// CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
+// CHECK-NEXT:        [[loc:%\d+]] = OpLoad %v2float %location
+// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image [[t2f4]] [[gSampler]]
+// CHECK-NEXT:        [[res:%\d+]] = OpImageGather %v4float [[sampledImg]] [[loc]] %int_3 ConstOffsets [[c1to8]]
+// CHECK-NEXT:                       OpStore %b [[res]]
+    float4 b = t2f4.GatherAlpha(gSampler, location, int2(1, 2), int2(3, 4), int2(5, 6), int2(7, 8));
+
+// CHECK:            [[t2i4:%\d+]] = OpLoad %type_2d_image_0 %t2i4
+// CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
+// CHECK-NEXT:        [[loc:%\d+]] = OpLoad %v2float %location
+// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2i4]] [[gSampler]]
+// CHECK-NEXT:        [[res:%\d+]] = OpImageGather %v4int [[sampledImg]] [[loc]] %int_3 ConstOffset [[c12]]
+// CHECK-NEXT:                       OpStore %c [[res]]
+    int4 c = t2i4.GatherAlpha(gSampler, location, int2(1, 2));
+// CHECK:            [[t2i4:%\d+]] = OpLoad %type_2d_image_0 %t2i4
+// CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
+// CHECK-NEXT:        [[loc:%\d+]] = OpLoad %v2float %location
+// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2i4]] [[gSampler]]
+// CHECK-NEXT:        [[res:%\d+]] = OpImageGather %v4int [[sampledImg]] [[loc]] %int_3 ConstOffsets [[c1to8]]
+// CHECK-NEXT:                       OpStore %d [[res]]
+    int4 d = t2i4.GatherAlpha(gSampler, location, int2(1, 2), int2(3, 4), int2(5, 6), int2(7, 8));
+
+    return 1.0;
+}
+

+ 49 - 0
tools/clang/test/CodeGenSPIRV/texture.gather-blue.hlsl

@@ -0,0 +1,49 @@
+// Run: %dxc -T ps_6_0 -E main
+
+SamplerState gSampler : register(s1);
+
+Texture2D<float4> t2f4 : register(t1);
+Texture2D<uint3>  t2u3 : register(t2);
+// .GatherBlue() does not support Texture1D and Texture3D.
+// .GatherBlue() for TextureCube only has one signature that takes the status parameter.
+
+// CHECK: [[c12:%\d+]] = OpConstantComposite %v2int %int_1 %int_2
+// CHECK: [[c34:%\d+]] = OpConstantComposite %v2int %int_3 %int_4
+// CHECK: [[c56:%\d+]] = OpConstantComposite %v2int %int_5 %int_6
+// CHECK: [[c78:%\d+]] = OpConstantComposite %v2int %int_7 %int_8
+// CHECK: [[c1to8:%\d+]] = OpConstantComposite %_arr_v2int_uint_4 [[c12]] [[c34]] [[c56]] [[c78]]
+
+float4 main(float2 location: A) : SV_Target {
+// CHECK:            [[t2f4:%\d+]] = OpLoad %type_2d_image %t2f4
+// CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
+// CHECK-NEXT:        [[loc:%\d+]] = OpLoad %v2float %location
+// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image [[t2f4]] [[gSampler]]
+// CHECK-NEXT:        [[res:%\d+]] = OpImageGather %v4float [[sampledImg]] [[loc]] %int_2 ConstOffset [[c12]]
+// CHECK-NEXT:                       OpStore %a [[res]]
+    float4 a = t2f4.GatherBlue(gSampler, location, int2(1, 2));
+// CHECK:            [[t2f4:%\d+]] = OpLoad %type_2d_image %t2f4
+// CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
+// CHECK-NEXT:        [[loc:%\d+]] = OpLoad %v2float %location
+// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image [[t2f4]] [[gSampler]]
+// CHECK-NEXT:        [[res:%\d+]] = OpImageGather %v4float [[sampledImg]] [[loc]] %int_2 ConstOffsets [[c1to8]]
+// CHECK-NEXT:                       OpStore %b [[res]]
+    float4 b = t2f4.GatherBlue(gSampler, location, int2(1, 2), int2(3, 4), int2(5, 6), int2(7, 8));
+
+// CHECK:            [[t2u3:%\d+]] = OpLoad %type_2d_image_0 %t2u3
+// CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
+// CHECK-NEXT:        [[loc:%\d+]] = OpLoad %v2float %location
+// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2u3]] [[gSampler]]
+// CHECK-NEXT:        [[res:%\d+]] = OpImageGather %v4uint [[sampledImg]] [[loc]] %int_2 ConstOffset [[c12]]
+// CHECK-NEXT:                       OpStore %c [[res]]
+    uint4 c = t2u3.GatherBlue(gSampler, location, int2(1, 2));
+// CHECK:            [[t2u3:%\d+]] = OpLoad %type_2d_image_0 %t2u3
+// CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
+// CHECK-NEXT:        [[loc:%\d+]] = OpLoad %v2float %location
+// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2u3]] [[gSampler]]
+// CHECK-NEXT:        [[res:%\d+]] = OpImageGather %v4uint [[sampledImg]] [[loc]] %int_2 ConstOffsets [[c1to8]]
+// CHECK-NEXT:                       OpStore %d [[res]]
+    uint4 d = t2u3.GatherBlue(gSampler, location, int2(1, 2), int2(3, 4), int2(5, 6), int2(7, 8));
+
+    return 1.0;
+}
+

+ 49 - 0
tools/clang/test/CodeGenSPIRV/texture.gather-green.hlsl

@@ -0,0 +1,49 @@
+// Run: %dxc -T ps_6_0 -E main
+
+SamplerState gSampler : register(s1);
+
+Texture2D<float4> t2f4 : register(t1);
+Texture2D<uint2>  t2u2 : register(t2);
+// .GatherGreen() does not support Texture1D and Texture3D.
+// .GatherGreen() for TextureCube only has one signature that takes the status parameter.
+
+// CHECK: [[c12:%\d+]] = OpConstantComposite %v2int %int_1 %int_2
+// CHECK: [[c34:%\d+]] = OpConstantComposite %v2int %int_3 %int_4
+// CHECK: [[c56:%\d+]] = OpConstantComposite %v2int %int_5 %int_6
+// CHECK: [[c78:%\d+]] = OpConstantComposite %v2int %int_7 %int_8
+// CHECK: [[c1to8:%\d+]] = OpConstantComposite %_arr_v2int_uint_4 [[c12]] [[c34]] [[c56]] [[c78]]
+
+float4 main(float2 location: A) : SV_Target {
+// CHECK:            [[t2f4:%\d+]] = OpLoad %type_2d_image %t2f4
+// CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
+// CHECK-NEXT:        [[loc:%\d+]] = OpLoad %v2float %location
+// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image [[t2f4]] [[gSampler]]
+// CHECK-NEXT:        [[res:%\d+]] = OpImageGather %v4float [[sampledImg]] [[loc]] %int_1 ConstOffset [[c12]]
+// CHECK-NEXT:                       OpStore %a [[res]]
+    float4 a = t2f4.GatherGreen(gSampler, location, int2(1, 2));
+// CHECK:            [[t2f4:%\d+]] = OpLoad %type_2d_image %t2f4
+// CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
+// CHECK-NEXT:        [[loc:%\d+]] = OpLoad %v2float %location
+// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image [[t2f4]] [[gSampler]]
+// CHECK-NEXT:        [[res:%\d+]] = OpImageGather %v4float [[sampledImg]] [[loc]] %int_1 ConstOffsets [[c1to8]]
+// CHECK-NEXT:                       OpStore %b [[res]]
+    float4 b = t2f4.GatherGreen(gSampler, location, int2(1, 2), int2(3, 4), int2(5, 6), int2(7, 8));
+
+// CHECK:            [[t2u2:%\d+]] = OpLoad %type_2d_image_0 %t2u2
+// CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
+// CHECK-NEXT:        [[loc:%\d+]] = OpLoad %v2float %location
+// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2u2]] [[gSampler]]
+// CHECK-NEXT:        [[res:%\d+]] = OpImageGather %v4uint [[sampledImg]] [[loc]] %int_1 ConstOffset [[c12]]
+// CHECK-NEXT:                       OpStore %c [[res]]
+    uint4 c = t2u2.GatherGreen(gSampler, location, int2(1, 2));
+// CHECK:            [[t2u2:%\d+]] = OpLoad %type_2d_image_0 %t2u2
+// CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
+// CHECK-NEXT:        [[loc:%\d+]] = OpLoad %v2float %location
+// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2u2]] [[gSampler]]
+// CHECK-NEXT:        [[res:%\d+]] = OpImageGather %v4uint [[sampledImg]] [[loc]] %int_1 ConstOffsets [[c1to8]]
+// CHECK-NEXT:                       OpStore %d [[res]]
+    uint4 d = t2u2.GatherGreen(gSampler, location, int2(1, 2), int2(3, 4), int2(5, 6), int2(7, 8));
+
+    return 1.0;
+}
+

+ 48 - 0
tools/clang/test/CodeGenSPIRV/texture.gather-red.hlsl

@@ -0,0 +1,48 @@
+// Run: %dxc -T ps_6_0 -E main
+
+SamplerState gSampler : register(s1);
+
+Texture2D<float4> t2f4 : register(t1);
+Texture2D<uint>   t2u1 : register(t2);
+// .GatherRed() does not support Texture1D and Texture3D.
+// .GatherRed() for TextureCube only has one signature that takes the status parameter.
+
+// CHECK: [[c12:%\d+]] = OpConstantComposite %v2int %int_1 %int_2
+// CHECK: [[c34:%\d+]] = OpConstantComposite %v2int %int_3 %int_4
+// CHECK: [[c56:%\d+]] = OpConstantComposite %v2int %int_5 %int_6
+// CHECK: [[c78:%\d+]] = OpConstantComposite %v2int %int_7 %int_8
+// CHECK: [[c1to8:%\d+]] = OpConstantComposite %_arr_v2int_uint_4 [[c12]] [[c34]] [[c56]] [[c78]]
+
+float4 main(float2 location: A) : SV_Target {
+// CHECK:            [[t2f4:%\d+]] = OpLoad %type_2d_image %t2f4
+// CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
+// CHECK-NEXT:        [[loc:%\d+]] = OpLoad %v2float %location
+// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image [[t2f4]] [[gSampler]]
+// CHECK-NEXT:        [[res:%\d+]] = OpImageGather %v4float [[sampledImg]] [[loc]] %int_0 ConstOffset [[c12]]
+// CHECK-NEXT:                       OpStore %a [[res]]
+    float4 a = t2f4.GatherRed(gSampler, location, int2(1, 2));
+// CHECK:            [[t2f4:%\d+]] = OpLoad %type_2d_image %t2f4
+// CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
+// CHECK-NEXT:        [[loc:%\d+]] = OpLoad %v2float %location
+// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image [[t2f4]] [[gSampler]]
+// CHECK-NEXT:        [[res:%\d+]] = OpImageGather %v4float [[sampledImg]] [[loc]] %int_0 ConstOffsets [[c1to8]]
+// CHECK-NEXT:                       OpStore %b [[res]]
+    float4 b = t2f4.GatherRed(gSampler, location, int2(1, 2), int2(3, 4), int2(5, 6), int2(7, 8));
+
+// CHECK:            [[t2u1:%\d+]] = OpLoad %type_2d_image_0 %t2u1
+// CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
+// CHECK-NEXT:        [[loc:%\d+]] = OpLoad %v2float %location
+// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2u1]] [[gSampler]]
+// CHECK-NEXT:        [[res:%\d+]] = OpImageGather %v4uint [[sampledImg]] [[loc]] %int_0 ConstOffset [[c12]]
+// CHECK-NEXT:                       OpStore %c [[res]]
+    uint4 c = t2u1.GatherRed(gSampler, location, int2(1, 2));
+// CHECK:            [[t2u1:%\d+]] = OpLoad %type_2d_image_0 %t2u1
+// CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
+// CHECK-NEXT:        [[loc:%\d+]] = OpLoad %v2float %location
+// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2u1]] [[gSampler]]
+// CHECK-NEXT:        [[res:%\d+]] = OpImageGather %v4uint [[sampledImg]] [[loc]] %int_0 ConstOffsets [[c1to8]]
+// CHECK-NEXT:                       OpStore %d [[res]]
+    uint4 d = t2u1.GatherRed(gSampler, location, int2(1, 2), int2(3, 4), int2(5, 6), int2(7, 8));
+
+    return 1.0;
+}

+ 17 - 2
tools/clang/test/CodeGenSPIRV/texture.gather.hlsl

@@ -3,7 +3,9 @@
 SamplerState gSampler : register(s1);
 SamplerState gSampler : register(s1);
 
 
 Texture2D   <float4> t2 : register(t2);
 Texture2D   <float4> t2 : register(t2);
-TextureCube <float4> t4 : register(t4);
+TextureCube <uint3>  t4 : register(t4);
+Texture2D   <int2>   t6 : register(t6);
+TextureCube <float>  t8 : register(t8);
 // .Gather() does not support Texture1D and Texture3D.
 // .Gather() does not support Texture1D and Texture3D.
 
 
 // CHECK: [[v2ic:%\d+]] = OpConstantComposite %v2int %int_1 %int_2
 // CHECK: [[v2ic:%\d+]] = OpConstantComposite %v2int %int_1 %int_2
@@ -21,8 +23,21 @@ float4 main(float2 location: A) : SV_Target {
 // CHECK:              [[t4:%\d+]] = OpLoad %type_cube_image %t4
 // CHECK:              [[t4:%\d+]] = OpLoad %type_cube_image %t4
 // CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
 // CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
 // CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t4]] [[gSampler]]
 // CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t4]] [[gSampler]]
+// CHECK-NEXT:            {{%\d+}} = OpImageGather %v4uint [[sampledImg]] [[v3fc]] %int_0
+    uint4 val4 = t4.Gather(gSampler, float3(0.1, 0.2, 0.3));
+
+// CHECK:              [[t6:%\d+]] = OpLoad %type_2d_image_0 %t6
+// CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
+// CHECK-NEXT:        [[loc:%\d+]] = OpLoad %v2float %location
+// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_1 [[t6]] [[gSampler]]
+// CHECK-NEXT:            {{%\d+}} = OpImageGather %v4int [[sampledImg]] [[loc]] %int_0 ConstOffset [[v2ic]]
+    int4 val6 = t6.Gather(gSampler, location, int2(1, 2));
+
+// CHECK:              [[t8:%\d+]] = OpLoad %type_cube_image_0 %t8
+// CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
+// CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_2 [[t8]] [[gSampler]]
 // CHECK-NEXT:            {{%\d+}} = OpImageGather %v4float [[sampledImg]] [[v3fc]] %int_0
 // CHECK-NEXT:            {{%\d+}} = OpImageGather %v4float [[sampledImg]] [[v3fc]] %int_0
-    float4 val4 = t4.Gather(gSampler, float3(0.1, 0.2, 0.3));
+    float4 val8 = t8.Gather(gSampler, float3(0.1, 0.2, 0.3));
 
 
     return 1.0;
     return 1.0;
 }
 }

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

@@ -390,6 +390,26 @@ TEST_F(FileTest, TextureGather) { runFileTest("texture.gather.hlsl"); }
 TEST_F(FileTest, TextureArrayGather) {
 TEST_F(FileTest, TextureArrayGather) {
   runFileTest("texture.array.gather.hlsl");
   runFileTest("texture.array.gather.hlsl");
 }
 }
+TEST_F(FileTest, TextureGatherRed) { runFileTest("texture.gather-red.hlsl"); }
+TEST_F(FileTest, TextureArrayGatherRed) {
+  runFileTest("texture.array.gather-red.hlsl");
+}
+TEST_F(FileTest, TextureGatherGreen) {
+  runFileTest("texture.gather-green.hlsl");
+}
+TEST_F(FileTest, TextureArrayGatherGreen) {
+  runFileTest("texture.array.gather-green.hlsl");
+}
+TEST_F(FileTest, TextureGatherBlue) { runFileTest("texture.gather-blue.hlsl"); }
+TEST_F(FileTest, TextureArrayGatherBlue) {
+  runFileTest("texture.array.gather-blue.hlsl");
+}
+TEST_F(FileTest, TextureGatherAlpha) {
+  runFileTest("texture.gather-alpha.hlsl");
+}
+TEST_F(FileTest, TextureArrayGatherAlpha) {
+  runFileTest("texture.array.gather-alpha.hlsl");
+}
 TEST_F(FileTest, TextureSampleLevel) {
 TEST_F(FileTest, TextureSampleLevel) {
   runFileTest("texture.sample-level.hlsl");
   runFileTest("texture.sample-level.hlsl");
 }
 }