writer/hlsl: Include format type for sampled textures

Required for correct output of .Load() functions

Bug: tint:689
Change-Id: I5e5ea068700bbe2239f04dc81da9acb7abce0210
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/47225
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
diff --git a/src/writer/hlsl/generator_impl.cc b/src/writer/hlsl/generator_impl.cc
index c569d51..845cb70 100644
--- a/src/writer/hlsl/generator_impl.cc
+++ b/src/writer/hlsl/generator_impl.cc
@@ -2442,24 +2442,26 @@
   } else if (auto* str = type->As<type::Struct>()) {
     out << builder_.Symbols().NameFor(str->symbol());
   } else if (auto* tex = type->As<type::Texture>()) {
-    if (tex->Is<type::StorageTexture>()) {
+    auto* storage = tex->As<type::StorageTexture>();
+    auto* multism = tex->As<type::MultisampledTexture>();
+    auto* sampled = tex->As<type::SampledTexture>();
+
+    if (storage) {
       if (access && !access->IsReadOnly()) {
         out << "RW";
       }
     }
     out << "Texture";
 
-    auto* ms = tex->As<type::MultisampledTexture>();
-
     switch (tex->dim()) {
       case type::TextureDimension::k1d:
         out << "1D";
         break;
       case type::TextureDimension::k2d:
-        out << (ms ? "2DMS" : "2D");
+        out << (multism ? "2DMS" : "2D");
         break;
       case type::TextureDimension::k2dArray:
-        out << (ms ? "2DMSArray" : "2DArray");
+        out << (multism ? "2DMSArray" : "2DArray");
         break;
       case type::TextureDimension::k3d:
         out << "3D";
@@ -2476,33 +2478,28 @@
         return false;
     }
 
-    if (ms) {
+    if (storage) {
+      auto* component = image_format_to_rwtexture_type(storage->image_format());
+      if (component == nullptr) {
+        TINT_ICE(diagnostics_) << "Unsupported StorageTexture ImageFormat: "
+                               << static_cast<int>(storage->image_format());
+        return false;
+      }
+      out << "<" << component << ">";
+    } else if (sampled || multism) {
+      auto* subtype = sampled ? sampled->type() : multism->type();
       out << "<";
-      if (ms->type()->Is<type::F32>()) {
+      if (subtype->Is<type::F32>()) {
         out << "float4";
-      } else if (ms->type()->Is<type::I32>()) {
+      } else if (subtype->Is<type::I32>()) {
         out << "int4";
-      } else if (ms->type()->Is<type::U32>()) {
+      } else if (subtype->Is<type::U32>()) {
         out << "uint4";
       } else {
         TINT_ICE(diagnostics_) << "Unsupported multisampled texture type";
         return false;
       }
-
-      // TODO(ben-clayton): The HLSL docs claim that the MS texture type should
-      // also contain the number of samples, which is not part of the WGSL type.
-      // However, DXC seems to consider this optional.
-      // See: https://github.com/gpuweb/gpuweb/issues/1445
-
       out << ">";
-    } else if (auto* st = tex->As<type::StorageTexture>()) {
-      auto* component = image_format_to_rwtexture_type(st->image_format());
-      if (component == nullptr) {
-        TINT_ICE(diagnostics_) << "Unsupported StorageTexture ImageFormat: "
-                               << static_cast<int>(st->image_format());
-        return false;
-      }
-      out << "<" << component << ">";
     }
   } else if (type->Is<type::U32>()) {
     out << "uint";
diff --git a/src/writer/hlsl/generator_impl_type_test.cc b/src/writer/hlsl/generator_impl_type_test.cc
index bb64ba4..5a3f4bb 100644
--- a/src/writer/hlsl/generator_impl_type_test.cc
+++ b/src/writer/hlsl/generator_impl_type_test.cc
@@ -355,8 +355,10 @@
         HlslDepthTextureData{type::TextureDimension::kCubeArray,
                              "TextureCubeArray tex : register(t1, space2);"}));
 
+enum class TextureDataType { F32, U32, I32 };
 struct HlslSampledTextureData {
   type::TextureDimension dim;
+  TextureDataType datatype;
   std::string result;
 };
 inline std::ostream& operator<<(std::ostream& out,
@@ -368,7 +370,19 @@
 TEST_P(HlslSampledTexturesTest, Emit) {
   auto params = GetParam();
 
-  auto* t = create<type::SampledTexture>(params.dim, ty.f32());
+  type::Type* datatype = nullptr;
+  switch (params.datatype) {
+    case TextureDataType::F32:
+      datatype = ty.f32();
+      break;
+    case TextureDataType::U32:
+      datatype = ty.u32();
+      break;
+    case TextureDataType::I32:
+      datatype = ty.i32();
+      break;
+  }
+  auto* t = create<type::SampledTexture>(params.dim, datatype);
 
   Global("tex", t, ast::StorageClass::kUniformConstant, nullptr,
          ast::DecorationList{
@@ -391,19 +405,96 @@
     HlslGeneratorImplTest_Type,
     HlslSampledTexturesTest,
     testing::Values(
-        HlslSampledTextureData{type::TextureDimension::k1d,
-                               "Texture1D tex : register(t1, space2);"},
-        HlslSampledTextureData{type::TextureDimension::k2d,
-                               "Texture2D tex : register(t1, space2);"},
-        HlslSampledTextureData{type::TextureDimension::k2dArray,
-                               "Texture2DArray tex : register(t1, space2);"},
-        HlslSampledTextureData{type::TextureDimension::k3d,
-                               "Texture3D tex : register(t1, space2);"},
-        HlslSampledTextureData{type::TextureDimension::kCube,
-                               "TextureCube tex : register(t1, space2);"},
+        HlslSampledTextureData{
+            type::TextureDimension::k1d,
+            TextureDataType::F32,
+            "Texture1D<float4> tex : register(t1, space2);",
+        },
+        HlslSampledTextureData{
+            type::TextureDimension::k2d,
+            TextureDataType::F32,
+            "Texture2D<float4> tex : register(t1, space2);",
+        },
+        HlslSampledTextureData{
+            type::TextureDimension::k2dArray,
+            TextureDataType::F32,
+            "Texture2DArray<float4> tex : register(t1, space2);",
+        },
+        HlslSampledTextureData{
+            type::TextureDimension::k3d,
+            TextureDataType::F32,
+            "Texture3D<float4> tex : register(t1, space2);",
+        },
+        HlslSampledTextureData{
+            type::TextureDimension::kCube,
+            TextureDataType::F32,
+            "TextureCube<float4> tex : register(t1, space2);",
+        },
         HlslSampledTextureData{
             type::TextureDimension::kCubeArray,
-            "TextureCubeArray tex : register(t1, space2);"}));
+            TextureDataType::F32,
+            "TextureCubeArray<float4> tex : register(t1, space2);",
+        },
+        HlslSampledTextureData{
+            type::TextureDimension::k1d,
+            TextureDataType::U32,
+            "Texture1D<uint4> tex : register(t1, space2);",
+        },
+        HlslSampledTextureData{
+            type::TextureDimension::k2d,
+            TextureDataType::U32,
+            "Texture2D<uint4> tex : register(t1, space2);",
+        },
+        HlslSampledTextureData{
+            type::TextureDimension::k2dArray,
+            TextureDataType::U32,
+            "Texture2DArray<uint4> tex : register(t1, space2);",
+        },
+        HlslSampledTextureData{
+            type::TextureDimension::k3d,
+            TextureDataType::U32,
+            "Texture3D<uint4> tex : register(t1, space2);",
+        },
+        HlslSampledTextureData{
+            type::TextureDimension::kCube,
+            TextureDataType::U32,
+            "TextureCube<uint4> tex : register(t1, space2);",
+        },
+        HlslSampledTextureData{
+            type::TextureDimension::kCubeArray,
+            TextureDataType::U32,
+            "TextureCubeArray<uint4> tex : register(t1, space2);",
+        },
+        HlslSampledTextureData{
+            type::TextureDimension::k1d,
+            TextureDataType::I32,
+            "Texture1D<int4> tex : register(t1, space2);",
+        },
+        HlslSampledTextureData{
+            type::TextureDimension::k2d,
+            TextureDataType::I32,
+            "Texture2D<int4> tex : register(t1, space2);",
+        },
+        HlslSampledTextureData{
+            type::TextureDimension::k2dArray,
+            TextureDataType::I32,
+            "Texture2DArray<int4> tex : register(t1, space2);",
+        },
+        HlslSampledTextureData{
+            type::TextureDimension::k3d,
+            TextureDataType::I32,
+            "Texture3D<int4> tex : register(t1, space2);",
+        },
+        HlslSampledTextureData{
+            type::TextureDimension::kCube,
+            TextureDataType::I32,
+            "TextureCube<int4> tex : register(t1, space2);",
+        },
+        HlslSampledTextureData{
+            type::TextureDimension::kCubeArray,
+            TextureDataType::I32,
+            "TextureCubeArray<int4> tex : register(t1, space2);",
+        }));
 
 TEST_F(HlslGeneratorImplTest_Type, EmitMultisampledTexture) {
   type::MultisampledTexture s(type::TextureDimension::k2d, ty.f32());