Sampled images as read-only storage (#3295)
There are some cases where a variable that is declared as a sampled
image could be read only. That is when the image type has sampled == 1.
Fixes #3288
diff --git a/source/opt/instruction.cpp b/source/opt/instruction.cpp
index a9d778a..9e54e7e 100644
--- a/source/opt/instruction.cpp
+++ b/source/opt/instruction.cpp
@@ -182,10 +182,27 @@
bool Instruction::IsReadOnlyLoad() const {
if (IsLoad()) {
Instruction* address_def = GetBaseAddress();
- if (!address_def || address_def->opcode() != SpvOpVariable) {
+ if (!address_def) {
return false;
}
- return address_def->IsReadOnlyVariable();
+
+ if (address_def->opcode() == SpvOpVariable) {
+ if (address_def->IsReadOnlyVariable()) {
+ return true;
+ }
+ }
+
+ if (address_def->opcode() == SpvOpLoad) {
+ const analysis::Type* address_type =
+ context()->get_type_mgr()->GetType(address_def->type_id());
+ if (address_type->AsSampledImage() != nullptr) {
+ const auto* image_type =
+ address_type->AsSampledImage()->image_type()->AsImage();
+ if (image_type->sampled() == 1) {
+ return true;
+ }
+ }
+ }
}
return false;
}
diff --git a/test/opt/value_table_test.cpp b/test/opt/value_table_test.cpp
index a0942cc..76e7f73 100644
--- a/test/opt/value_table_test.cpp
+++ b/test/opt/value_table_test.cpp
@@ -684,6 +684,50 @@
vtable.GetValueNumber(inst);
}
+TEST_F(ValueTableTest, RedundantSampledImageLoad) {
+ const std::string text = R"(
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %main "main" %gl_FragColor
+ OpExecutionMode %main OriginLowerLeft
+ OpSource GLSL 330
+ OpName %main "main"
+ OpName %tex0 "tex0"
+ OpName %gl_FragColor "gl_FragColor"
+ OpDecorate %tex0 Location 0
+ OpDecorate %tex0 DescriptorSet 0
+ OpDecorate %tex0 Binding 0
+ OpDecorate %gl_FragColor Location 0
+ %void = OpTypeVoid
+ %6 = OpTypeFunction %void
+ %float = OpTypeFloat 32
+ %v4float = OpTypeVector %float 4
+ %9 = OpTypeImage %float 2D 0 0 0 1 Unknown
+ %10 = OpTypeSampledImage %9
+%_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10
+ %tex0 = OpVariable %_ptr_UniformConstant_10 UniformConstant
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+ %13 = OpConstantNull %v4float
+%gl_FragColor = OpVariable %_ptr_Output_v4float Output
+ %14 = OpUndef %v4float
+ %main = OpFunction %void None %6
+ %15 = OpLabel
+ %16 = OpLoad %10 %tex0
+ %17 = OpImageSampleProjImplicitLod %v4float %16 %13
+ %18 = OpImageSampleProjImplicitLod %v4float %16 %13
+ %19 = OpFAdd %v4float %18 %17
+ OpStore %gl_FragColor %19
+ OpReturn
+ OpFunctionEnd
+ )";
+ auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
+ ValueNumberTable vtable(context.get());
+ Instruction* load1 = context->get_def_use_mgr()->GetDef(17);
+ Instruction* load2 = context->get_def_use_mgr()->GetDef(18);
+ EXPECT_EQ(vtable.GetValueNumber(load1), vtable.GetValueNumber(load2));
+}
+
} // namespace
} // namespace opt
} // namespace spvtools