[spirv-reader][ir] Fix issue with SampledImage registration.

When converting user calls, we may fork functions which take image
parameters. This means, if the function has a `SampledImage` we won't
have registered it in the `SampledImage` hash. To fix this, when
re-iterating over the instructions, re-record any `SampledImage`
instructions.

Fixed: 430358345
Change-Id: I2dbdda8cbb7276ab7a8f129ebe1ef40cf6c7a2d0
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/256295
Commit-Queue: James Price <jrprice@google.com>
Reviewed-by: James Price <jrprice@google.com>
diff --git a/src/tint/lang/spirv/reader/lower/texture.cc b/src/tint/lang/spirv/reader/lower/texture.cc
index 1094329..1166a51 100644
--- a/src/tint/lang/spirv/reader/lower/texture.cc
+++ b/src/tint/lang/spirv/reader/lower/texture.cc
@@ -182,7 +182,12 @@
             if (auto* builtin = inst->As<spirv::ir::BuiltinCall>()) {
                 switch (builtin->Func()) {
                     case spirv::BuiltinFn::kSampledImage:
-                        // Handled above.
+                        // Note, we _also_ do this here even though it was done above. The one above
+                        // registers for the depth functions, but, we may have forked functions in
+                        // the `UpdateValues` when it does the `ConvertUserCalls`. This would then
+                        // generate new `SampledImage` objects which need to be registered. In the
+                        // worse case, we just write the same data twice.
+                        SampledImage(builtin);
                         break;
                     case spirv::BuiltinFn::kImage:
                     case spirv::BuiltinFn::kImageRead:
@@ -245,7 +250,11 @@
 
         // Destroy all the OpSampledImage instructions.
         for (auto res : sampled_images_) {
-            res.value->Destroy();
+            // If the sampled image was in a user function which was forked and the original
+            // destroyed then it will no longer be alive.
+            if (res.value->Alive()) {
+                res.value->Destroy();
+            }
         }
     }
 
diff --git a/src/tint/lang/spirv/reader/texture_test.cc b/src/tint/lang/spirv/reader/texture_test.cc
index 3159e89..4a07d73 100644
--- a/src/tint/lang/spirv/reader/texture_test.cc
+++ b/src/tint/lang/spirv/reader/texture_test.cc
@@ -4180,5 +4180,83 @@
 )");
 }
 
+// https://crbug.com/430358345
+TEST_F(SpirvReaderTest, Image_UserCall_Params) {
+    EXPECT_IR(R"(
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %main "main" %main_position_Input
+               OpExecutionMode %main OriginUpperLeft
+               OpName %sampler0 "sampler0"
+               OpName %texture0 "texture0"
+               OpName %main_position_Input "main_position_Input"
+               OpName %foo "foo"
+               OpName %t "t"
+               OpName %s "s"
+               OpName %main "main"
+               OpDecorate %sampler0 DescriptorSet 0
+               OpDecorate %sampler0 Binding 0
+               OpDecorate %texture0 DescriptorSet 0
+               OpDecorate %texture0 Binding 1
+               OpDecorate %main_position_Input BuiltIn FragCoord
+          %3 = OpTypeSampler
+%_ptr_UniformConstant_3 = OpTypePointer UniformConstant %3
+   %sampler0 = OpVariable %_ptr_UniformConstant_3 UniformConstant
+      %float = OpTypeFloat 32
+          %6 = OpTypeImage %float 2D 0 0 0 1 Unknown
+%_ptr_UniformConstant_6 = OpTypePointer UniformConstant %6
+   %texture0 = OpVariable %_ptr_UniformConstant_6 UniformConstant
+    %v4float = OpTypeVector %float 4
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+%main_position_Input = OpVariable %_ptr_Input_v4float Input
+         %17 = OpTypeFunction %v4float %6 %3
+    %v2float = OpTypeVector %float 2
+    %float_2 = OpConstant %float 2
+         %22 = OpConstantComposite %v2float %float_2 %float_2
+         %25 = OpTypeSampledImage %6
+         %29 = OpTypeFunction %v4float %v4float
+       %void = OpTypeVoid
+         %36 = OpTypeFunction %void
+
+        %foo = OpFunction %v4float None %17
+          %t = OpFunctionParameter %6
+          %s = OpFunctionParameter %3
+         %18 = OpLabel
+         %24 = OpSampledImage %25 %t %s
+         %26 = OpImageSampleImplicitLod %v4float %24 %22 None
+               OpReturnValue %26
+               OpFunctionEnd
+
+       %main = OpFunction %void None %36
+         %37 = OpLabel
+         %31 = OpLoad %6 %texture0 None
+         %32 = OpLoad %3 %sampler0 None
+         %33 = OpFunctionCall %v4float %foo %31 %32
+               OpReturn
+               OpFunctionEnd
+)",
+              R"(
+$B1: {  # root
+  %sampler0:ptr<handle, sampler, read> = var undef @binding_point(0, 0)
+  %texture0:ptr<handle, texture_2d<f32>, read> = var undef @binding_point(0, 1)
+}
+
+%main = @fragment func(%main_position_Input:vec4<f32> [@position]):void {
+  $B2: {
+    %5:texture_2d<f32> = load %texture0
+    %6:sampler = load %sampler0
+    %7:vec4<f32> = call %foo, %5, %6
+    ret
+  }
+}
+%foo = func(%t:texture_2d<f32>, %s:sampler):vec4<f32> {
+  $B3: {
+    %11:vec4<f32> = textureSample %t, %s, vec2<f32>(2.0f)
+    ret %11
+  }
+}
+)");
+}
+
 }  // namespace
 }  // namespace tint::spirv::reader