1fd4e5da5Sopenharmony_ci// Copyright (c) 2021 Google LLC
2fd4e5da5Sopenharmony_ci//
3fd4e5da5Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License");
4fd4e5da5Sopenharmony_ci// you may not use this file except in compliance with the License.
5fd4e5da5Sopenharmony_ci// You may obtain a copy of the License at
6fd4e5da5Sopenharmony_ci//
7fd4e5da5Sopenharmony_ci//     http://www.apache.org/licenses/LICENSE-2.0
8fd4e5da5Sopenharmony_ci//
9fd4e5da5Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software
10fd4e5da5Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS,
11fd4e5da5Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12fd4e5da5Sopenharmony_ci// See the License for the specific language governing permissions and
13fd4e5da5Sopenharmony_ci// limitations under the License.
14fd4e5da5Sopenharmony_ci
15fd4e5da5Sopenharmony_ci#include <vector>
16fd4e5da5Sopenharmony_ci
17fd4e5da5Sopenharmony_ci#include "gmock/gmock.h"
18fd4e5da5Sopenharmony_ci#include "source/opt/convert_to_sampled_image_pass.h"
19fd4e5da5Sopenharmony_ci#include "test/opt/pass_fixture.h"
20fd4e5da5Sopenharmony_ci#include "test/opt/pass_utils.h"
21fd4e5da5Sopenharmony_ci
22fd4e5da5Sopenharmony_cinamespace spvtools {
23fd4e5da5Sopenharmony_cinamespace opt {
24fd4e5da5Sopenharmony_cinamespace {
25fd4e5da5Sopenharmony_ci
26fd4e5da5Sopenharmony_ciusing testing::Eq;
27fd4e5da5Sopenharmony_ciusing VectorOfDescriptorSetAndBindingPairs =
28fd4e5da5Sopenharmony_ci    std::vector<DescriptorSetAndBinding>;
29fd4e5da5Sopenharmony_ci
30fd4e5da5Sopenharmony_cistruct DescriptorSetAndBindingStringParsingTestCase {
31fd4e5da5Sopenharmony_ci  const char* descriptor_set_binding_str;
32fd4e5da5Sopenharmony_ci  bool expect_success;
33fd4e5da5Sopenharmony_ci  VectorOfDescriptorSetAndBindingPairs expected_descriptor_set_binding_pairs;
34fd4e5da5Sopenharmony_ci};
35fd4e5da5Sopenharmony_ci
36fd4e5da5Sopenharmony_ciusing DescriptorSetAndBindingStringParsingTest =
37fd4e5da5Sopenharmony_ci    ::testing::TestWithParam<DescriptorSetAndBindingStringParsingTestCase>;
38fd4e5da5Sopenharmony_ci
39fd4e5da5Sopenharmony_ciTEST_P(DescriptorSetAndBindingStringParsingTest, TestCase) {
40fd4e5da5Sopenharmony_ci  const auto& tc = GetParam();
41fd4e5da5Sopenharmony_ci  auto actual_descriptor_set_binding_pairs =
42fd4e5da5Sopenharmony_ci      ConvertToSampledImagePass::ParseDescriptorSetBindingPairsString(
43fd4e5da5Sopenharmony_ci          tc.descriptor_set_binding_str);
44fd4e5da5Sopenharmony_ci  if (tc.expect_success) {
45fd4e5da5Sopenharmony_ci    EXPECT_NE(nullptr, actual_descriptor_set_binding_pairs);
46fd4e5da5Sopenharmony_ci    if (actual_descriptor_set_binding_pairs) {
47fd4e5da5Sopenharmony_ci      EXPECT_THAT(*actual_descriptor_set_binding_pairs,
48fd4e5da5Sopenharmony_ci                  Eq(tc.expected_descriptor_set_binding_pairs));
49fd4e5da5Sopenharmony_ci    }
50fd4e5da5Sopenharmony_ci  } else {
51fd4e5da5Sopenharmony_ci    EXPECT_EQ(nullptr, actual_descriptor_set_binding_pairs);
52fd4e5da5Sopenharmony_ci  }
53fd4e5da5Sopenharmony_ci}
54fd4e5da5Sopenharmony_ci
55fd4e5da5Sopenharmony_ciINSTANTIATE_TEST_SUITE_P(
56fd4e5da5Sopenharmony_ci    ValidString, DescriptorSetAndBindingStringParsingTest,
57fd4e5da5Sopenharmony_ci    ::testing::ValuesIn(std::vector<
58fd4e5da5Sopenharmony_ci                        DescriptorSetAndBindingStringParsingTestCase>{
59fd4e5da5Sopenharmony_ci        // 0. empty vector
60fd4e5da5Sopenharmony_ci        {"", true, VectorOfDescriptorSetAndBindingPairs({})},
61fd4e5da5Sopenharmony_ci        // 1. one pair
62fd4e5da5Sopenharmony_ci        {"100:1024", true,
63fd4e5da5Sopenharmony_ci         VectorOfDescriptorSetAndBindingPairs({DescriptorSetAndBinding{100,
64fd4e5da5Sopenharmony_ci                                                                       1024}})},
65fd4e5da5Sopenharmony_ci        // 2. two pairs
66fd4e5da5Sopenharmony_ci        {"100:1024 200:2048", true,
67fd4e5da5Sopenharmony_ci         VectorOfDescriptorSetAndBindingPairs(
68fd4e5da5Sopenharmony_ci             {DescriptorSetAndBinding{100, 1024},
69fd4e5da5Sopenharmony_ci              DescriptorSetAndBinding{200, 2048}})},
70fd4e5da5Sopenharmony_ci        // 3. spaces between entries
71fd4e5da5Sopenharmony_ci        {"100:1024 \n \r \t \v \f 200:2048", true,
72fd4e5da5Sopenharmony_ci         VectorOfDescriptorSetAndBindingPairs(
73fd4e5da5Sopenharmony_ci             {DescriptorSetAndBinding{100, 1024},
74fd4e5da5Sopenharmony_ci              DescriptorSetAndBinding{200, 2048}})},
75fd4e5da5Sopenharmony_ci        // 4. \t, \n, \r and spaces before spec id
76fd4e5da5Sopenharmony_ci        {"   \n \r\t \t \v \f 100:1024", true,
77fd4e5da5Sopenharmony_ci         VectorOfDescriptorSetAndBindingPairs({DescriptorSetAndBinding{100,
78fd4e5da5Sopenharmony_ci                                                                       1024}})},
79fd4e5da5Sopenharmony_ci        // 5. \t, \n, \r and spaces after value string
80fd4e5da5Sopenharmony_ci        {"100:1024   \n \r\t \t \v \f ", true,
81fd4e5da5Sopenharmony_ci         VectorOfDescriptorSetAndBindingPairs({DescriptorSetAndBinding{100,
82fd4e5da5Sopenharmony_ci                                                                       1024}})},
83fd4e5da5Sopenharmony_ci        // 6. maximum spec id
84fd4e5da5Sopenharmony_ci        {"4294967295:0", true,
85fd4e5da5Sopenharmony_ci         VectorOfDescriptorSetAndBindingPairs({DescriptorSetAndBinding{
86fd4e5da5Sopenharmony_ci             4294967295, 0}})},
87fd4e5da5Sopenharmony_ci        // 7. minimum spec id
88fd4e5da5Sopenharmony_ci        {"0:100", true,
89fd4e5da5Sopenharmony_ci         VectorOfDescriptorSetAndBindingPairs({DescriptorSetAndBinding{0,
90fd4e5da5Sopenharmony_ci                                                                       100}})},
91fd4e5da5Sopenharmony_ci        // 8. multiple entries
92fd4e5da5Sopenharmony_ci        {"101:1 102:2 103:3 104:4 200:201 9999:1000", true,
93fd4e5da5Sopenharmony_ci         VectorOfDescriptorSetAndBindingPairs(
94fd4e5da5Sopenharmony_ci             {DescriptorSetAndBinding{101, 1}, DescriptorSetAndBinding{102, 2},
95fd4e5da5Sopenharmony_ci              DescriptorSetAndBinding{103, 3}, DescriptorSetAndBinding{104, 4},
96fd4e5da5Sopenharmony_ci              DescriptorSetAndBinding{200, 201},
97fd4e5da5Sopenharmony_ci              DescriptorSetAndBinding{9999, 1000}})},
98fd4e5da5Sopenharmony_ci    }));
99fd4e5da5Sopenharmony_ci
100fd4e5da5Sopenharmony_ciINSTANTIATE_TEST_SUITE_P(
101fd4e5da5Sopenharmony_ci    InvalidString, DescriptorSetAndBindingStringParsingTest,
102fd4e5da5Sopenharmony_ci    ::testing::ValuesIn(
103fd4e5da5Sopenharmony_ci        std::vector<DescriptorSetAndBindingStringParsingTestCase>{
104fd4e5da5Sopenharmony_ci            // 0. missing default value
105fd4e5da5Sopenharmony_ci            {"100:", false, VectorOfDescriptorSetAndBindingPairs{}},
106fd4e5da5Sopenharmony_ci            // 1. descriptor set is not an integer
107fd4e5da5Sopenharmony_ci            {"100.0:200", false, VectorOfDescriptorSetAndBindingPairs{}},
108fd4e5da5Sopenharmony_ci            // 2. descriptor set is not a number
109fd4e5da5Sopenharmony_ci            {"something_not_a_number:1", false,
110fd4e5da5Sopenharmony_ci             VectorOfDescriptorSetAndBindingPairs{}},
111fd4e5da5Sopenharmony_ci            // 3. only descriptor set number
112fd4e5da5Sopenharmony_ci            {"100", false, VectorOfDescriptorSetAndBindingPairs{}},
113fd4e5da5Sopenharmony_ci            // 4. empty descriptor set
114fd4e5da5Sopenharmony_ci            {":3", false, VectorOfDescriptorSetAndBindingPairs{}},
115fd4e5da5Sopenharmony_ci            // 5. only colon
116fd4e5da5Sopenharmony_ci            {":", false, VectorOfDescriptorSetAndBindingPairs{}},
117fd4e5da5Sopenharmony_ci            // 6. descriptor set overflow
118fd4e5da5Sopenharmony_ci            {"4294967296:200", false, VectorOfDescriptorSetAndBindingPairs{}},
119fd4e5da5Sopenharmony_ci            // 7. descriptor set less than 0
120fd4e5da5Sopenharmony_ci            {"-1:200", false, VectorOfDescriptorSetAndBindingPairs{}},
121fd4e5da5Sopenharmony_ci            // 8. nullptr
122fd4e5da5Sopenharmony_ci            {nullptr, false, VectorOfDescriptorSetAndBindingPairs{}},
123fd4e5da5Sopenharmony_ci            // 9. only a number is invalid
124fd4e5da5Sopenharmony_ci            {"1234", false, VectorOfDescriptorSetAndBindingPairs{}},
125fd4e5da5Sopenharmony_ci            // 10. invalid entry separator
126fd4e5da5Sopenharmony_ci            {"12:34;23:14", false, VectorOfDescriptorSetAndBindingPairs{}},
127fd4e5da5Sopenharmony_ci            // 11. invalid descriptor set and default value separator
128fd4e5da5Sopenharmony_ci            {"12@34", false, VectorOfDescriptorSetAndBindingPairs{}},
129fd4e5da5Sopenharmony_ci            // 12. spaces before colon
130fd4e5da5Sopenharmony_ci            {"100   :1024", false, VectorOfDescriptorSetAndBindingPairs{}},
131fd4e5da5Sopenharmony_ci            // 13. spaces after colon
132fd4e5da5Sopenharmony_ci            {"100:   1024", false, VectorOfDescriptorSetAndBindingPairs{}},
133fd4e5da5Sopenharmony_ci            // 14. descriptor set represented in hex float format is invalid
134fd4e5da5Sopenharmony_ci            {"0x3p10:200", false, VectorOfDescriptorSetAndBindingPairs{}},
135fd4e5da5Sopenharmony_ci        }));
136fd4e5da5Sopenharmony_ci
137fd4e5da5Sopenharmony_cistd::string BuildShader(const char* shader_decorate_instructions,
138fd4e5da5Sopenharmony_ci                        const char* shader_image_and_sampler_variables,
139fd4e5da5Sopenharmony_ci                        const char* shader_body) {
140fd4e5da5Sopenharmony_ci  // Base HLSL code:
141fd4e5da5Sopenharmony_ci  //
142fd4e5da5Sopenharmony_ci  // SamplerState sam : register(s2);
143fd4e5da5Sopenharmony_ci  // Texture2D <float4> texture : register(t5);
144fd4e5da5Sopenharmony_ci  //
145fd4e5da5Sopenharmony_ci  // float4 main() : SV_TARGET {
146fd4e5da5Sopenharmony_ci  //     return texture.SampleLevel(sam, float2(1, 2), 10, 2);
147fd4e5da5Sopenharmony_ci  // }
148fd4e5da5Sopenharmony_ci  std::stringstream ss;
149fd4e5da5Sopenharmony_ci  ss << R"(
150fd4e5da5Sopenharmony_ci               OpCapability Shader
151fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
152fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %main "main" %out_var_SV_TARGET
153fd4e5da5Sopenharmony_ci               OpExecutionMode %main OriginUpperLeft
154fd4e5da5Sopenharmony_ci               OpSource HLSL 600
155fd4e5da5Sopenharmony_ci               OpName %type_sampler "type.sampler"
156fd4e5da5Sopenharmony_ci               OpName %type_2d_image "type.2d.image"
157fd4e5da5Sopenharmony_ci               OpName %out_var_SV_TARGET "out.var.SV_TARGET"
158fd4e5da5Sopenharmony_ci               OpName %main "main"
159fd4e5da5Sopenharmony_ci               OpName %type_sampled_image "type.sampled.image"
160fd4e5da5Sopenharmony_ci               OpDecorate %out_var_SV_TARGET Location 0
161fd4e5da5Sopenharmony_ci               )";
162fd4e5da5Sopenharmony_ci  ss << shader_decorate_instructions;
163fd4e5da5Sopenharmony_ci  ss << R"(
164fd4e5da5Sopenharmony_ci      %float = OpTypeFloat 32
165fd4e5da5Sopenharmony_ci    %float_1 = OpConstant %float 1
166fd4e5da5Sopenharmony_ci    %float_2 = OpConstant %float 2
167fd4e5da5Sopenharmony_ci    %v2float = OpTypeVector %float 2
168fd4e5da5Sopenharmony_ci         %12 = OpConstantComposite %v2float %float_1 %float_2
169fd4e5da5Sopenharmony_ci   %float_10 = OpConstant %float 10
170fd4e5da5Sopenharmony_ci        %int = OpTypeInt 32 1
171fd4e5da5Sopenharmony_ci      %int_2 = OpConstant %int 2
172fd4e5da5Sopenharmony_ci      %v2int = OpTypeVector %int 2
173fd4e5da5Sopenharmony_ci         %17 = OpConstantComposite %v2int %int_2 %int_2
174fd4e5da5Sopenharmony_ci%type_sampler = OpTypeSampler
175fd4e5da5Sopenharmony_ci%_ptr_UniformConstant_type_sampler = OpTypePointer UniformConstant %type_sampler
176fd4e5da5Sopenharmony_ci%type_2d_image = OpTypeImage %float 2D 2 0 0 1 Unknown
177fd4e5da5Sopenharmony_ci%_ptr_UniformConstant_type_2d_image = OpTypePointer UniformConstant %type_2d_image
178fd4e5da5Sopenharmony_ci    %v4float = OpTypeVector %float 4
179fd4e5da5Sopenharmony_ci%_ptr_Output_v4float = OpTypePointer Output %v4float
180fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
181fd4e5da5Sopenharmony_ci         %23 = OpTypeFunction %void
182fd4e5da5Sopenharmony_ci%type_sampled_image = OpTypeSampledImage %type_2d_image
183fd4e5da5Sopenharmony_ci               )";
184fd4e5da5Sopenharmony_ci  ss << shader_image_and_sampler_variables;
185fd4e5da5Sopenharmony_ci  ss << R"(
186fd4e5da5Sopenharmony_ci%out_var_SV_TARGET = OpVariable %_ptr_Output_v4float Output
187fd4e5da5Sopenharmony_ci       %main = OpFunction %void None %23
188fd4e5da5Sopenharmony_ci         %24 = OpLabel
189fd4e5da5Sopenharmony_ci  )";
190fd4e5da5Sopenharmony_ci  ss << shader_body;
191fd4e5da5Sopenharmony_ci  ss << R"(
192fd4e5da5Sopenharmony_ci               OpReturn
193fd4e5da5Sopenharmony_ci               OpFunctionEnd
194fd4e5da5Sopenharmony_ci  )";
195fd4e5da5Sopenharmony_ci  return ss.str();
196fd4e5da5Sopenharmony_ci}
197fd4e5da5Sopenharmony_ci
198fd4e5da5Sopenharmony_ciusing ConvertToSampledImageTest = PassTest<::testing::Test>;
199fd4e5da5Sopenharmony_ci
200fd4e5da5Sopenharmony_ciTEST_F(ConvertToSampledImageTest, Texture2DAndSamplerToSampledImage) {
201fd4e5da5Sopenharmony_ci  const std::string shader = BuildShader(
202fd4e5da5Sopenharmony_ci      R"(
203fd4e5da5Sopenharmony_ci               OpDecorate %sam DescriptorSet 0
204fd4e5da5Sopenharmony_ci               OpDecorate %sam Binding 5
205fd4e5da5Sopenharmony_ci               OpDecorate %texture DescriptorSet 0
206fd4e5da5Sopenharmony_ci               OpDecorate %texture Binding 5
207fd4e5da5Sopenharmony_ci               )",
208fd4e5da5Sopenharmony_ci      R"(
209fd4e5da5Sopenharmony_ci            ; CHECK-NOT: OpVariable %_ptr_UniformConstant_type_2d_image
210fd4e5da5Sopenharmony_ci
211fd4e5da5Sopenharmony_ci            ; CHECK: [[tex:%\w+]] = OpVariable %_ptr_UniformConstant_type_sampled_image UniformConstant
212fd4e5da5Sopenharmony_ci        %sam = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant
213fd4e5da5Sopenharmony_ci    %texture = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
214fd4e5da5Sopenharmony_ci               )",
215fd4e5da5Sopenharmony_ci      R"(
216fd4e5da5Sopenharmony_ci            ; CHECK: [[load:%\w+]] = OpLoad %type_sampled_image [[tex]]
217fd4e5da5Sopenharmony_ci            ; CHECK: OpImageSampleExplicitLod %v4float [[load]]
218fd4e5da5Sopenharmony_ci         %25 = OpLoad %type_2d_image %texture
219fd4e5da5Sopenharmony_ci         %26 = OpLoad %type_sampler %sam
220fd4e5da5Sopenharmony_ci         %27 = OpSampledImage %type_sampled_image %25 %26
221fd4e5da5Sopenharmony_ci         %28 = OpImageSampleExplicitLod %v4float %27 %12 Lod|ConstOffset %float_10 %17
222fd4e5da5Sopenharmony_ci               OpStore %out_var_SV_TARGET %28
223fd4e5da5Sopenharmony_ci               )");
224fd4e5da5Sopenharmony_ci
225fd4e5da5Sopenharmony_ci  auto result = SinglePassRunAndMatch<ConvertToSampledImagePass>(
226fd4e5da5Sopenharmony_ci      shader, /* do_validate = */ true,
227fd4e5da5Sopenharmony_ci      VectorOfDescriptorSetAndBindingPairs{DescriptorSetAndBinding{0, 5}});
228fd4e5da5Sopenharmony_ci
229fd4e5da5Sopenharmony_ci  EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange);
230fd4e5da5Sopenharmony_ci}
231fd4e5da5Sopenharmony_ci
232fd4e5da5Sopenharmony_ciTEST_F(ConvertToSampledImageTest, Texture2DToSampledImage) {
233fd4e5da5Sopenharmony_ci  const std::string shader = BuildShader(
234fd4e5da5Sopenharmony_ci      R"(
235fd4e5da5Sopenharmony_ci               OpDecorate %sam DescriptorSet 0
236fd4e5da5Sopenharmony_ci               OpDecorate %sam Binding 2
237fd4e5da5Sopenharmony_ci               OpDecorate %texture DescriptorSet 0
238fd4e5da5Sopenharmony_ci               OpDecorate %texture Binding 5
239fd4e5da5Sopenharmony_ci               )",
240fd4e5da5Sopenharmony_ci      R"(
241fd4e5da5Sopenharmony_ci            ; CHECK: [[tex:%\w+]] = OpVariable %_ptr_UniformConstant_type_sampled_image UniformConstant
242fd4e5da5Sopenharmony_ci        %sam = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant
243fd4e5da5Sopenharmony_ci    %texture = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
244fd4e5da5Sopenharmony_ci               )",
245fd4e5da5Sopenharmony_ci      R"(
246fd4e5da5Sopenharmony_ci            ; CHECK: [[load:%\w+]] = OpLoad %type_sampled_image [[tex]]
247fd4e5da5Sopenharmony_ci            ; CHECK: [[image_extraction:%\w+]] = OpImage %type_2d_image [[load]]
248fd4e5da5Sopenharmony_ci            ; CHECK: OpSampledImage %type_sampled_image [[image_extraction]]
249fd4e5da5Sopenharmony_ci         %25 = OpLoad %type_2d_image %texture
250fd4e5da5Sopenharmony_ci         %26 = OpLoad %type_sampler %sam
251fd4e5da5Sopenharmony_ci         %27 = OpSampledImage %type_sampled_image %25 %26
252fd4e5da5Sopenharmony_ci         %28 = OpImageSampleExplicitLod %v4float %27 %12 Lod|ConstOffset %float_10 %17
253fd4e5da5Sopenharmony_ci               OpStore %out_var_SV_TARGET %28
254fd4e5da5Sopenharmony_ci               )");
255fd4e5da5Sopenharmony_ci
256fd4e5da5Sopenharmony_ci  auto result = SinglePassRunAndMatch<ConvertToSampledImagePass>(
257fd4e5da5Sopenharmony_ci      shader, /* do_validate = */ true,
258fd4e5da5Sopenharmony_ci      VectorOfDescriptorSetAndBindingPairs{DescriptorSetAndBinding{0, 5}});
259fd4e5da5Sopenharmony_ci
260fd4e5da5Sopenharmony_ci  EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange);
261fd4e5da5Sopenharmony_ci}
262fd4e5da5Sopenharmony_ci
263fd4e5da5Sopenharmony_ciTEST_F(ConvertToSampledImageTest, SamplerToSampledImage) {
264fd4e5da5Sopenharmony_ci  const std::string shader = BuildShader(
265fd4e5da5Sopenharmony_ci      R"(
266fd4e5da5Sopenharmony_ci               OpDecorate %sam DescriptorSet 0
267fd4e5da5Sopenharmony_ci               OpDecorate %sam Binding 2
268fd4e5da5Sopenharmony_ci               OpDecorate %texture DescriptorSet 0
269fd4e5da5Sopenharmony_ci               OpDecorate %texture Binding 5
270fd4e5da5Sopenharmony_ci               )",
271fd4e5da5Sopenharmony_ci      R"(
272fd4e5da5Sopenharmony_ci        %sam = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant
273fd4e5da5Sopenharmony_ci    %texture = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
274fd4e5da5Sopenharmony_ci               )",
275fd4e5da5Sopenharmony_ci      R"(
276fd4e5da5Sopenharmony_ci         %25 = OpLoad %type_2d_image %texture
277fd4e5da5Sopenharmony_ci         %26 = OpLoad %type_sampler %sam
278fd4e5da5Sopenharmony_ci         %27 = OpSampledImage %type_sampled_image %25 %26
279fd4e5da5Sopenharmony_ci         %28 = OpImageSampleExplicitLod %v4float %27 %12 Lod|ConstOffset %float_10 %17
280fd4e5da5Sopenharmony_ci               OpStore %out_var_SV_TARGET %28
281fd4e5da5Sopenharmony_ci               )");
282fd4e5da5Sopenharmony_ci
283fd4e5da5Sopenharmony_ci  auto result = SinglePassRunToBinary<ConvertToSampledImagePass>(
284fd4e5da5Sopenharmony_ci      shader, /* skip_nop = */ false,
285fd4e5da5Sopenharmony_ci      VectorOfDescriptorSetAndBindingPairs{DescriptorSetAndBinding{0, 2}});
286fd4e5da5Sopenharmony_ci
287fd4e5da5Sopenharmony_ci  EXPECT_EQ(std::get<1>(result), Pass::Status::Failure);
288fd4e5da5Sopenharmony_ci}
289fd4e5da5Sopenharmony_ci
290fd4e5da5Sopenharmony_ciTEST_F(ConvertToSampledImageTest, TwoImagesWithDuplicatedDescriptorSetBinding) {
291fd4e5da5Sopenharmony_ci  const std::string shader = BuildShader(
292fd4e5da5Sopenharmony_ci      R"(
293fd4e5da5Sopenharmony_ci               OpDecorate %sam DescriptorSet 0
294fd4e5da5Sopenharmony_ci               OpDecorate %sam Binding 2
295fd4e5da5Sopenharmony_ci               OpDecorate %texture0 DescriptorSet 0
296fd4e5da5Sopenharmony_ci               OpDecorate %texture0 Binding 5
297fd4e5da5Sopenharmony_ci               OpDecorate %texture1 DescriptorSet 0
298fd4e5da5Sopenharmony_ci               OpDecorate %texture1 Binding 5
299fd4e5da5Sopenharmony_ci               )",
300fd4e5da5Sopenharmony_ci      R"(
301fd4e5da5Sopenharmony_ci        %sam = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant
302fd4e5da5Sopenharmony_ci   %texture0 = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
303fd4e5da5Sopenharmony_ci   %texture1 = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
304fd4e5da5Sopenharmony_ci               )",
305fd4e5da5Sopenharmony_ci      R"(
306fd4e5da5Sopenharmony_ci         %25 = OpLoad %type_2d_image %texture0
307fd4e5da5Sopenharmony_ci         %26 = OpLoad %type_sampler %sam
308fd4e5da5Sopenharmony_ci         %27 = OpSampledImage %type_sampled_image %25 %26
309fd4e5da5Sopenharmony_ci         %28 = OpImageSampleExplicitLod %v4float %27 %12 Lod|ConstOffset %float_10 %17
310fd4e5da5Sopenharmony_ci               OpStore %out_var_SV_TARGET %28
311fd4e5da5Sopenharmony_ci               )");
312fd4e5da5Sopenharmony_ci
313fd4e5da5Sopenharmony_ci  auto result = SinglePassRunToBinary<ConvertToSampledImagePass>(
314fd4e5da5Sopenharmony_ci      shader, /* skip_nop = */ false,
315fd4e5da5Sopenharmony_ci      VectorOfDescriptorSetAndBindingPairs{DescriptorSetAndBinding{0, 5}});
316fd4e5da5Sopenharmony_ci
317fd4e5da5Sopenharmony_ci  EXPECT_EQ(std::get<1>(result), Pass::Status::Failure);
318fd4e5da5Sopenharmony_ci}
319fd4e5da5Sopenharmony_ci
320fd4e5da5Sopenharmony_ciTEST_F(ConvertToSampledImageTest,
321fd4e5da5Sopenharmony_ci       TwoSamplersWithDuplicatedDescriptorSetBinding) {
322fd4e5da5Sopenharmony_ci  const std::string shader = BuildShader(
323fd4e5da5Sopenharmony_ci      R"(
324fd4e5da5Sopenharmony_ci               OpDecorate %sam0 DescriptorSet 0
325fd4e5da5Sopenharmony_ci               OpDecorate %sam0 Binding 2
326fd4e5da5Sopenharmony_ci               OpDecorate %sam1 DescriptorSet 0
327fd4e5da5Sopenharmony_ci               OpDecorate %sam1 Binding 2
328fd4e5da5Sopenharmony_ci               OpDecorate %texture DescriptorSet 0
329fd4e5da5Sopenharmony_ci               OpDecorate %texture Binding 5
330fd4e5da5Sopenharmony_ci               )",
331fd4e5da5Sopenharmony_ci      R"(
332fd4e5da5Sopenharmony_ci       %sam0 = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant
333fd4e5da5Sopenharmony_ci       %sam1 = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant
334fd4e5da5Sopenharmony_ci    %texture = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
335fd4e5da5Sopenharmony_ci               )",
336fd4e5da5Sopenharmony_ci      R"(
337fd4e5da5Sopenharmony_ci         %25 = OpLoad %type_2d_image %texture
338fd4e5da5Sopenharmony_ci         %26 = OpLoad %type_sampler %sam0
339fd4e5da5Sopenharmony_ci         %27 = OpSampledImage %type_sampled_image %25 %26
340fd4e5da5Sopenharmony_ci         %28 = OpImageSampleExplicitLod %v4float %27 %12 Lod|ConstOffset %float_10 %17
341fd4e5da5Sopenharmony_ci               OpStore %out_var_SV_TARGET %28
342fd4e5da5Sopenharmony_ci               )");
343fd4e5da5Sopenharmony_ci
344fd4e5da5Sopenharmony_ci  auto result = SinglePassRunToBinary<ConvertToSampledImagePass>(
345fd4e5da5Sopenharmony_ci      shader, /* skip_nop = */ false,
346fd4e5da5Sopenharmony_ci      VectorOfDescriptorSetAndBindingPairs{DescriptorSetAndBinding{0, 2}});
347fd4e5da5Sopenharmony_ci
348fd4e5da5Sopenharmony_ci  EXPECT_EQ(std::get<1>(result), Pass::Status::Failure);
349fd4e5da5Sopenharmony_ci}
350fd4e5da5Sopenharmony_ci
351fd4e5da5Sopenharmony_ci}  // namespace
352fd4e5da5Sopenharmony_ci}  // namespace opt
353fd4e5da5Sopenharmony_ci}  // namespace spvtools
354