ソースを参照

[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
 addtional SPIR-V image operands ``ConstOffset`` or ``Offset`` on it.
 
+The overload with the status parameter are not supported.
+
 ``.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``
 or ``Offset`` on it.
 
+The overload with the status parameter are not supported.
+
 ``.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
 ``Grad``.
 
+The overload with the status parameter are not supported.
+
 ``.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
 operands ``Bias``.
 
-``.Gather(sampler, location[, offset])``
-++++++++++++++++++++++++++++++++++++++++
+The overload with the status parameter are not supported.
+
+``.Gather()``
++++++++++++++
 
 Available to ``Texture2D``, ``Texture2DArray``, ``TextureCube``, and
 ``TextureCubeArray``.
 
 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])``
 ++++++++++++++++++++++++++++++++++++++++++++
@@ -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
 the desired number of elements.
 
+The overload with the status parameter are not supported.
+
 ``operator[]``
 ++++++++++++++
 Handled similarly as ``.Load()``.

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

@@ -1691,6 +1691,70 @@ SPIRVEmitter::processTextureLevelOfDetail(const CXXMemberCallExpr *expr) {
                                            {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,
                                                 const uint32_t locationId,
                                                 uint32_t constOffset,
@@ -2008,6 +2072,14 @@ SPIRVEmitter::processIntrinsicMemberCall(const CXXMemberCallExpr *expr,
           /*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_SampleLevel: {
     // Signatures:

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

@@ -495,6 +495,10 @@ private:
   /// the given texture. Handles intrinsic HLSL CalculateLevelOfDetail function.
   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
   /// for the requested information. Based on the dimension of the image, the
   /// 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
   /// 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 =
         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

+ 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);
 
 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.
 
 // 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-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %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
-    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;
 }

+ 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);
 
 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.
 
 // 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-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %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
-    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;
 }

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

@@ -390,6 +390,26 @@ TEST_F(FileTest, TextureGather) { runFileTest("texture.gather.hlsl"); }
 TEST_F(FileTest, TextureArrayGather) {
   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) {
   runFileTest("texture.sample-level.hlsl");
 }