[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