[tint][ir][spirv] Deduplicate storage textures with different accesses

`readonly_and_readwrite_storage_textures` adds support for storage texture with read and write access controls. SPIR-V does not consider these different types, and need deduplicating.

Fixed: 342840932
Change-Id: I3ecb0b7ac4dabe414eece04343d1089ffb9af570
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/190621
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Reviewed-by: David Neto <dneto@google.com>
Auto-Submit: Ben Clayton <bclayton@google.com>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
diff --git a/src/tint/lang/spirv/writer/printer/printer.cc b/src/tint/lang/spirv/writer/printer/printer.cc
index c2e7104..3a3fa00 100644
--- a/src/tint/lang/spirv/writer/printer/printer.cc
+++ b/src/tint/lang/spirv/writer/printer/printer.cc
@@ -32,6 +32,7 @@
 #include "spirv/unified1/GLSL.std.450.h"
 #include "spirv/unified1/spirv.h"
 
+#include "src/tint/lang/core/access.h"
 #include "src/tint/lang/core/address_space.h"
 #include "src/tint/lang/core/builtin_value.h"
 #include "src/tint/lang/core/constant/scalar.h"
@@ -157,6 +158,10 @@
         [&](const core::type::DepthMultisampledTexture* depth) {
             return types.Get<core::type::MultisampledTexture>(depth->dim(), types.f32());
         },
+        [&](const core::type::StorageTexture* st) -> const core::type::Type* {
+            return types.Get<core::type::StorageTexture>(st->dim(), st->texel_format(),
+                                                         core::Access::kRead, st->type());
+        },
 
         // Both sampler types are the same in SPIR-V.
         [&](const core::type::Sampler* s) -> const core::type::Type* {
diff --git a/src/tint/lang/spirv/writer/type_test.cc b/src/tint/lang/spirv/writer/type_test.cc
index 27fdc1b..febac19 100644
--- a/src/tint/lang/spirv/writer/type_test.cc
+++ b/src/tint/lang/spirv/writer/type_test.cc
@@ -302,6 +302,26 @@
     EXPECT_INST("%v2 = OpVariable %_ptr_UniformConstant_3_0 UniformConstant");
 }
 
+TEST_F(SpirvWriterTest, Type_StorageTexture_Dedup) {
+    b.Append(b.ir.root_block, [&] {
+        auto* v1 = b.Var("v1", ty.ptr<handle, read_write>(ty.Get<core::type::StorageTexture>(
+                                   core::type::TextureDimension::k2dArray,
+                                   core::TexelFormat::kR32Uint, core::Access::kRead, ty.u32())));
+        auto* v2 = b.Var("v2", ty.ptr<handle, read_write>(ty.Get<core::type::StorageTexture>(
+                                   core::type::TextureDimension::k2dArray,
+                                   core::TexelFormat::kR32Uint, core::Access::kWrite, ty.u32())));
+        v1->SetBindingPoint(0, 1);
+        v2->SetBindingPoint(0, 2);
+    });
+
+    ASSERT_TRUE(Generate()) << Error() << output_;
+    EXPECT_INST("%3 = OpTypeImage %uint 2D 0 1 0 2 R32ui");
+    EXPECT_INST("%_ptr_UniformConstant_3 = OpTypePointer UniformConstant %3");
+    EXPECT_INST("%v1 = OpVariable %_ptr_UniformConstant_3 UniformConstant");
+    EXPECT_INST("%_ptr_UniformConstant_3_0 = OpTypePointer UniformConstant %3");
+    EXPECT_INST("%v2 = OpVariable %_ptr_UniformConstant_3_0 UniformConstant");
+}
+
 using Dim = core::type::TextureDimension;
 struct TextureCase {
     std::string result;
diff --git a/test/tint/bug/chromium/342840932.wgsl b/test/tint/bug/chromium/342840932.wgsl
new file mode 100644
index 0000000..fdfbe04
--- /dev/null
+++ b/test/tint/bug/chromium/342840932.wgsl
@@ -0,0 +1,4 @@
+@group(0) @binding(0) var image_dup_src: texture_storage_1d<r32uint,read>;
+@group(0) @binding(1) var image_dst: texture_storage_1d<r32uint,write>;
+
+// for #1307 loads with ivec2 coords.
diff --git a/test/tint/bug/chromium/342840932.wgsl.expected.dxc.hlsl b/test/tint/bug/chromium/342840932.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..94156e0
--- /dev/null
+++ b/test/tint/bug/chromium/342840932.wgsl.expected.dxc.hlsl
@@ -0,0 +1,7 @@
+[numthreads(1, 1, 1)]
+void unused_entry_point() {
+  return;
+}
+
+Texture1D<uint4> image_dup_src : register(t0);
+RWTexture1D<uint4> image_dst : register(u1);
diff --git a/test/tint/bug/chromium/342840932.wgsl.expected.fxc.hlsl b/test/tint/bug/chromium/342840932.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..94156e0
--- /dev/null
+++ b/test/tint/bug/chromium/342840932.wgsl.expected.fxc.hlsl
@@ -0,0 +1,7 @@
+[numthreads(1, 1, 1)]
+void unused_entry_point() {
+  return;
+}
+
+Texture1D<uint4> image_dup_src : register(t0);
+RWTexture1D<uint4> image_dst : register(u1);
diff --git a/test/tint/bug/chromium/342840932.wgsl.expected.glsl b/test/tint/bug/chromium/342840932.wgsl.expected.glsl
new file mode 100644
index 0000000..53b3c19
--- /dev/null
+++ b/test/tint/bug/chromium/342840932.wgsl.expected.glsl
@@ -0,0 +1,8 @@
+#version 310 es
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void unused_entry_point() {
+  return;
+}
+layout(r32ui) uniform highp readonly uimage2D image_dup_src;
+layout(r32ui) uniform highp writeonly uimage2D image_dst;
diff --git a/test/tint/bug/chromium/342840932.wgsl.expected.msl b/test/tint/bug/chromium/342840932.wgsl.expected.msl
new file mode 100644
index 0000000..466ceaa
--- /dev/null
+++ b/test/tint/bug/chromium/342840932.wgsl.expected.msl
@@ -0,0 +1,3 @@
+#include <metal_stdlib>
+
+using namespace metal;
diff --git a/test/tint/bug/chromium/342840932.wgsl.expected.spvasm b/test/tint/bug/chromium/342840932.wgsl.expected.spvasm
new file mode 100644
index 0000000..6936908
--- /dev/null
+++ b/test/tint/bug/chromium/342840932.wgsl.expected.spvasm
@@ -0,0 +1,31 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 11
+; Schema: 0
+               OpCapability Shader
+               OpCapability Image1D
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %unused_entry_point "unused_entry_point"
+               OpExecutionMode %unused_entry_point LocalSize 1 1 1
+               OpName %image_dup_src "image_dup_src"
+               OpName %image_dst "image_dst"
+               OpName %unused_entry_point "unused_entry_point"
+               OpDecorate %image_dup_src NonWritable
+               OpDecorate %image_dup_src DescriptorSet 0
+               OpDecorate %image_dup_src Binding 0
+               OpDecorate %image_dst NonReadable
+               OpDecorate %image_dst DescriptorSet 0
+               OpDecorate %image_dst Binding 1
+       %uint = OpTypeInt 32 0
+          %3 = OpTypeImage %uint 1D 0 0 0 2 R32ui
+%_ptr_UniformConstant_3 = OpTypePointer UniformConstant %3
+%image_dup_src = OpVariable %_ptr_UniformConstant_3 UniformConstant
+%_ptr_UniformConstant_3_0 = OpTypePointer UniformConstant %3
+  %image_dst = OpVariable %_ptr_UniformConstant_3_0 UniformConstant
+       %void = OpTypeVoid
+          %7 = OpTypeFunction %void
+%unused_entry_point = OpFunction %void None %7
+         %10 = OpLabel
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/bug/chromium/342840932.wgsl.expected.wgsl b/test/tint/bug/chromium/342840932.wgsl.expected.wgsl
new file mode 100644
index 0000000..f5ce9b1
--- /dev/null
+++ b/test/tint/bug/chromium/342840932.wgsl.expected.wgsl
@@ -0,0 +1,3 @@
+@group(0) @binding(0) var image_dup_src : texture_storage_1d<r32uint, read>;
+
+@group(0) @binding(1) var image_dst : texture_storage_1d<r32uint, write>;