1 // Copyright (c) 2017 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <cstdarg>
16 #include <string>
17 #include <vector>
18 
19 #include "gmock/gmock.h"
20 #include "pass_utils.h"
21 #include "test/opt/assembly_builder.h"
22 #include "test/opt/pass_fixture.h"
23 
24 namespace spvtools {
25 namespace opt {
26 namespace {
27 
28 using ReplaceInvalidOpcodeTest = PassTest<::testing::Test>;
29 
TEST_F(ReplaceInvalidOpcodeTest,ReplaceInstruction)30 TEST_F(ReplaceInvalidOpcodeTest, ReplaceInstruction) {
31   const std::string text = R"(
32 ; CHECK: [[special_const:%\w+]] = OpConstant %float -6.2598534e+18
33 ; CHECK: [[constant:%\w+]] = OpConstantComposite %v4float [[special_const]] [[special_const]] [[special_const]] [[special_const]]
34 ; CHECK-NOT: OpImageSampleImplicitLod
35 ; CHECK: OpStore [[:%\w+]] [[constant]]
36                 OpCapability Shader
37           %1 = OpExtInstImport "GLSL.std.450"
38                OpMemoryModel Logical GLSL450
39                OpEntryPoint Vertex %main "main" %3 %gl_VertexIndex %5
40                OpSource GLSL 400
41                OpSourceExtension "GL_ARB_separate_shader_objects"
42                OpSourceExtension "GL_ARB_shading_language_420pack"
43                OpName %main "main"
44                OpDecorate %3 Location 0
45                OpDecorate %gl_VertexIndex BuiltIn VertexIndex
46                OpMemberDecorate %_struct_6 0 BuiltIn Position
47                OpDecorate %_struct_6 Block
48        %void = OpTypeVoid
49           %8 = OpTypeFunction %void
50       %float = OpTypeFloat 32
51          %10 = OpTypeImage %float 2D 0 0 0 1 Unknown
52 %_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10
53          %12 = OpTypeSampler
54 %_ptr_UniformConstant_12 = OpTypePointer UniformConstant %12
55          %14 = OpTypeSampledImage %10
56     %v4float = OpTypeVector %float 4
57     %v2float = OpTypeVector %float 2
58 %_ptr_Output_v4float = OpTypePointer Output %v4float
59           %3 = OpVariable %_ptr_Output_v4float Output
60         %int = OpTypeInt 32 1
61 %_ptr_Input_int = OpTypePointer Input %int
62 %gl_VertexIndex = OpVariable %_ptr_Input_int Input
63   %_struct_6 = OpTypeStruct %v4float
64 %_ptr_Output__struct_6 = OpTypePointer Output %_struct_6
65           %5 = OpVariable %_ptr_Output__struct_6 Output
66       %int_0 = OpConstant %int 0
67     %float_0 = OpConstant %float 0
68          %23 = OpConstantComposite %v2float %float_0 %float_0
69          %24 = OpVariable %_ptr_UniformConstant_10 UniformConstant
70          %25 = OpVariable %_ptr_UniformConstant_12 UniformConstant
71        %main = OpFunction %void None %8
72          %26 = OpLabel
73          %27 = OpLoad %12 %25
74          %28 = OpLoad %10 %24
75          %29 = OpSampledImage %14 %28 %27
76          %30 = OpImageSampleImplicitLod %v4float %29 %23
77          %31 = OpAccessChain %_ptr_Output_v4float %5 %int_0
78                OpStore %31 %30
79                OpReturn
80                OpFunctionEnd)";
81 
82   SinglePassRunAndMatch<ReplaceInvalidOpcodePass>(text, false);
83 }
84 
TEST_F(ReplaceInvalidOpcodeTest,ReplaceInstructionInNonEntryPoint)85 TEST_F(ReplaceInvalidOpcodeTest, ReplaceInstructionInNonEntryPoint) {
86   const std::string text = R"(
87 ; CHECK: [[special_const:%\w+]] = OpConstant %float -6.2598534e+18
88 ; CHECK: [[constant:%\w+]] = OpConstantComposite %v4float [[special_const]] [[special_const]] [[special_const]] [[special_const]]
89 ; CHECK-NOT: OpImageSampleImplicitLod
90 ; CHECK: OpStore [[:%\w+]] [[constant]]
91                OpCapability Shader
92           %1 = OpExtInstImport "GLSL.std.450"
93                OpMemoryModel Logical GLSL450
94                OpEntryPoint Vertex %main "main" %3 %gl_VertexIndex %5
95                OpSource GLSL 400
96                OpSourceExtension "GL_ARB_separate_shader_objects"
97                OpSourceExtension "GL_ARB_shading_language_420pack"
98                OpName %main "main"
99                OpDecorate %3 Location 0
100                OpDecorate %gl_VertexIndex BuiltIn VertexIndex
101                OpMemberDecorate %_struct_6 0 BuiltIn Position
102                OpDecorate %_struct_6 Block
103        %void = OpTypeVoid
104           %8 = OpTypeFunction %void
105       %float = OpTypeFloat 32
106          %10 = OpTypeImage %float 2D 0 0 0 1 Unknown
107 %_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10
108          %12 = OpTypeSampler
109 %_ptr_UniformConstant_12 = OpTypePointer UniformConstant %12
110          %14 = OpTypeSampledImage %10
111     %v4float = OpTypeVector %float 4
112     %v2float = OpTypeVector %float 2
113 %_ptr_Output_v4float = OpTypePointer Output %v4float
114           %3 = OpVariable %_ptr_Output_v4float Output
115         %int = OpTypeInt 32 1
116 %_ptr_Input_int = OpTypePointer Input %int
117 %gl_VertexIndex = OpVariable %_ptr_Input_int Input
118   %_struct_6 = OpTypeStruct %v4float
119 %_ptr_Output__struct_6 = OpTypePointer Output %_struct_6
120           %5 = OpVariable %_ptr_Output__struct_6 Output
121       %int_0 = OpConstant %int 0
122     %float_0 = OpConstant %float 0
123          %23 = OpConstantComposite %v2float %float_0 %float_0
124          %24 = OpVariable %_ptr_UniformConstant_10 UniformConstant
125          %25 = OpVariable %_ptr_UniformConstant_12 UniformConstant
126        %main = OpFunction %void None %8
127          %26 = OpLabel
128          %27 = OpFunctionCall %void %28
129                OpReturn
130                OpFunctionEnd
131          %28 = OpFunction %void None %8
132          %29 = OpLabel
133          %30 = OpLoad %12 %25
134          %31 = OpLoad %10 %24
135          %32 = OpSampledImage %14 %31 %30
136          %33 = OpImageSampleImplicitLod %v4float %32 %23
137          %34 = OpAccessChain %_ptr_Output_v4float %5 %int_0
138                OpStore %34 %33
139                OpReturn
140                OpFunctionEnd)";
141 
142   SinglePassRunAndMatch<ReplaceInvalidOpcodePass>(text, false);
143 }
144 
TEST_F(ReplaceInvalidOpcodeTest,ReplaceInstructionMultipleEntryPoints)145 TEST_F(ReplaceInvalidOpcodeTest, ReplaceInstructionMultipleEntryPoints) {
146   const std::string text = R"(
147 ; CHECK: [[special_const:%\w+]] = OpConstant %float -6.2598534e+18
148 ; CHECK: [[constant:%\w+]] = OpConstantComposite %v4float [[special_const]] [[special_const]] [[special_const]] [[special_const]]
149 ; CHECK-NOT: OpImageSampleImplicitLod
150 ; CHECK: OpStore [[:%\w+]] [[constant]]
151 ; CHECK-NOT: OpImageSampleImplicitLod
152 ; CHECK: OpStore [[:%\w+]] [[constant]]
153                 OpCapability Shader
154           %1 = OpExtInstImport "GLSL.std.450"
155                OpMemoryModel Logical GLSL450
156                OpEntryPoint Vertex %main "main" %3 %gl_VertexIndex %5
157                OpEntryPoint Vertex %main2 "main2" %3 %gl_VertexIndex %5
158                OpSource GLSL 400
159                OpSourceExtension "GL_ARB_separate_shader_objects"
160                OpSourceExtension "GL_ARB_shading_language_420pack"
161                OpName %main "main"
162                OpName %main2 "main2"
163                OpDecorate %3 Location 0
164                OpDecorate %gl_VertexIndex BuiltIn VertexIndex
165                OpMemberDecorate %_struct_6 0 BuiltIn Position
166                OpDecorate %_struct_6 Block
167        %void = OpTypeVoid
168           %8 = OpTypeFunction %void
169       %float = OpTypeFloat 32
170          %10 = OpTypeImage %float 2D 0 0 0 1 Unknown
171 %_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10
172          %12 = OpTypeSampler
173 %_ptr_UniformConstant_12 = OpTypePointer UniformConstant %12
174          %14 = OpTypeSampledImage %10
175     %v4float = OpTypeVector %float 4
176     %v2float = OpTypeVector %float 2
177 %_ptr_Output_v4float = OpTypePointer Output %v4float
178           %3 = OpVariable %_ptr_Output_v4float Output
179         %int = OpTypeInt 32 1
180 %_ptr_Input_int = OpTypePointer Input %int
181 %gl_VertexIndex = OpVariable %_ptr_Input_int Input
182   %_struct_6 = OpTypeStruct %v4float
183 %_ptr_Output__struct_6 = OpTypePointer Output %_struct_6
184           %5 = OpVariable %_ptr_Output__struct_6 Output
185       %int_0 = OpConstant %int 0
186     %float_0 = OpConstant %float 0
187          %23 = OpConstantComposite %v2float %float_0 %float_0
188          %24 = OpVariable %_ptr_UniformConstant_10 UniformConstant
189          %25 = OpVariable %_ptr_UniformConstant_12 UniformConstant
190        %main = OpFunction %void None %8
191          %26 = OpLabel
192          %27 = OpLoad %12 %25
193          %28 = OpLoad %10 %24
194          %29 = OpSampledImage %14 %28 %27
195          %30 = OpImageSampleImplicitLod %v4float %29 %23
196          %31 = OpAccessChain %_ptr_Output_v4float %5 %int_0
197                OpStore %31 %30
198                OpReturn
199                OpFunctionEnd
200       %main2 = OpFunction %void None %8
201          %46 = OpLabel
202          %47 = OpLoad %12 %25
203          %48 = OpLoad %10 %24
204          %49 = OpSampledImage %14 %48 %47
205          %50 = OpImageSampleImplicitLod %v4float %49 %23
206          %51 = OpAccessChain %_ptr_Output_v4float %5 %int_0
207                OpStore %51 %50
208                OpReturn
209                OpFunctionEnd)";
210 
211   SinglePassRunAndMatch<ReplaceInvalidOpcodePass>(text, false);
212 }
TEST_F(ReplaceInvalidOpcodeTest,DontReplaceInstruction)213 TEST_F(ReplaceInvalidOpcodeTest, DontReplaceInstruction) {
214   const std::string text = R"(
215                 OpCapability Shader
216           %1 = OpExtInstImport "GLSL.std.450"
217                OpMemoryModel Logical GLSL450
218                OpEntryPoint Fragment %main "main" %3 %gl_VertexIndex %5
219                OpSource GLSL 400
220                OpSourceExtension "GL_ARB_separate_shader_objects"
221                OpSourceExtension "GL_ARB_shading_language_420pack"
222                OpName %main "main"
223                OpDecorate %3 Location 0
224                OpDecorate %gl_VertexIndex BuiltIn VertexIndex
225                OpMemberDecorate %_struct_6 0 BuiltIn Position
226                OpDecorate %_struct_6 Block
227        %void = OpTypeVoid
228           %8 = OpTypeFunction %void
229       %float = OpTypeFloat 32
230          %10 = OpTypeImage %float 2D 0 0 0 1 Unknown
231 %_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10
232          %12 = OpTypeSampler
233 %_ptr_UniformConstant_12 = OpTypePointer UniformConstant %12
234          %14 = OpTypeSampledImage %10
235     %v4float = OpTypeVector %float 4
236     %v2float = OpTypeVector %float 2
237 %_ptr_Output_v4float = OpTypePointer Output %v4float
238           %3 = OpVariable %_ptr_Output_v4float Output
239         %int = OpTypeInt 32 1
240 %_ptr_Input_int = OpTypePointer Input %int
241 %gl_VertexIndex = OpVariable %_ptr_Input_int Input
242   %_struct_6 = OpTypeStruct %v4float
243 %_ptr_Output__struct_6 = OpTypePointer Output %_struct_6
244           %5 = OpVariable %_ptr_Output__struct_6 Output
245       %int_0 = OpConstant %int 0
246     %float_0 = OpConstant %float 0
247          %23 = OpConstantComposite %v2float %float_0 %float_0
248          %24 = OpVariable %_ptr_UniformConstant_10 UniformConstant
249          %25 = OpVariable %_ptr_UniformConstant_12 UniformConstant
250        %main = OpFunction %void None %8
251          %26 = OpLabel
252          %27 = OpLoad %12 %25
253          %28 = OpLoad %10 %24
254          %29 = OpSampledImage %14 %28 %27
255          %30 = OpImageSampleImplicitLod %v4float %29 %23
256          %31 = OpAccessChain %_ptr_Output_v4float %5 %int_0
257                OpStore %31 %30
258                OpReturn
259                OpFunctionEnd)";
260 
261   auto result = SinglePassRunAndDisassemble<ReplaceInvalidOpcodePass>(
262       text, /* skip_nop = */ true, /* do_validation = */ false);
263   EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
264 }
265 
TEST_F(ReplaceInvalidOpcodeTest,MultipleEntryPointsDifferentStage)266 TEST_F(ReplaceInvalidOpcodeTest, MultipleEntryPointsDifferentStage) {
267   const std::string text = R"(
268                 OpCapability Shader
269           %1 = OpExtInstImport "GLSL.std.450"
270                OpMemoryModel Logical GLSL450
271                OpEntryPoint Vertex %main "main" %3 %gl_VertexIndex %5
272                OpEntryPoint Fragment %main2 "main2" %3 %gl_VertexIndex %5
273                OpSource GLSL 400
274                OpSourceExtension "GL_ARB_separate_shader_objects"
275                OpSourceExtension "GL_ARB_shading_language_420pack"
276                OpName %main "main"
277                OpName %main2 "main2"
278                OpDecorate %3 Location 0
279                OpDecorate %gl_VertexIndex BuiltIn VertexIndex
280                OpMemberDecorate %_struct_6 0 BuiltIn Position
281                OpDecorate %_struct_6 Block
282        %void = OpTypeVoid
283           %8 = OpTypeFunction %void
284       %float = OpTypeFloat 32
285          %10 = OpTypeImage %float 2D 0 0 0 1 Unknown
286 %_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10
287          %12 = OpTypeSampler
288 %_ptr_UniformConstant_12 = OpTypePointer UniformConstant %12
289          %14 = OpTypeSampledImage %10
290     %v4float = OpTypeVector %float 4
291     %v2float = OpTypeVector %float 2
292 %_ptr_Output_v4float = OpTypePointer Output %v4float
293           %3 = OpVariable %_ptr_Output_v4float Output
294         %int = OpTypeInt 32 1
295 %_ptr_Input_int = OpTypePointer Input %int
296 %gl_VertexIndex = OpVariable %_ptr_Input_int Input
297   %_struct_6 = OpTypeStruct %v4float
298 %_ptr_Output__struct_6 = OpTypePointer Output %_struct_6
299           %5 = OpVariable %_ptr_Output__struct_6 Output
300       %int_0 = OpConstant %int 0
301     %float_0 = OpConstant %float 0
302          %23 = OpConstantComposite %v2float %float_0 %float_0
303          %24 = OpVariable %_ptr_UniformConstant_10 UniformConstant
304          %25 = OpVariable %_ptr_UniformConstant_12 UniformConstant
305        %main = OpFunction %void None %8
306          %26 = OpLabel
307          %27 = OpLoad %12 %25
308          %28 = OpLoad %10 %24
309          %29 = OpSampledImage %14 %28 %27
310          %30 = OpImageSampleImplicitLod %v4float %29 %23
311          %31 = OpAccessChain %_ptr_Output_v4float %5 %int_0
312                OpStore %31 %30
313                OpReturn
314                OpFunctionEnd
315       %main2 = OpFunction %void None %8
316          %46 = OpLabel
317          %47 = OpLoad %12 %25
318          %48 = OpLoad %10 %24
319          %49 = OpSampledImage %14 %48 %47
320          %50 = OpImageSampleImplicitLod %v4float %49 %23
321          %51 = OpAccessChain %_ptr_Output_v4float %5 %int_0
322                OpStore %51 %50
323                OpReturn
324                OpFunctionEnd)";
325 
326   auto result = SinglePassRunAndDisassemble<ReplaceInvalidOpcodePass>(
327       text, /* skip_nop = */ true, /* do_validation = */ false);
328   EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
329 }
330 
TEST_F(ReplaceInvalidOpcodeTest,DontReplaceLinkage)331 TEST_F(ReplaceInvalidOpcodeTest, DontReplaceLinkage) {
332   const std::string text = R"(
333                 OpCapability Shader
334                 OpCapability Linkage
335           %1 = OpExtInstImport "GLSL.std.450"
336                OpMemoryModel Logical GLSL450
337                OpEntryPoint Vertex %main "main" %3 %gl_VertexIndex %5
338                OpSource GLSL 400
339                OpSourceExtension "GL_ARB_separate_shader_objects"
340                OpSourceExtension "GL_ARB_shading_language_420pack"
341                OpName %main "main"
342                OpDecorate %3 Location 0
343                OpDecorate %gl_VertexIndex BuiltIn VertexIndex
344                OpMemberDecorate %_struct_6 0 BuiltIn Position
345                OpDecorate %_struct_6 Block
346        %void = OpTypeVoid
347           %8 = OpTypeFunction %void
348       %float = OpTypeFloat 32
349          %10 = OpTypeImage %float 2D 0 0 0 1 Unknown
350 %_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10
351          %12 = OpTypeSampler
352 %_ptr_UniformConstant_12 = OpTypePointer UniformConstant %12
353          %14 = OpTypeSampledImage %10
354     %v4float = OpTypeVector %float 4
355     %v2float = OpTypeVector %float 2
356 %_ptr_Output_v4float = OpTypePointer Output %v4float
357           %3 = OpVariable %_ptr_Output_v4float Output
358         %int = OpTypeInt 32 1
359 %_ptr_Input_int = OpTypePointer Input %int
360 %gl_VertexIndex = OpVariable %_ptr_Input_int Input
361   %_struct_6 = OpTypeStruct %v4float
362 %_ptr_Output__struct_6 = OpTypePointer Output %_struct_6
363           %5 = OpVariable %_ptr_Output__struct_6 Output
364       %int_0 = OpConstant %int 0
365     %float_0 = OpConstant %float 0
366          %23 = OpConstantComposite %v2float %float_0 %float_0
367          %24 = OpVariable %_ptr_UniformConstant_10 UniformConstant
368          %25 = OpVariable %_ptr_UniformConstant_12 UniformConstant
369        %main = OpFunction %void None %8
370          %26 = OpLabel
371          %27 = OpLoad %12 %25
372          %28 = OpLoad %10 %24
373          %29 = OpSampledImage %14 %28 %27
374          %30 = OpImageSampleImplicitLod %v4float %29 %23
375          %31 = OpAccessChain %_ptr_Output_v4float %5 %int_0
376                OpStore %31 %30
377                OpReturn
378                OpFunctionEnd)";
379 
380   auto result = SinglePassRunAndDisassemble<ReplaceInvalidOpcodePass>(
381       text, /* skip_nop = */ true, /* do_validation = */ false);
382   EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
383 }
384 
TEST_F(ReplaceInvalidOpcodeTest,BarrierDontReplace)385 TEST_F(ReplaceInvalidOpcodeTest, BarrierDontReplace) {
386   const std::string text = R"(
387             OpCapability Shader
388        %1 = OpExtInstImport "GLSL.std.450"
389             OpMemoryModel Logical GLSL450
390             OpEntryPoint GLCompute %main "main"
391             OpExecutionMode %main LocalSize 1 1 1
392             OpSource GLSL 450
393             OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
394             OpSourceExtension "GL_GOOGLE_include_directive"
395             OpName %main "main"
396     %void = OpTypeVoid
397        %3 = OpTypeFunction %void
398     %uint = OpTypeInt 32 0
399   %uint_2 = OpConstant %uint 2
400 %uint_264 = OpConstant %uint 264
401     %main = OpFunction %void None %3
402        %5 = OpLabel
403             OpControlBarrier %uint_2 %uint_2 %uint_264
404             OpReturn
405             OpFunctionEnd)";
406 
407   auto result = SinglePassRunAndDisassemble<ReplaceInvalidOpcodePass>(
408       text, /* skip_nop = */ true, /* do_validation = */ false);
409   EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
410 }
411 
TEST_F(ReplaceInvalidOpcodeTest,BarrierReplace)412 TEST_F(ReplaceInvalidOpcodeTest, BarrierReplace) {
413   const std::string text = R"(
414 ; CHECK-NOT: OpControlBarrier
415             OpCapability Shader
416        %1 = OpExtInstImport "GLSL.std.450"
417             OpMemoryModel Logical GLSL450
418             OpEntryPoint Vertex %main "main"
419             OpExecutionMode %main LocalSize 1 1 1
420             OpSource GLSL 450
421             OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
422             OpSourceExtension "GL_GOOGLE_include_directive"
423             OpName %main "main"
424     %void = OpTypeVoid
425        %3 = OpTypeFunction %void
426     %uint = OpTypeInt 32 0
427   %uint_2 = OpConstant %uint 2
428 %uint_264 = OpConstant %uint 264
429     %main = OpFunction %void None %3
430        %5 = OpLabel
431             OpControlBarrier %uint_2 %uint_2 %uint_264
432             OpReturn
433             OpFunctionEnd)";
434 
435   SinglePassRunAndMatch<ReplaceInvalidOpcodePass>(text, false);
436 }
437 
TEST_F(ReplaceInvalidOpcodeTest,MessageTest)438 TEST_F(ReplaceInvalidOpcodeTest, MessageTest) {
439   const std::string text = R"(
440                OpCapability Shader
441           %1 = OpExtInstImport "GLSL.std.450"
442                OpMemoryModel Logical GLSL450
443                OpEntryPoint Vertex %main "main" %3 %gl_VertexIndex %5
444                OpSource GLSL 400
445           %6 = OpString "test.hlsl"
446                OpSourceExtension "GL_ARB_separate_shader_objects"
447                OpSourceExtension "GL_ARB_shading_language_420pack"
448                OpName %main "main"
449                OpDecorate %3 Location 0
450                OpDecorate %gl_VertexIndex BuiltIn VertexIndex
451                OpMemberDecorate %_struct_7 0 BuiltIn Position
452                OpDecorate %_struct_7 Block
453        %void = OpTypeVoid
454           %9 = OpTypeFunction %void
455       %float = OpTypeFloat 32
456          %11 = OpTypeImage %float 2D 0 0 0 1 Unknown
457 %_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
458          %13 = OpTypeSampler
459 %_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
460          %15 = OpTypeSampledImage %11
461     %v4float = OpTypeVector %float 4
462     %v2float = OpTypeVector %float 2
463 %_ptr_Output_v4float = OpTypePointer Output %v4float
464           %3 = OpVariable %_ptr_Output_v4float Output
465         %int = OpTypeInt 32 1
466 %_ptr_Input_int = OpTypePointer Input %int
467 %gl_VertexIndex = OpVariable %_ptr_Input_int Input
468   %_struct_7 = OpTypeStruct %v4float
469 %_ptr_Output__struct_7 = OpTypePointer Output %_struct_7
470           %5 = OpVariable %_ptr_Output__struct_7 Output
471       %int_0 = OpConstant %int 0
472     %float_0 = OpConstant %float 0
473          %24 = OpConstantComposite %v2float %float_0 %float_0
474          %25 = OpVariable %_ptr_UniformConstant_11 UniformConstant
475          %26 = OpVariable %_ptr_UniformConstant_13 UniformConstant
476        %main = OpFunction %void None %9
477          %27 = OpLabel
478                OpLine %6 2 4
479          %28 = OpLoad %13 %26
480          %29 = OpLoad %11 %25
481          %30 = OpSampledImage %15 %29 %28
482          %31 = OpImageSampleImplicitLod %v4float %30 %24
483          %32 = OpAccessChain %_ptr_Output_v4float %5 %int_0
484                OpStore %32 %31
485                OpReturn
486                OpFunctionEnd)";
487 
488   std::vector<Message> messages = {
489       {SPV_MSG_WARNING, "test.hlsl", 2, 4,
490        "Removing ImageSampleImplicitLod instruction because of incompatible "
491        "execution model."}};
492   SetMessageConsumer(GetTestMessageConsumer(messages));
493   auto result = SinglePassRunAndDisassemble<ReplaceInvalidOpcodePass>(
494       text, /* skip_nop = */ true, /* do_validation = */ false);
495   EXPECT_EQ(Pass::Status::SuccessWithChange, std::get<1>(result));
496 }
497 
TEST_F(ReplaceInvalidOpcodeTest,MultipleMessageTest)498 TEST_F(ReplaceInvalidOpcodeTest, MultipleMessageTest) {
499   const std::string text = R"(
500                OpCapability Shader
501           %1 = OpExtInstImport "GLSL.std.450"
502                OpMemoryModel Logical GLSL450
503                OpEntryPoint Vertex %main "main" %3 %gl_VertexIndex %5
504                OpSource GLSL 400
505           %6 = OpString "test.hlsl"
506                OpSourceExtension "GL_ARB_separate_shader_objects"
507                OpSourceExtension "GL_ARB_shading_language_420pack"
508                OpName %main "main"
509                OpDecorate %3 Location 0
510                OpDecorate %gl_VertexIndex BuiltIn VertexIndex
511                OpMemberDecorate %_struct_7 0 BuiltIn Position
512                OpDecorate %_struct_7 Block
513        %void = OpTypeVoid
514           %9 = OpTypeFunction %void
515       %float = OpTypeFloat 32
516          %11 = OpTypeImage %float 2D 0 0 0 1 Unknown
517 %_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
518          %13 = OpTypeSampler
519 %_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
520          %15 = OpTypeSampledImage %11
521     %v4float = OpTypeVector %float 4
522     %v2float = OpTypeVector %float 2
523 %_ptr_Output_v4float = OpTypePointer Output %v4float
524           %3 = OpVariable %_ptr_Output_v4float Output
525         %int = OpTypeInt 32 1
526 %_ptr_Input_int = OpTypePointer Input %int
527 %gl_VertexIndex = OpVariable %_ptr_Input_int Input
528   %_struct_7 = OpTypeStruct %v4float
529 %_ptr_Output__struct_7 = OpTypePointer Output %_struct_7
530           %5 = OpVariable %_ptr_Output__struct_7 Output
531       %int_0 = OpConstant %int 0
532     %float_0 = OpConstant %float 0
533          %24 = OpConstantComposite %v2float %float_0 %float_0
534          %25 = OpVariable %_ptr_UniformConstant_11 UniformConstant
535          %26 = OpVariable %_ptr_UniformConstant_13 UniformConstant
536        %main = OpFunction %void None %9
537          %27 = OpLabel
538                OpLine %6 2 4
539          %28 = OpLoad %13 %26
540          %29 = OpLoad %11 %25
541          %30 = OpSampledImage %15 %29 %28
542          %31 = OpImageSampleImplicitLod %v4float %30 %24
543                OpLine %6 12 4
544          %41 = OpImageSampleProjImplicitLod %v4float %30 %24
545          %32 = OpAccessChain %_ptr_Output_v4float %5 %int_0
546                OpStore %32 %31
547                OpReturn
548                OpFunctionEnd)";
549 
550   std::vector<Message> messages = {
551       {SPV_MSG_WARNING, "test.hlsl", 2, 4,
552        "Removing ImageSampleImplicitLod instruction because of incompatible "
553        "execution model."},
554       {SPV_MSG_WARNING, "test.hlsl", 12, 4,
555        "Removing ImageSampleProjImplicitLod instruction because of "
556        "incompatible "
557        "execution model."}};
558   SetMessageConsumer(GetTestMessageConsumer(messages));
559   auto result = SinglePassRunAndDisassemble<ReplaceInvalidOpcodePass>(
560       text, /* skip_nop = */ true, /* do_validation = */ false);
561   EXPECT_EQ(Pass::Status::SuccessWithChange, std::get<1>(result));
562 }
563 
564 }  // namespace
565 }  // namespace opt
566 }  // namespace spvtools
567