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