spirv-reader: convert arity of textureLoad on depth texture

Fixed: tint:439
Change-Id: I151e388a1ea11bdcb5cebf0441a73ddcaf8a6f54
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/37063
Commit-Queue: David Neto <dneto@google.com>
Auto-Submit: David Neto <dneto@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
diff --git a/src/reader/spirv/function.cc b/src/reader/spirv/function.cc
index 7ed54e2..fcfcc33 100644
--- a/src/reader/spirv/function.cc
+++ b/src/reader/spirv/function.cc
@@ -4073,15 +4073,17 @@
 
   std::string builtin_name;
   bool use_level_of_detail_suffix = true;
-  bool is_dref = false;
+  bool is_dref_sample = false;
+  bool is_non_dref_sample = false;
   switch (opcode) {
     case SpvOpImageSampleImplicitLod:
     case SpvOpImageSampleExplicitLod:
+      is_non_dref_sample = true;
       builtin_name = "textureSample";
       break;
     case SpvOpImageSampleDrefImplicitLod:
     case SpvOpImageSampleDrefExplicitLod:
-      is_dref = true;
+      is_dref_sample = true;
       builtin_name = "textureSampleCompare";
       if (arg_index < num_args) {
         params.push_back(MakeOperand(inst, arg_index).expr);
@@ -4138,7 +4140,7 @@
   }
   if (arg_index < num_args &&
       (image_operands_mask & SpvImageOperandsBiasMask)) {
-    if (is_dref) {
+    if (is_dref_sample) {
       return Fail() << "WGSL does not support depth-reference sampling with "
                        "level-of-detail bias: "
                     << inst.PrettyPrint();
@@ -4164,7 +4166,7 @@
   }
   if (arg_index + 1 < num_args &&
       (image_operands_mask & SpvImageOperandsGradMask)) {
-    if (is_dref) {
+    if (is_dref_sample) {
       return Fail() << "WGSL does not support depth-reference sampling with "
                        "explicit gradient: "
                     << inst.PrettyPrint();
@@ -4224,19 +4226,27 @@
       result_component_type = result_vector_type->type();
     }
 
-    // Convert the arity of the result when operating on depth textures.
-    // SPIR-V operations on depth textures always result in 4-element vectors.
-    // But WGSL operations on depth textures always result in a f32 scalar.
+    // For depth textures, the arity might mot match WGSL:
+    //  Operation           SPIR-V                     WGSL
+    //   normal sampling     vec4  ImplicitLod          f32
+    //   normal sampling     vec4  ExplicitLod          f32
+    //   compare sample      f32   DrefImplicitLod      f32
+    //   compare sample      f32   DrefExplicitLod      f32
+    //   texel load          vec4  ImageFetch           f32
+    //   normal gather       vec4  ImageGather          vec4 TODO(dneto)
+    //   dref gather         vec4  ImageFetch           vec4 TODO(dneto)
     // Construct a 4-element vector with the result from the builtin in the
     // first component.
     if (texture_type->Is<ast::type::DepthTexture>()) {
-      value = create<ast::TypeConstructorExpression>(
-          Source{},
-          result_type,  // a vec4
-          ast::ExpressionList{
-              value, parser_impl_.MakeNullValue(result_component_type),
-              parser_impl_.MakeNullValue(result_component_type),
-              parser_impl_.MakeNullValue(result_component_type)});
+      if (is_non_dref_sample || (opcode == SpvOpImageFetch)) {
+        value = create<ast::TypeConstructorExpression>(
+            Source{},
+            result_type,  // a vec4
+            ast::ExpressionList{
+                value, parser_impl_.MakeNullValue(result_component_type),
+                parser_impl_.MakeNullValue(result_component_type),
+                parser_impl_.MakeNullValue(result_component_type)});
+      }
     }
 
     // If necessary, convert the result to the signedness of the instruction
diff --git a/src/reader/spirv/parser_impl_handle_test.cc b/src/reader/spirv/parser_impl_handle_test.cc
index 619bfe3..5844e1b 100644
--- a/src/reader/spirv/parser_impl_handle_test.cc
+++ b/src/reader/spirv/parser_impl_handle_test.cc
@@ -927,13 +927,13 @@
                              "Usage(Texture( is_sampled ))"},
         // OpImageSampleDrefImplicitLod
         UsageImageAccessCase{"%result = OpImageSampleDrefImplicitLod "
-                             "%v4float %sampled_image %coords %depth",
+                             "%float %sampled_image %coords %depth",
                              "Usage(Sampler( comparison ))",
                              "Usage(Texture( is_sampled depth ))"},
         // OpImageSampleDrefExplicitLod
         UsageImageAccessCase{
             "%result = OpImageSampleDrefExplicitLod "
-            "%v4float %sampled_image %coords %depth Lod %float_null",
+            "%float %sampled_image %coords %depth Lod %float_null",
             "Usage(Sampler( comparison ))",
             "Usage(Texture( is_sampled depth ))"},
 
@@ -952,13 +952,13 @@
                              "Usage(Texture( is_sampled ))"},
         // OpImageSampleProjDrefImplicitLod
         UsageImageAccessCase{"%result = OpImageSampleProjDrefImplicitLod "
-                             "%v4float %sampled_image %coords %depth",
+                             "%float %sampled_image %coords %depth",
                              "Usage(Sampler( comparison ))",
                              "Usage(Texture( is_sampled depth ))"},
         // OpImageSampleProjDrefExplicitLod
         UsageImageAccessCase{
             "%result = OpImageSampleProjDrefExplicitLod "
-            "%v4float %sampled_image %coords %depth Lod %float_null",
+            "%float %sampled_image %coords %depth Lod %float_null",
             "Usage(Sampler( comparison ))",
             "Usage(Texture( is_sampled depth ))"},
 
@@ -1714,7 +1714,7 @@
      %sampled_dref_image = OpSampledImage %si_ty %im %sam_dref
 
      %200 = OpImageSampleImplicitLod %v4float %sampled_image %coords12
-     %210 = OpImageSampleDrefImplicitLod %v4float %sampled_dref_image %coords12 %depth
+     %210 = OpImageSampleDrefImplicitLod %float %sampled_dref_image %coords12 %depth
 )",
                         R"(
   Variable{
@@ -1772,22 +1772,16 @@
       VariableConst{
         x_210
         none
-        __vec_4__f32
+        __f32
         {
-          TypeConstructor[not set]{
-            __vec_4__f32
-            Call[not set]{
-              Identifier[not set]{textureSampleCompare}
-              (
-                Identifier[not set]{x_20}
-                Identifier[not set]{x_30}
-                Identifier[not set]{coords12}
-                ScalarConstructor[not set]{0.200000}
-              )
-            }
-            ScalarConstructor[not set]{0.000000}
-            ScalarConstructor[not set]{0.000000}
-            ScalarConstructor[not set]{0.000000}
+          Call[not set]{
+            Identifier[not set]{textureSampleCompare}
+            (
+              Identifier[not set]{x_20}
+              Identifier[not set]{x_30}
+              Identifier[not set]{coords12}
+              ScalarConstructor[not set]{0.200000}
+            )
           }
         }
       }
@@ -1800,7 +1794,7 @@
         // ImageSampleDrefImplicitLod
         ImageAccessCase{"%float 2D 0 0 0 1 Unknown",
                         "%result = OpImageSampleDrefImplicitLod "
-                        "%v4float %sampled_image %coords12 %depth",
+                        "%float %sampled_image %coords12 %depth",
                         R"(
   Variable{
     Decorations{
@@ -1821,25 +1815,19 @@
     __depth_texture_2d
   })",
                         R"(
-          TypeConstructor[not set]{
-            __vec_4__f32
-            Call[not set]{
-              Identifier[not set]{textureSampleCompare}
-              (
-                Identifier[not set]{x_20}
-                Identifier[not set]{x_10}
-                Identifier[not set]{coords12}
-                ScalarConstructor[not set]{0.200000}
-              )
-            }
-            ScalarConstructor[not set]{0.000000}
-            ScalarConstructor[not set]{0.000000}
-            ScalarConstructor[not set]{0.000000}
+          Call[not set]{
+            Identifier[not set]{textureSampleCompare}
+            (
+              Identifier[not set]{x_20}
+              Identifier[not set]{x_10}
+              Identifier[not set]{coords12}
+              ScalarConstructor[not set]{0.200000}
+            )
           })"},
         // ImageSampleDrefImplicitLod - arrayed
         ImageAccessCase{"%float 2D 0 1 0 1 Unknown",
                         "%result = OpImageSampleDrefImplicitLod "
-                        "%v4float %sampled_image %coords123 %depth",
+                        "%float %sampled_image %coords123 %depth",
                         R"(
   Variable{
     Decorations{
@@ -1860,35 +1848,29 @@
     __depth_texture_2d_array
   })",
                         R"(
-          TypeConstructor[not set]{
-            __vec_4__f32
-            Call[not set]{
-              Identifier[not set]{textureSampleCompare}
-              (
-                Identifier[not set]{x_20}
-                Identifier[not set]{x_10}
+          Call[not set]{
+            Identifier[not set]{textureSampleCompare}
+            (
+              Identifier[not set]{x_20}
+              Identifier[not set]{x_10}
+              MemberAccessor[not set]{
+                Identifier[not set]{coords123}
+                Identifier[not set]{xy}
+              }
+              TypeConstructor[not set]{
+                __i32
                 MemberAccessor[not set]{
                   Identifier[not set]{coords123}
-                  Identifier[not set]{xy}
+                  Identifier[not set]{z}
                 }
-                TypeConstructor[not set]{
-                  __i32
-                  MemberAccessor[not set]{
-                    Identifier[not set]{coords123}
-                    Identifier[not set]{z}
-                  }
-                }
-                ScalarConstructor[not set]{0.200000}
-              )
-            }
-            ScalarConstructor[not set]{0.000000}
-            ScalarConstructor[not set]{0.000000}
-            ScalarConstructor[not set]{0.000000}
+              }
+              ScalarConstructor[not set]{0.200000}
+            )
           })"},
         // ImageSampleDrefImplicitLod with ConstOffset
         ImageAccessCase{
             "%float 2D 0 0 0 1 Unknown",
-            "%result = OpImageSampleDrefImplicitLod %v4float "
+            "%result = OpImageSampleDrefImplicitLod %float "
             "%sampled_image %coords12 %depth ConstOffset %offsets2d",
             R"(
   Variable{
@@ -1910,26 +1892,20 @@
     __depth_texture_2d
   })",
             R"(
-          TypeConstructor[not set]{
-            __vec_4__f32
-            Call[not set]{
-              Identifier[not set]{textureSampleCompare}
-              (
-                Identifier[not set]{x_20}
-                Identifier[not set]{x_10}
-                Identifier[not set]{coords12}
-                ScalarConstructor[not set]{0.200000}
-                Identifier[not set]{offsets2d}
-              )
-            }
-            ScalarConstructor[not set]{0.000000}
-            ScalarConstructor[not set]{0.000000}
-            ScalarConstructor[not set]{0.000000}
+          Call[not set]{
+            Identifier[not set]{textureSampleCompare}
+            (
+              Identifier[not set]{x_20}
+              Identifier[not set]{x_10}
+              Identifier[not set]{coords12}
+              ScalarConstructor[not set]{0.200000}
+              Identifier[not set]{offsets2d}
+            )
           })"},
         // ImageSampleDrefImplicitLod arrayed with ConstOffset
         ImageAccessCase{
             "%float 2D 0 1 0 1 Unknown",
-            "%result = OpImageSampleDrefImplicitLod %v4float "
+            "%result = OpImageSampleDrefImplicitLod %float "
             "%sampled_image %coords123 %depth ConstOffset %offsets2d",
             R"(
   Variable{
@@ -1951,31 +1927,25 @@
     __depth_texture_2d_array
   })",
             R"(
-          TypeConstructor[not set]{
-            __vec_4__f32
-            Call[not set]{
-              Identifier[not set]{textureSampleCompare}
-              (
-                Identifier[not set]{x_20}
-                Identifier[not set]{x_10}
+          Call[not set]{
+            Identifier[not set]{textureSampleCompare}
+            (
+              Identifier[not set]{x_20}
+              Identifier[not set]{x_10}
+              MemberAccessor[not set]{
+                Identifier[not set]{coords123}
+                Identifier[not set]{xy}
+              }
+              TypeConstructor[not set]{
+                __i32
                 MemberAccessor[not set]{
                   Identifier[not set]{coords123}
-                  Identifier[not set]{xy}
+                  Identifier[not set]{z}
                 }
-                TypeConstructor[not set]{
-                  __i32
-                  MemberAccessor[not set]{
-                    Identifier[not set]{coords123}
-                    Identifier[not set]{z}
-                  }
-                }
-                ScalarConstructor[not set]{0.200000}
-                Identifier[not set]{offsets2d}
-              )
-            }
-            ScalarConstructor[not set]{0.000000}
-            ScalarConstructor[not set]{0.000000}
-            ScalarConstructor[not set]{0.000000}
+              }
+              ScalarConstructor[not set]{0.200000}
+              Identifier[not set]{offsets2d}
+            )
           })"}));
 
 INSTANTIATE_TEST_SUITE_P(
@@ -3126,6 +3096,48 @@
       }
     })"}}));
 
+INSTANTIATE_TEST_SUITE_P(ImageFetch_Depth,
+                         // In SPIR-V OpImageFetch always yields a vector of 4
+                         // elements, even for depth images.  But in WGSL,
+                         // textureLoad on a depth image yields f32.
+                         // crbug.com/tint/439
+                         SpvParserTest_ImageAccessTest,
+                         ::testing::ValuesIn(std::vector<ImageAccessCase>{
+                             // ImageFetch on depth image.
+                             {"%float 2D 1 0 0 1 Unknown",
+                              "%99 = OpImageFetch %v4float %im %vi12 ",
+                              R"(Variable{
+    Decorations{
+      SetDecoration{2}
+      BindingDecoration{1}
+    }
+    x_20
+    uniform_constant
+    __depth_texture_2d
+  })",
+                              R"(VariableDeclStatement{
+      VariableConst{
+        x_99
+        none
+        __vec_4__f32
+        {
+          TypeConstructor[not set]{
+            __vec_4__f32
+            Call[not set]{
+              Identifier[not set]{textureLoad}
+              (
+                Identifier[not set]{x_20}
+                Identifier[not set]{vi12}
+              )
+            }
+            ScalarConstructor[not set]{0.000000}
+            ScalarConstructor[not set]{0.000000}
+            ScalarConstructor[not set]{0.000000}
+          }
+        }
+      }
+    })"}}));
+
 INSTANTIATE_TEST_SUITE_P(
     ImageFetch_Multisampled,
     SpvParserTest_ImageAccessTest,
@@ -3966,12 +3978,12 @@
          "",
          {"Identifier[not set]{vf12}\n"}},
         {"%float 2D 1 0 0 1 Unknown",
-         "%result = OpImageSampleDrefImplicitLod %v4float %sampled_image %vf12 "
+         "%result = OpImageSampleDrefImplicitLod %float %sampled_image %vf12 "
          "%depth",
          "",
          {"Identifier[not set]{vf12}\n"}},
         {"%float 2D 1 0 0 1 Unknown",
-         "%result = OpImageSampleDrefExplicitLod %v4float %sampled_image %vf12 "
+         "%result = OpImageSampleDrefExplicitLod %float %sampled_image %vf12 "
          "%depth Lod %f1",
          "",
          {"Identifier[not set]{vf12}\n"}},
@@ -4022,7 +4034,7 @@
 }
 )"}},
         {"%float 2D 1 1 0 1 Unknown",
-         "%result = OpImageSampleDrefImplicitLod %v4float %sampled_image "
+         "%result = OpImageSampleDrefImplicitLod %float %sampled_image "
          "%vf123 %depth",
          "",
          {
@@ -4040,7 +4052,7 @@
 }
 )"}},
         {"%float 2D 1 1 0 1 Unknown",
-         "%result = OpImageSampleDrefExplicitLod %v4float %sampled_image "
+         "%result = OpImageSampleDrefExplicitLod %float %sampled_image "
          "%vf123 %depth Lod %f1",
          "",
          {
@@ -4354,23 +4366,23 @@
          {}},
         // ImageSampleDrefImplicitLod
         {"%uint 2D 0 0 0 1 Unknown",
-         "%result = OpImageSampleDrefImplicitLod %v4uint %sampled_image %vf12 "
+         "%result = OpImageSampleDrefImplicitLod %uint %sampled_image %vf12 "
          "%f1",
          "sampled image must have float component type",
          {}},
         {"%int 2D 0 0 0 1 Unknown",
-         "%result = OpImageSampleDrefImplicitLod %v4int %sampled_image %vf12 "
+         "%result = OpImageSampleDrefImplicitLod %int %sampled_image %vf12 "
          "%f1",
          "sampled image must have float component type",
          {}},
         // ImageSampleDrefExplicitLod
         {"%uint 2D 0 0 0 1 Unknown",
-         "%result = OpImageSampleDrefExplicitLod %v4uint %sampled_image %vf12 "
+         "%result = OpImageSampleDrefExplicitLod %uint %sampled_image %vf12 "
          "%f1 Lod %f1",
          "sampled image must have float component type",
          {}},
         {"%int 2D 0 0 0 1 Unknown",
-         "%result = OpImageSampleDrefExplicitLod %v4int %sampled_image %vf12 "
+         "%result = OpImageSampleDrefExplicitLod %int %sampled_image %vf12 "
          "%f1 Lod %f1",
          "sampled image must have float component type",
          {}}}));