Fix HLSL emission of RWTextures

These must have a element type in a declaration statement for the object. See: https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/sm5-object-rwtexture2d

Change-Id: Ia13fb37351a7cf3f043e152d5f7a216e3c2bf88e
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/35380
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
diff --git a/src/writer/hlsl/generator_impl.cc b/src/writer/hlsl/generator_impl.cc
index baefa5f..f040181 100644
--- a/src/writer/hlsl/generator_impl.cc
+++ b/src/writer/hlsl/generator_impl.cc
@@ -112,6 +112,33 @@
   return 0;
 }
 
+const char* image_format_to_rwtexture_type(
+    ast::type::ImageFormat image_format) {
+  switch (image_format) {
+    case ast::type::ImageFormat::kRgba8Unorm:
+    case ast::type::ImageFormat::kRgba8Snorm:
+    case ast::type::ImageFormat::kRgba16Float:
+    case ast::type::ImageFormat::kR32Float:
+    case ast::type::ImageFormat::kRg32Float:
+    case ast::type::ImageFormat::kRgba32Float:
+      return "float4";
+    case ast::type::ImageFormat::kRgba8Uint:
+    case ast::type::ImageFormat::kRgba16Uint:
+    case ast::type::ImageFormat::kR32Uint:
+    case ast::type::ImageFormat::kRg32Uint:
+    case ast::type::ImageFormat::kRgba32Uint:
+      return "uint4";
+    case ast::type::ImageFormat::kRgba8Sint:
+    case ast::type::ImageFormat::kRgba16Sint:
+    case ast::type::ImageFormat::kR32Sint:
+    case ast::type::ImageFormat::kRg32Sint:
+    case ast::type::ImageFormat::kRgba32Sint:
+      return "int4";
+    default:
+      return nullptr;
+  }
+}
+
 }  // namespace
 
 GeneratorImpl::GeneratorImpl(ast::Module* module) : module_(module) {}
@@ -2157,6 +2184,15 @@
         return false;
     }
 
+    if (auto* st = tex->As<ast::type::StorageTexture>()) {
+      auto* component = image_format_to_rwtexture_type(st->image_format());
+      if (component == nullptr) {
+        error_ = "Unsupported StorageTexture ImageFormat: " +
+                 std::to_string(static_cast<int>(st->image_format()));
+        return false;
+      }
+      out << "<" << component << ">";
+    }
   } else if (type->Is<ast::type::U32>()) {
     out << "uint";
   } else if (auto* vec = type->As<ast::type::Vector>()) {
diff --git a/src/writer/hlsl/generator_impl_type_test.cc b/src/writer/hlsl/generator_impl_type_test.cc
index fdd19c8..b59c9c4 100644
--- a/src/writer/hlsl/generator_impl_type_test.cc
+++ b/src/writer/hlsl/generator_impl_type_test.cc
@@ -405,6 +405,7 @@
 
 struct HlslStorageTextureData {
   ast::type::TextureDimension dim;
+  ast::type::ImageFormat imgfmt;
   bool ro;
   std::string result;
 };
@@ -420,7 +421,7 @@
   ast::type::StorageTexture s(params.dim,
                               params.ro ? ast::AccessControl::kReadOnly
                                         : ast::AccessControl::kWriteOnly,
-                              ast::type::ImageFormat::kR16Float);
+                              params.imgfmt);
 
   ASSERT_TRUE(gen.EmitType(out, &s, "")) << gen.error();
   EXPECT_EQ(result(), params.result);
@@ -429,26 +430,54 @@
     HlslGeneratorImplTest_Type,
     HlslStoragetexturesTest,
     testing::Values(
-        HlslStorageTextureData{ast::type::TextureDimension::k1d, true,
-                               "RWTexture1D"},
-        HlslStorageTextureData{ast::type::TextureDimension::k1dArray, true,
-                               "RWTexture1DArray"},
-        HlslStorageTextureData{ast::type::TextureDimension::k2d, true,
-                               "RWTexture2D"},
-        HlslStorageTextureData{ast::type::TextureDimension::k2dArray, true,
-                               "RWTexture2DArray"},
-        HlslStorageTextureData{ast::type::TextureDimension::k3d, true,
-                               "RWTexture3D"},
-        HlslStorageTextureData{ast::type::TextureDimension::k1d, false,
-                               "RWTexture1D"},
-        HlslStorageTextureData{ast::type::TextureDimension::k1dArray, false,
-                               "RWTexture1DArray"},
-        HlslStorageTextureData{ast::type::TextureDimension::k2d, false,
-                               "RWTexture2D"},
-        HlslStorageTextureData{ast::type::TextureDimension::k2dArray, false,
-                               "RWTexture2DArray"},
-        HlslStorageTextureData{ast::type::TextureDimension::k3d, false,
-                               "RWTexture3D"}));
+        HlslStorageTextureData{ast::type::TextureDimension::k1d,
+                               ast::type::ImageFormat::kRgba8Unorm, true,
+                               "RWTexture1D<float4>"},
+        HlslStorageTextureData{ast::type::TextureDimension::k1dArray,
+                               ast::type::ImageFormat::kRgba8Snorm, true,
+                               "RWTexture1DArray<float4>"},
+        HlslStorageTextureData{ast::type::TextureDimension::k2d,
+                               ast::type::ImageFormat::kRgba16Float, true,
+                               "RWTexture2D<float4>"},
+        HlslStorageTextureData{ast::type::TextureDimension::k2dArray,
+                               ast::type::ImageFormat::kR32Float, true,
+                               "RWTexture2DArray<float4>"},
+        HlslStorageTextureData{ast::type::TextureDimension::k3d,
+                               ast::type::ImageFormat::kRg32Float, true,
+                               "RWTexture3D<float4>"},
+        HlslStorageTextureData{ast::type::TextureDimension::k1d,
+                               ast::type::ImageFormat::kRgba32Float, false,
+                               "RWTexture1D<float4>"},
+        HlslStorageTextureData{ast::type::TextureDimension::k1dArray,
+                               ast::type::ImageFormat::kRgba8Uint, false,
+                               "RWTexture1DArray<uint4>"},
+        HlslStorageTextureData{ast::type::TextureDimension::k2d,
+                               ast::type::ImageFormat::kRgba16Uint, false,
+                               "RWTexture2D<uint4>"},
+        HlslStorageTextureData{ast::type::TextureDimension::k2dArray,
+                               ast::type::ImageFormat::kR32Uint, false,
+                               "RWTexture2DArray<uint4>"},
+        HlslStorageTextureData{ast::type::TextureDimension::k3d,
+                               ast::type::ImageFormat::kRg32Uint, false,
+                               "RWTexture3D<uint4>"},
+        HlslStorageTextureData{ast::type::TextureDimension::k1d,
+                               ast::type::ImageFormat::kRgba32Uint, true,
+                               "RWTexture1D<uint4>"},
+        HlslStorageTextureData{ast::type::TextureDimension::k1dArray,
+                               ast::type::ImageFormat::kRgba8Sint, true,
+                               "RWTexture1DArray<int4>"},
+        HlslStorageTextureData{ast::type::TextureDimension::k2d,
+                               ast::type::ImageFormat::kRgba16Sint, true,
+                               "RWTexture2D<int4>"},
+        HlslStorageTextureData{ast::type::TextureDimension::k2dArray,
+                               ast::type::ImageFormat::kR32Sint, true,
+                               "RWTexture2DArray<int4>"},
+        HlslStorageTextureData{ast::type::TextureDimension::k3d,
+                               ast::type::ImageFormat::kRg32Sint, true,
+                               "RWTexture3D<int4>"},
+        HlslStorageTextureData{ast::type::TextureDimension::k1d,
+                               ast::type::ImageFormat::kRgba32Sint, false,
+                               "RWTexture1D<int4>"}));
 
 }  // namespace
 }  // namespace hlsl