1 // Copyright (c) 2017 Valve Corporation
2 // Copyright (c) 2017 LunarG Inc.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 
16 #include <string>
17 
18 #include "test/opt/pass_fixture.h"
19 #include "test/opt/pass_utils.h"
20 
21 namespace spvtools {
22 namespace opt {
23 namespace {
24 
25 using LocalAccessChainConvertTest = PassTest<::testing::Test>;
26 
TEST_F(LocalAccessChainConvertTest,StructOfVecsOfFloatConverted)27 TEST_F(LocalAccessChainConvertTest, StructOfVecsOfFloatConverted) {
28   //  #version 140
29   //
30   //  in vec4 BaseColor;
31   //
32   //  struct S_t {
33   //      vec4 v0;
34   //      vec4 v1;
35   //  };
36   //
37   //  void main()
38   //  {
39   //      S_t s0;
40   //      s0.v1 = BaseColor;
41   //      gl_FragColor = s0.v1;
42   //  }
43 
44   const std::string predefs_before =
45       R"(OpCapability Shader
46 %1 = OpExtInstImport "GLSL.std.450"
47 OpMemoryModel Logical GLSL450
48 OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
49 OpExecutionMode %main OriginUpperLeft
50 OpSource GLSL 140
51 OpName %main "main"
52 OpName %S_t "S_t"
53 OpMemberName %S_t 0 "v0"
54 OpMemberName %S_t 1 "v1"
55 OpName %s0 "s0"
56 OpName %BaseColor "BaseColor"
57 OpName %gl_FragColor "gl_FragColor"
58 %void = OpTypeVoid
59 %8 = OpTypeFunction %void
60 %float = OpTypeFloat 32
61 %v4float = OpTypeVector %float 4
62 %S_t = OpTypeStruct %v4float %v4float
63 %_ptr_Function_S_t = OpTypePointer Function %S_t
64 %int = OpTypeInt 32 1
65 %int_1 = OpConstant %int 1
66 %_ptr_Input_v4float = OpTypePointer Input %v4float
67 %BaseColor = OpVariable %_ptr_Input_v4float Input
68 %_ptr_Function_v4float = OpTypePointer Function %v4float
69 %_ptr_Output_v4float = OpTypePointer Output %v4float
70 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
71 )";
72 
73   const std::string before =
74       R"(
75 ; CHECK: [[st_id:%\w+]] = OpLoad %v4float %BaseColor
76 ; CHECK: [[ld1:%\w+]] = OpLoad %S_t %s0
77 ; CHECK: [[ex1:%\w+]] = OpCompositeInsert %S_t [[st_id]] [[ld1]] 1
78 ; CHECK: OpStore %s0 [[ex1]]
79 ; CHECK: [[ld2:%\w+]] = OpLoad %S_t %s0
80 ; CHECK: [[ex2:%\w+]] = OpCompositeExtract %v4float [[ld2]] 1
81 ; CHECK: OpStore %gl_FragColor [[ex2]]
82 %main = OpFunction %void None %8
83 %17 = OpLabel
84 %s0 = OpVariable %_ptr_Function_S_t Function
85 %18 = OpLoad %v4float %BaseColor
86 %19 = OpAccessChain %_ptr_Function_v4float %s0 %int_1
87 OpStore %19 %18
88 %20 = OpAccessChain %_ptr_Function_v4float %s0 %int_1
89 %21 = OpLoad %v4float %20
90 OpStore %gl_FragColor %21
91 OpReturn
92 OpFunctionEnd
93 )";
94 
95   SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs_before + before,
96                                                      true);
97 }
98 
TEST_F(LocalAccessChainConvertTest,DebugScopeAndLineInfoForNewInstructions)99 TEST_F(LocalAccessChainConvertTest, DebugScopeAndLineInfoForNewInstructions) {
100   //  #version 140
101   //
102   //  in vec4 BaseColor;
103   //
104   //  struct S_t {
105   //      vec4 v0;
106   //      vec4 v1;
107   //  };
108   //
109   //  void main()
110   //  {
111   //      S_t s0;
112   //      s0.v1 = BaseColor;
113   //      gl_FragColor = s0.v1;
114   //  }
115 
116   const std::string predefs_before =
117       R"(OpCapability Shader
118 %1 = OpExtInstImport "GLSL.std.450"
119 %ext = OpExtInstImport "OpenCL.DebugInfo.100"
120 OpMemoryModel Logical GLSL450
121 OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
122 OpExecutionMode %main OriginUpperLeft
123 OpSource GLSL 140
124 OpName %main "main"
125 OpName %S_t "S_t"
126 OpMemberName %S_t 0 "v0"
127 OpMemberName %S_t 1 "v1"
128 OpName %s0 "s0"
129 OpName %BaseColor "BaseColor"
130 OpName %gl_FragColor "gl_FragColor"
131 %5 = OpString "ps.hlsl"
132 %6 = OpString "float"
133 %var_name = OpString "s0"
134 %main_name = OpString "main"
135 %void = OpTypeVoid
136 %8 = OpTypeFunction %void
137 %float = OpTypeFloat 32
138 %v4float = OpTypeVector %float 4
139 %S_t = OpTypeStruct %v4float %v4float
140 %_ptr_Function_S_t = OpTypePointer Function %S_t
141 %int = OpTypeInt 32 1
142 %int_1 = OpConstant %int 1
143 %int_32 = OpConstant %int 32
144 %_ptr_Input_v4float = OpTypePointer Input %v4float
145 %BaseColor = OpVariable %_ptr_Input_v4float Input
146 %_ptr_Function_v4float = OpTypePointer Function %v4float
147 %_ptr_Output_v4float = OpTypePointer Output %v4float
148 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
149 %20 = OpExtInst %void %ext DebugSource %5
150 %21 = OpExtInst %void %ext DebugCompilationUnit 1 4 %20 HLSL
151 %22 = OpExtInst %void %ext DebugTypeBasic %6 %int_32 Float
152 %23 = OpExtInst %void %ext DebugTypeVector %22 4
153 %24 = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %23
154 %dbg_main = OpExtInst %void %ext DebugFunction %main_name %24 %20 4 1 %21 %main_name FlagIsProtected|FlagIsPrivate 4 %main
155 %25 = OpExtInst %void %ext DebugLocalVariable %var_name %23 %20 0 0 %dbg_main FlagIsLocal
156 )";
157 
158   const std::string before =
159       R"(
160 ; CHECK: [[st_id:%\w+]] = OpLoad %v4float %BaseColor
161 ; CHECK: OpLine {{%\w+}} 1 0
162 ; CHECK: [[ld1:%\w+]] = OpLoad %S_t %s0
163 ; CHECK: [[ex1:%\w+]] = OpCompositeInsert %S_t [[st_id]] [[ld1]] 1
164 ; CHECK: OpStore %s0 [[ex1]]
165 ; CHECK: OpLine {{%\w+}} 3 0
166 ; CHECK: [[ld2:%\w+]] = OpLoad %S_t %s0
167 ; CHECK: [[ex2:%\w+]] = OpCompositeExtract %v4float [[ld2]] 1
168 ; CHECK: OpLine {{%\w+}} 4 0
169 ; CHECK: OpStore %gl_FragColor [[ex2]]
170 %main = OpFunction %void None %8
171 %17 = OpLabel
172 %26 = OpExtInst %void %ext DebugScope %dbg_main
173 %s0 = OpVariable %_ptr_Function_S_t Function
174 %18 = OpLoad %v4float %BaseColor
175 OpLine %5 0 0
176 %19 = OpAccessChain %_ptr_Function_v4float %s0 %int_1
177 OpLine %5 1 0
178 OpStore %19 %18
179 OpLine %5 2 0
180 %27 = OpAccessChain %_ptr_Function_v4float %s0 %int_1
181 OpLine %5 3 0
182 %28 = OpLoad %v4float %27
183 OpLine %5 4 0
184 OpStore %gl_FragColor %28
185 OpReturn
186 OpFunctionEnd
187 )";
188 
189   SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs_before + before,
190                                                      true);
191 }
192 
TEST_F(LocalAccessChainConvertTest,TestTargetsReferencedByDebugValue)193 TEST_F(LocalAccessChainConvertTest, TestTargetsReferencedByDebugValue) {
194   //  #version 140
195   //
196   //  in vec4 BaseColor;
197   //
198   //  struct S_t {
199   //      vec4 v0;
200   //      vec4 v1;
201   //  };
202   //
203   //  void main()
204   //  {
205   //      S_t s0;
206   //      s0.v1 = BaseColor;
207   //      gl_FragColor = s0.v1;
208   //  }
209 
210   const std::string predefs_before =
211       R"(OpCapability Shader
212 %1 = OpExtInstImport "GLSL.std.450"
213 %ext = OpExtInstImport "OpenCL.DebugInfo.100"
214 OpMemoryModel Logical GLSL450
215 OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
216 OpExecutionMode %main OriginUpperLeft
217 OpSource GLSL 140
218 OpName %main "main"
219 OpName %S_t "S_t"
220 OpMemberName %S_t 0 "v0"
221 OpMemberName %S_t 1 "v1"
222 OpName %s0 "s0"
223 OpName %BaseColor "BaseColor"
224 OpName %gl_FragColor "gl_FragColor"
225 %5 = OpString "ps.hlsl"
226 %6 = OpString "float"
227 %var_name = OpString "s0"
228 %main_name = OpString "main"
229 %void = OpTypeVoid
230 %8 = OpTypeFunction %void
231 %float = OpTypeFloat 32
232 %v4float = OpTypeVector %float 4
233 %S_t = OpTypeStruct %v4float %v4float
234 %_ptr_Function_S_t = OpTypePointer Function %S_t
235 %int = OpTypeInt 32 1
236 %int_1 = OpConstant %int 1
237 %int_32 = OpConstant %int 32
238 %_ptr_Input_v4float = OpTypePointer Input %v4float
239 %BaseColor = OpVariable %_ptr_Input_v4float Input
240 %_ptr_Function_v4float = OpTypePointer Function %v4float
241 %_ptr_Output_v4float = OpTypePointer Output %v4float
242 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
243 %deref = OpExtInst %void %ext DebugOperation Deref
244 %deref_expr = OpExtInst %void %ext DebugExpression %deref
245 %null_expr = OpExtInst %void %ext DebugExpression
246 %20 = OpExtInst %void %ext DebugSource %5
247 %21 = OpExtInst %void %ext DebugCompilationUnit 1 4 %20 HLSL
248 %22 = OpExtInst %void %ext DebugTypeBasic %6 %int_32 Float
249 %23 = OpExtInst %void %ext DebugTypeVector %22 4
250 %24 = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %23
251 %dbg_main = OpExtInst %void %ext DebugFunction %main_name %24 %20 4 1 %21 %main_name FlagIsProtected|FlagIsPrivate 4 %main
252 %25 = OpExtInst %void %ext DebugLocalVariable %var_name %23 %20 0 0 %dbg_main FlagIsLocal
253 )";
254 
255   const std::string before =
256       R"(
257 ; CHECK: [[st_id:%\w+]] = OpLoad %v4float %BaseColor
258 ; CHECK: OpLine {{%\w+}} 0 0
259 ; CHECK: [[s0_1_ptr:%\w+]] = OpAccessChain %_ptr_Function_v4float %s0 %int_1
260 ; CHECK: DebugValue [[dbg_s0:%\w+]] [[s0_1_ptr]]
261 ; CHECK: OpLine {{%\w+}} 1 0
262 ; CHECK: [[s0:%\w+]] = OpLoad %S_t %s0
263 ; CHECK: [[comp:%\w+]] = OpCompositeInsert %S_t [[st_id]] [[s0]] 1
264 ; CHECK: OpStore %s0 [[comp]]
265 ; CHECK: OpLine {{%\w+}} 2 0
266 ; CHECK: [[s0_2_ptr:%\w+]] = OpAccessChain %_ptr_Function_v4float %s0 %int_1
267 ; CHECK: OpLine {{%\w+}} 3 0
268 ; CHECK: [[s0:%\w+]] = OpLoad %S_t %s0
269 ; CHECK: [[s0_2_val:%\w+]] = OpCompositeExtract %v4float [[s0]] 1
270 ; CHECK: DebugValue [[dbg_s0]] [[s0_2_val]]
271 ; CHECK: OpLine {{%\w+}} 4 0
272 ; CHECK: OpStore %gl_FragColor [[s0_2_val]]
273 %main = OpFunction %void None %8
274 %17 = OpLabel
275 %26 = OpExtInst %void %ext DebugScope %dbg_main
276 %s0 = OpVariable %_ptr_Function_S_t Function
277 %18 = OpLoad %v4float %BaseColor
278 OpLine %5 0 0
279 %19 = OpAccessChain %_ptr_Function_v4float %s0 %int_1
280 %29 = OpExtInst %void %ext DebugValue %25 %19 %deref_expr %int_1
281 OpLine %5 1 0
282 OpStore %19 %18
283 OpLine %5 2 0
284 %27 = OpAccessChain %_ptr_Function_v4float %s0 %int_1
285 OpLine %5 3 0
286 %28 = OpLoad %v4float %27
287 %30 = OpExtInst %void %ext DebugValue %25 %28 %null_expr %int_1
288 OpLine %5 4 0
289 OpStore %gl_FragColor %28
290 OpReturn
291 OpFunctionEnd
292 )";
293 
294   SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs_before + before,
295                                                      true);
296 }
297 
TEST_F(LocalAccessChainConvertTest,InBoundsAccessChainsConverted)298 TEST_F(LocalAccessChainConvertTest, InBoundsAccessChainsConverted) {
299   //  #version 140
300   //
301   //  in vec4 BaseColor;
302   //
303   //  struct S_t {
304   //      vec4 v0;
305   //      vec4 v1;
306   //  };
307   //
308   //  void main()
309   //  {
310   //      S_t s0;
311   //      s0.v1 = BaseColor;
312   //      gl_FragColor = s0.v1;
313   //  }
314 
315   const std::string predefs_before =
316       R"(OpCapability Shader
317 %1 = OpExtInstImport "GLSL.std.450"
318 OpMemoryModel Logical GLSL450
319 OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
320 OpExecutionMode %main OriginUpperLeft
321 OpSource GLSL 140
322 OpName %main "main"
323 OpName %S_t "S_t"
324 OpMemberName %S_t 0 "v0"
325 OpMemberName %S_t 1 "v1"
326 OpName %s0 "s0"
327 OpName %BaseColor "BaseColor"
328 OpName %gl_FragColor "gl_FragColor"
329 %void = OpTypeVoid
330 %8 = OpTypeFunction %void
331 %float = OpTypeFloat 32
332 %v4float = OpTypeVector %float 4
333 %S_t = OpTypeStruct %v4float %v4float
334 %_ptr_Function_S_t = OpTypePointer Function %S_t
335 %int = OpTypeInt 32 1
336 %int_1 = OpConstant %int 1
337 %_ptr_Input_v4float = OpTypePointer Input %v4float
338 %BaseColor = OpVariable %_ptr_Input_v4float Input
339 %_ptr_Function_v4float = OpTypePointer Function %v4float
340 %_ptr_Output_v4float = OpTypePointer Output %v4float
341 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
342 )";
343 
344   const std::string before =
345       R"(
346 ; CHECK: [[st_id:%\w+]] = OpLoad %v4float %BaseColor
347 ; CHECK: [[ld1:%\w+]] = OpLoad %S_t %s0
348 ; CHECK: [[ex1:%\w+]] = OpCompositeInsert %S_t [[st_id]] [[ld1]] 1
349 ; CHECK: OpStore %s0 [[ex1]]
350 ; CHECK: [[ld2:%\w+]] = OpLoad %S_t %s0
351 ; CHECK: [[ex2:%\w+]] = OpCompositeExtract %v4float [[ld2]] 1
352 ; CHECK: OpStore %gl_FragColor [[ex2]]
353 %main = OpFunction %void None %8
354 %17 = OpLabel
355 %s0 = OpVariable %_ptr_Function_S_t Function
356 %18 = OpLoad %v4float %BaseColor
357 %19 = OpInBoundsAccessChain %_ptr_Function_v4float %s0 %int_1
358 OpStore %19 %18
359 %20 = OpInBoundsAccessChain %_ptr_Function_v4float %s0 %int_1
360 %21 = OpLoad %v4float %20
361 OpStore %gl_FragColor %21
362 OpReturn
363 OpFunctionEnd
364 )";
365 
366   SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs_before + before,
367                                                      true);
368 }
369 
TEST_F(LocalAccessChainConvertTest,TwoUsesofSingleChainConverted)370 TEST_F(LocalAccessChainConvertTest, TwoUsesofSingleChainConverted) {
371   //  #version 140
372   //
373   //  in vec4 BaseColor;
374   //
375   //  struct S_t {
376   //      vec4 v0;
377   //      vec4 v1;
378   //  };
379   //
380   //  void main()
381   //  {
382   //      S_t s0;
383   //      s0.v1 = BaseColor;
384   //      gl_FragColor = s0.v1;
385   //  }
386 
387   const std::string predefs_before =
388       R"(OpCapability Shader
389 %1 = OpExtInstImport "GLSL.std.450"
390 OpMemoryModel Logical GLSL450
391 OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
392 OpExecutionMode %main OriginUpperLeft
393 OpSource GLSL 140
394 OpName %main "main"
395 OpName %S_t "S_t"
396 OpMemberName %S_t 0 "v0"
397 OpMemberName %S_t 1 "v1"
398 OpName %s0 "s0"
399 OpName %BaseColor "BaseColor"
400 OpName %gl_FragColor "gl_FragColor"
401 %void = OpTypeVoid
402 %8 = OpTypeFunction %void
403 %float = OpTypeFloat 32
404 %v4float = OpTypeVector %float 4
405 %S_t = OpTypeStruct %v4float %v4float
406 %_ptr_Function_S_t = OpTypePointer Function %S_t
407 %int = OpTypeInt 32 1
408 %int_1 = OpConstant %int 1
409 %_ptr_Input_v4float = OpTypePointer Input %v4float
410 %BaseColor = OpVariable %_ptr_Input_v4float Input
411 %_ptr_Function_v4float = OpTypePointer Function %v4float
412 %_ptr_Output_v4float = OpTypePointer Output %v4float
413 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
414 )";
415 
416   const std::string before =
417       R"(
418 ; CHECK: [[st_id:%\w+]] = OpLoad %v4float %BaseColor
419 ; CHECK: [[ld1:%\w+]] = OpLoad %S_t %s0
420 ; CHECK: [[ex1:%\w+]] = OpCompositeInsert %S_t [[st_id]] [[ld1]] 1
421 ; CHECK: OpStore %s0 [[ex1]]
422 ; CHECK: [[ld2:%\w+]] = OpLoad %S_t %s0
423 ; CHECK: [[ex2:%\w+]] = OpCompositeExtract %v4float [[ld2]] 1
424 ; CHECK: OpStore %gl_FragColor [[ex2]]
425 %main = OpFunction %void None %8
426 %17 = OpLabel
427 %s0 = OpVariable %_ptr_Function_S_t Function
428 %18 = OpLoad %v4float %BaseColor
429 %19 = OpAccessChain %_ptr_Function_v4float %s0 %int_1
430 OpStore %19 %18
431 %20 = OpLoad %v4float %19
432 OpStore %gl_FragColor %20
433 OpReturn
434 OpFunctionEnd
435 )";
436 
437   SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs_before + before,
438                                                      true);
439 }
440 
TEST_F(LocalAccessChainConvertTest,OpaqueConverted)441 TEST_F(LocalAccessChainConvertTest, OpaqueConverted) {
442   // SPIR-V not representable in GLSL; not generatable from HLSL
443   // at the moment
444 
445   const std::string predefs =
446       R"(
447 OpCapability Shader
448 %1 = OpExtInstImport "GLSL.std.450"
449 OpMemoryModel Logical GLSL450
450 OpEntryPoint Fragment %main "main" %outColor %texCoords
451 OpExecutionMode %main OriginUpperLeft
452 OpSource GLSL 140
453 OpName %main "main"
454 OpName %S_t "S_t"
455 OpMemberName %S_t 0 "v0"
456 OpMemberName %S_t 1 "v1"
457 OpMemberName %S_t 2 "smp"
458 OpName %foo_struct_S_t_vf2_vf21_ "foo(struct-S_t-vf2-vf21;"
459 OpName %s "s"
460 OpName %outColor "outColor"
461 OpName %sampler15 "sampler15"
462 OpName %s0 "s0"
463 OpName %texCoords "texCoords"
464 OpName %param "param"
465 OpDecorate %sampler15 DescriptorSet 0
466 %void = OpTypeVoid
467 %12 = OpTypeFunction %void
468 %float = OpTypeFloat 32
469 %v2float = OpTypeVector %float 2
470 %v4float = OpTypeVector %float 4
471 %_ptr_Output_v4float = OpTypePointer Output %v4float
472 %outColor = OpVariable %_ptr_Output_v4float Output
473 %17 = OpTypeImage %float 2D 0 0 0 1 Unknown
474 %18 = OpTypeSampledImage %17
475 %S_t = OpTypeStruct %v2float %v2float %18
476 %_ptr_Function_S_t = OpTypePointer Function %S_t
477 %20 = OpTypeFunction %void %_ptr_Function_S_t
478 %_ptr_UniformConstant_18 = OpTypePointer UniformConstant %18
479 %_ptr_Function_18 = OpTypePointer Function %18
480 %sampler15 = OpVariable %_ptr_UniformConstant_18 UniformConstant
481 %int = OpTypeInt 32 1
482 %int_0 = OpConstant %int 0
483 %int_2 = OpConstant %int 2
484 %_ptr_Function_v2float = OpTypePointer Function %v2float
485 %_ptr_Input_v2float = OpTypePointer Input %v2float
486 %texCoords = OpVariable %_ptr_Input_v2float Input
487 )";
488 
489   const std::string before =
490       R"(
491 ; CHECK: [[l1:%\w+]] = OpLoad %S_t %param
492 ; CHECK: [[e1:%\w+]] = OpCompositeExtract {{%\w+}} [[l1]] 2
493 ; CHECK: [[l2:%\w+]] = OpLoad %S_t %param
494 ; CHECK: [[e2:%\w+]] = OpCompositeExtract {{%\w+}} [[l2]] 0
495 ; CHECK: OpImageSampleImplicitLod {{%\w+}} [[e1]] [[e2]]
496 %main = OpFunction %void None %12
497 %28 = OpLabel
498 %s0 = OpVariable %_ptr_Function_S_t Function
499 %param = OpVariable %_ptr_Function_S_t Function
500 %29 = OpLoad %v2float %texCoords
501 %30 = OpAccessChain %_ptr_Function_v2float %s0 %int_0
502 OpStore %30 %29
503 %31 = OpLoad %18 %sampler15
504 %32 = OpAccessChain %_ptr_Function_18 %s0 %int_2
505 OpStore %32 %31
506 %33 = OpLoad %S_t %s0
507 OpStore %param %33
508 %34 = OpAccessChain %_ptr_Function_18 %param %int_2
509 %35 = OpLoad %18 %34
510 %36 = OpAccessChain %_ptr_Function_v2float %param %int_0
511 %37 = OpLoad %v2float %36
512 %38 = OpImageSampleImplicitLod %v4float %35 %37
513 OpStore %outColor %38
514 OpReturn
515 OpFunctionEnd
516 )";
517 
518   const std::string remain =
519       R"(%foo_struct_S_t_vf2_vf21_ = OpFunction %void None %20
520 %s = OpFunctionParameter %_ptr_Function_S_t
521 %39 = OpLabel
522 %40 = OpAccessChain %_ptr_Function_18 %s %int_2
523 %41 = OpLoad %18 %40
524 %42 = OpAccessChain %_ptr_Function_v2float %s %int_0
525 %43 = OpLoad %v2float %42
526 %44 = OpImageSampleImplicitLod %v4float %41 %43
527 OpStore %outColor %44
528 OpReturn
529 OpFunctionEnd
530 )";
531 
532   SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs + before + remain,
533                                                      true);
534 }
535 
TEST_F(LocalAccessChainConvertTest,NestedStructsConverted)536 TEST_F(LocalAccessChainConvertTest, NestedStructsConverted) {
537   //  #version 140
538   //
539   //  in vec4 BaseColor;
540   //
541   //  struct S1_t {
542   //      vec4 v1;
543   //  };
544   //
545   //  struct S2_t {
546   //      vec4 v2;
547   //      S1_t s1;
548   //  };
549   //
550   //  void main()
551   //  {
552   //      S2_t s2;
553   //      s2.s1.v1 = BaseColor;
554   //      gl_FragColor = s2.s1.v1;
555   //  }
556 
557   const std::string predefs_before =
558       R"(OpCapability Shader
559 %1 = OpExtInstImport "GLSL.std.450"
560 OpMemoryModel Logical GLSL450
561 OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
562 OpExecutionMode %main OriginUpperLeft
563 OpSource GLSL 140
564 OpName %main "main"
565 OpName %S1_t "S1_t"
566 OpMemberName %S1_t 0 "v1"
567 OpName %S2_t "S2_t"
568 OpMemberName %S2_t 0 "v2"
569 OpMemberName %S2_t 1 "s1"
570 OpName %s2 "s2"
571 OpName %BaseColor "BaseColor"
572 OpName %gl_FragColor "gl_FragColor"
573 %void = OpTypeVoid
574 %9 = OpTypeFunction %void
575 %float = OpTypeFloat 32
576 %v4float = OpTypeVector %float 4
577 %S1_t = OpTypeStruct %v4float
578 %S2_t = OpTypeStruct %v4float %S1_t
579 %_ptr_Function_S2_t = OpTypePointer Function %S2_t
580 %int = OpTypeInt 32 1
581 %int_1 = OpConstant %int 1
582 %int_0 = OpConstant %int 0
583 %_ptr_Input_v4float = OpTypePointer Input %v4float
584 %BaseColor = OpVariable %_ptr_Input_v4float Input
585 %_ptr_Function_v4float = OpTypePointer Function %v4float
586 %_ptr_Output_v4float = OpTypePointer Output %v4float
587 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
588 )";
589 
590   const std::string before =
591       R"(
592 ; CHECK: [[st_id:%\w+]] = OpLoad %v4float %BaseColor
593 ; CHECK: [[ld1:%\w+]] = OpLoad %S2_t %s2
594 ; CHECK: [[ex1:%\w+]] = OpCompositeInsert %S2_t [[st_id]] [[ld1]] 1 0
595 ; CHECK: OpStore %s2 [[ex1]]
596 ; CHECK: [[ld2:%\w+]] = OpLoad %S2_t %s2
597 ; CHECK: [[ex2:%\w+]] = OpCompositeExtract %v4float [[ld2]] 1 0
598 ; CHECK: OpStore %gl_FragColor [[ex2]]
599 %main = OpFunction %void None %9
600 %19 = OpLabel
601 %s2 = OpVariable %_ptr_Function_S2_t Function
602 %20 = OpLoad %v4float %BaseColor
603 %21 = OpAccessChain %_ptr_Function_v4float %s2 %int_1 %int_0
604 OpStore %21 %20
605 %22 = OpAccessChain %_ptr_Function_v4float %s2 %int_1 %int_0
606 %23 = OpLoad %v4float %22
607 OpStore %gl_FragColor %23
608 OpReturn
609 OpFunctionEnd
610 )";
611 
612   SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs_before + before,
613                                                      true);
614 }
615 
TEST_F(LocalAccessChainConvertTest,SomeAccessChainsHaveNoUse)616 TEST_F(LocalAccessChainConvertTest, SomeAccessChainsHaveNoUse) {
617   // Based on HLSL source code:
618   // struct S {
619   //   float f;
620   // };
621 
622   // float main(float input : A) : B {
623   //   S local = { input };
624   //   return local.f;
625   // }
626 
627   const std::string predefs = R"(OpCapability Shader
628 OpMemoryModel Logical GLSL450
629 OpEntryPoint Vertex %main "main" %in_var_A %out_var_B
630 OpName %main "main"
631 OpName %in_var_A "in.var.A"
632 OpName %out_var_B "out.var.B"
633 OpName %S "S"
634 OpName %local "local"
635 %int = OpTypeInt 32 1
636 %void = OpTypeVoid
637 %8 = OpTypeFunction %void
638 %float = OpTypeFloat 32
639 %_ptr_Function_float = OpTypePointer Function %float
640 %_ptr_Input_float = OpTypePointer Input %float
641 %_ptr_Output_float = OpTypePointer Output %float
642 %S = OpTypeStruct %float
643 %_ptr_Function_S = OpTypePointer Function %S
644 %int_0 = OpConstant %int 0
645 %in_var_A = OpVariable %_ptr_Input_float Input
646 %out_var_B = OpVariable %_ptr_Output_float Output
647 %main = OpFunction %void None %8
648 %15 = OpLabel
649 %local = OpVariable %_ptr_Function_S Function
650 %16 = OpLoad %float %in_var_A
651 %17 = OpCompositeConstruct %S %16
652 OpStore %local %17
653 )";
654 
655   const std::string before =
656       R"(
657 ; CHECK: [[ld:%\w+]] = OpLoad %S %local
658 ; CHECK: [[ex:%\w+]] = OpCompositeExtract %float [[ld]] 0
659 ; CHECK: OpStore %out_var_B [[ex]]
660 %18 = OpAccessChain %_ptr_Function_float %local %int_0
661 %19 = OpAccessChain %_ptr_Function_float %local %int_0
662 %20 = OpLoad %float %18
663 OpStore %out_var_B %20
664 OpReturn
665 OpFunctionEnd
666 )";
667 
668   SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs + before, true);
669 }
670 
TEST_F(LocalAccessChainConvertTest,StructOfVecsOfFloatConvertedWithDecorationOnLoad)671 TEST_F(LocalAccessChainConvertTest,
672        StructOfVecsOfFloatConvertedWithDecorationOnLoad) {
673   //  #version 140
674   //
675   //  in vec4 BaseColor;
676   //
677   //  struct S_t {
678   //      vec4 v0;
679   //      vec4 v1;
680   //  };
681   //
682   //  void main()
683   //  {
684   //      S_t s0;
685   //      s0.v1 = BaseColor;
686   //      gl_FragColor = s0.v1;
687   //  }
688 
689   const std::string predefs_before =
690       R"(OpCapability Shader
691 %1 = OpExtInstImport "GLSL.std.450"
692 OpMemoryModel Logical GLSL450
693 OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
694 OpExecutionMode %main OriginUpperLeft
695 OpSource GLSL 140
696 OpName %main "main"
697 OpName %S_t "S_t"
698 OpMemberName %S_t 0 "v0"
699 OpMemberName %S_t 1 "v1"
700 OpName %s0 "s0"
701 OpName %BaseColor "BaseColor"
702 OpName %gl_FragColor "gl_FragColor"
703 OpDecorate %21 RelaxedPrecision
704 %void = OpTypeVoid
705 %8 = OpTypeFunction %void
706 %float = OpTypeFloat 32
707 %v4float = OpTypeVector %float 4
708 %S_t = OpTypeStruct %v4float %v4float
709 %_ptr_Function_S_t = OpTypePointer Function %S_t
710 %int = OpTypeInt 32 1
711 %int_1 = OpConstant %int 1
712 %_ptr_Input_v4float = OpTypePointer Input %v4float
713 %BaseColor = OpVariable %_ptr_Input_v4float Input
714 %_ptr_Function_v4float = OpTypePointer Function %v4float
715 %_ptr_Output_v4float = OpTypePointer Output %v4float
716 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
717 )";
718 
719   const std::string before =
720       R"(
721 ; CHECK: OpDecorate
722 ; CHECK: OpDecorate [[ld2:%\w+]] RelaxedPrecision
723 ; CHECK-NOT: OpDecorate
724 ; CHECK: [[st_id:%\w+]] = OpLoad %v4float %BaseColor
725 ; CHECK: [[ld1:%\w+]] = OpLoad %S_t %s0
726 ; CHECK: [[ins:%\w+]] = OpCompositeInsert %S_t [[st_id]] [[ld1]] 1
727 ; CHECK: OpStore %s0 [[ins]]
728 ; CHECK: [[ld2]] = OpLoad %S_t %s0
729 ; CHECK: [[ex2:%\w+]] = OpCompositeExtract %v4float [[ld2]] 1
730 ; CHECK: OpStore %gl_FragColor [[ex2]]
731 %main = OpFunction %void None %8
732 %17 = OpLabel
733 %s0 = OpVariable %_ptr_Function_S_t Function
734 %18 = OpLoad %v4float %BaseColor
735 %19 = OpAccessChain %_ptr_Function_v4float %s0 %int_1
736 OpStore %19 %18
737 %20 = OpAccessChain %_ptr_Function_v4float %s0 %int_1
738 %21 = OpLoad %v4float %20
739 OpStore %gl_FragColor %21
740 OpReturn
741 OpFunctionEnd
742 )";
743 
744   SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs_before + before,
745                                                      true);
746 }
747 
TEST_F(LocalAccessChainConvertTest,StructOfVecsOfFloatConvertedWithDecorationOnStore)748 TEST_F(LocalAccessChainConvertTest,
749        StructOfVecsOfFloatConvertedWithDecorationOnStore) {
750   //  #version 140
751   //
752   //  in vec4 BaseColor;
753   //
754   //  struct S_t {
755   //      vec4 v0;
756   //      vec4 v1;
757   //  };
758   //
759   //  void main()
760   //  {
761   //      S_t s0;
762   //      s0.v1 = BaseColor;
763   //      gl_FragColor = s0.v1;
764   //  }
765 
766   const std::string predefs_before =
767       R"(OpCapability Shader
768 %1 = OpExtInstImport "GLSL.std.450"
769 OpMemoryModel Logical GLSL450
770 OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
771 OpExecutionMode %main OriginUpperLeft
772 OpSource GLSL 140
773 OpName %main "main"
774 OpName %S_t "S_t"
775 OpMemberName %S_t 0 "v0"
776 OpMemberName %S_t 1 "v1"
777 OpName %s0 "s0"
778 OpName %BaseColor "BaseColor"
779 OpName %gl_FragColor "gl_FragColor"
780 OpDecorate %s0 RelaxedPrecision
781 %void = OpTypeVoid
782 %8 = OpTypeFunction %void
783 %float = OpTypeFloat 32
784 %v4float = OpTypeVector %float 4
785 %S_t = OpTypeStruct %v4float %v4float
786 %_ptr_Function_S_t = OpTypePointer Function %S_t
787 %int = OpTypeInt 32 1
788 %int_1 = OpConstant %int 1
789 %_ptr_Input_v4float = OpTypePointer Input %v4float
790 %BaseColor = OpVariable %_ptr_Input_v4float Input
791 %_ptr_Function_v4float = OpTypePointer Function %v4float
792 %_ptr_Output_v4float = OpTypePointer Output %v4float
793 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
794 )";
795 
796   const std::string before =
797       R"(
798 ; CHECK: OpDecorate
799 ; CHECK: OpDecorate [[ld1:%\w+]] RelaxedPrecision
800 ; CHECK: OpDecorate [[ins:%\w+]] RelaxedPrecision
801 ; CHECK-NOT: OpDecorate
802 ; CHECK: [[st_id:%\w+]] = OpLoad %v4float %BaseColor
803 ; CHECK: [[ld1]] = OpLoad %S_t %s0
804 ; CHECK: [[ins]] = OpCompositeInsert %S_t [[st_id]] [[ld1]] 1
805 ; CHECK: OpStore %s0 [[ins]]
806 ; CHECK: [[ld2:%\w+]] = OpLoad %S_t %s0
807 ; CHECK: [[ex2:%\w+]] = OpCompositeExtract %v4float [[ld2]] 1
808 ; CHECK: OpStore %gl_FragColor [[ex2]]
809 %main = OpFunction %void None %8
810 %17 = OpLabel
811 %s0 = OpVariable %_ptr_Function_S_t Function
812 %18 = OpLoad %v4float %BaseColor
813 %19 = OpAccessChain %_ptr_Function_v4float %s0 %int_1
814 OpStore %19 %18
815 %20 = OpAccessChain %_ptr_Function_v4float %s0 %int_1
816 %21 = OpLoad %v4float %20
817 OpStore %gl_FragColor %21
818 OpReturn
819 OpFunctionEnd
820 )";
821 
822   SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs_before + before,
823                                                      true);
824 }
825 
TEST_F(LocalAccessChainConvertTest,DynamicallyIndexedVarNotConverted)826 TEST_F(LocalAccessChainConvertTest, DynamicallyIndexedVarNotConverted) {
827   //  #version 140
828   //
829   //  in vec4 BaseColor;
830   //  flat in int Idx;
831   //  in float Bi;
832   //
833   //  struct S_t {
834   //      vec4 v0;
835   //      vec4 v1;
836   //  };
837   //
838   //  void main()
839   //  {
840   //      S_t s0;
841   //      s0.v1 = BaseColor;
842   //      s0.v1[Idx] = Bi;
843   //      gl_FragColor = s0.v1;
844   //  }
845 
846   const std::string assembly =
847       R"(OpCapability Shader
848 %1 = OpExtInstImport "GLSL.std.450"
849 OpMemoryModel Logical GLSL450
850 OpEntryPoint Fragment %main "main" %BaseColor %Idx %Bi %gl_FragColor
851 OpExecutionMode %main OriginUpperLeft
852 OpSource GLSL 140
853 OpName %main "main"
854 OpName %S_t "S_t"
855 OpMemberName %S_t 0 "v0"
856 OpMemberName %S_t 1 "v1"
857 OpName %s0 "s0"
858 OpName %BaseColor "BaseColor"
859 OpName %Idx "Idx"
860 OpName %Bi "Bi"
861 OpName %gl_FragColor "gl_FragColor"
862 OpDecorate %Idx Flat
863 %void = OpTypeVoid
864 %10 = OpTypeFunction %void
865 %float = OpTypeFloat 32
866 %v4float = OpTypeVector %float 4
867 %S_t = OpTypeStruct %v4float %v4float
868 %_ptr_Function_S_t = OpTypePointer Function %S_t
869 %int = OpTypeInt 32 1
870 %int_1 = OpConstant %int 1
871 %_ptr_Input_v4float = OpTypePointer Input %v4float
872 %BaseColor = OpVariable %_ptr_Input_v4float Input
873 %_ptr_Function_v4float = OpTypePointer Function %v4float
874 %_ptr_Input_int = OpTypePointer Input %int
875 %Idx = OpVariable %_ptr_Input_int Input
876 %_ptr_Input_float = OpTypePointer Input %float
877 %Bi = OpVariable %_ptr_Input_float Input
878 %_ptr_Function_float = OpTypePointer Function %float
879 %_ptr_Output_v4float = OpTypePointer Output %v4float
880 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
881 %main = OpFunction %void None %10
882 %22 = OpLabel
883 %s0 = OpVariable %_ptr_Function_S_t Function
884 %23 = OpLoad %v4float %BaseColor
885 %24 = OpAccessChain %_ptr_Function_v4float %s0 %int_1
886 OpStore %24 %23
887 %25 = OpLoad %int %Idx
888 %26 = OpLoad %float %Bi
889 %27 = OpAccessChain %_ptr_Function_float %s0 %int_1 %25
890 OpStore %27 %26
891 %28 = OpAccessChain %_ptr_Function_v4float %s0 %int_1
892 %29 = OpLoad %v4float %28
893 OpStore %gl_FragColor %29
894 OpReturn
895 OpFunctionEnd
896 )";
897 
898   SinglePassRunAndCheck<LocalAccessChainConvertPass>(assembly, assembly, false,
899                                                      true);
900 }
901 
TEST_F(LocalAccessChainConvertTest,VariablePointersStorageBuffer)902 TEST_F(LocalAccessChainConvertTest, VariablePointersStorageBuffer) {
903   // A case with a storage buffer variable pointer.  We should still convert
904   // the access chain on the function scope symbol.
905   const std::string test =
906       R"(
907 ; CHECK: OpFunction
908 ; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Function
909 ; CHECK: [[ld:%\w+]] = OpLoad {{%\w+}} [[var]]
910 ; CHECK: OpCompositeExtract {{%\w+}} [[ld]] 0 0
911                OpCapability Shader
912                OpCapability VariablePointersStorageBuffer
913           %1 = OpExtInstImport "GLSL.std.450"
914                OpMemoryModel Logical GLSL450
915                OpEntryPoint GLCompute %2 "main"
916                OpExecutionMode %2 LocalSize 1 1 1
917                OpSource GLSL 450
918                OpMemberDecorate %_struct_3 0 Offset 0
919                OpDecorate %_struct_3 Block
920                OpDecorate %4 DescriptorSet 0
921                OpDecorate %4 Binding 0
922                OpDecorate %_ptr_StorageBuffer_int ArrayStride 4
923                OpDecorate %_arr_int_int_128 ArrayStride 4
924        %void = OpTypeVoid
925           %8 = OpTypeFunction %void
926         %int = OpTypeInt 32 1
927     %int_128 = OpConstant %int 128
928 %_arr_int_int_128 = OpTypeArray %int %int_128
929   %_struct_3 = OpTypeStruct %_arr_int_int_128
930 %_ptr_StorageBuffer__struct_3 = OpTypePointer StorageBuffer %_struct_3
931 %_ptr_Function__struct_3 = OpTypePointer Function %_struct_3
932           %4 = OpVariable %_ptr_StorageBuffer__struct_3 StorageBuffer
933        %bool = OpTypeBool
934        %true = OpConstantTrue %bool
935       %int_0 = OpConstant %int 0
936       %int_1 = OpConstant %int 1
937 %_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
938 %_ptr_Function_int = OpTypePointer Function %int
939           %2 = OpFunction %void None %8
940          %18 = OpLabel
941          %19 = OpVariable %_ptr_Function__struct_3 Function
942          %20 = OpAccessChain %_ptr_StorageBuffer_int %4 %int_0 %int_0
943                OpBranch %21
944          %21 = OpLabel
945          %22 = OpPhi %_ptr_StorageBuffer_int %20 %18 %23 %24
946                OpLoopMerge %25 %24 None
947                OpBranchConditional %true %26 %25
948          %26 = OpLabel
949                OpStore %22 %int_0
950                OpBranch %24
951          %24 = OpLabel
952          %23 = OpPtrAccessChain %_ptr_StorageBuffer_int %22 %int_1
953                OpBranch %21
954          %25 = OpLabel
955          %27 = OpAccessChain %_ptr_Function_int %19 %int_0 %int_0
956          %28 = OpLoad %int %27
957                OpReturn
958                OpFunctionEnd
959 )";
960 
961   SinglePassRunAndMatch<LocalAccessChainConvertPass>(test, true);
962 }
963 
TEST_F(LocalAccessChainConvertTest,VariablePointers)964 TEST_F(LocalAccessChainConvertTest, VariablePointers) {
965   // A case with variable pointer capability.  We should not convert
966   // the access chain on the function scope symbol because the variable pointer
967   // could the analysis to miss references to function scope symbols.
968   const std::string test =
969       R"(OpCapability Shader
970 OpCapability VariablePointers
971 %1 = OpExtInstImport "GLSL.std.450"
972 OpMemoryModel Logical GLSL450
973 OpEntryPoint GLCompute %2 "main"
974 OpExecutionMode %2 LocalSize 1 1 1
975 OpSource GLSL 450
976 OpMemberDecorate %_struct_3 0 Offset 0
977 OpDecorate %_struct_3 Block
978 OpDecorate %4 DescriptorSet 0
979 OpDecorate %4 Binding 0
980 OpDecorate %_ptr_StorageBuffer_int ArrayStride 4
981 OpDecorate %_arr_int_int_128 ArrayStride 4
982 %void = OpTypeVoid
983 %8 = OpTypeFunction %void
984 %int = OpTypeInt 32 1
985 %int_128 = OpConstant %int 128
986 %_arr_int_int_128 = OpTypeArray %int %int_128
987 %_struct_3 = OpTypeStruct %_arr_int_int_128
988 %_ptr_StorageBuffer__struct_3 = OpTypePointer StorageBuffer %_struct_3
989 %_ptr_Function__struct_3 = OpTypePointer Function %_struct_3
990 %4 = OpVariable %_ptr_StorageBuffer__struct_3 StorageBuffer
991 %bool = OpTypeBool
992 %true = OpConstantTrue %bool
993 %int_0 = OpConstant %int 0
994 %int_1 = OpConstant %int 1
995 %_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
996 %_ptr_Function_int = OpTypePointer Function %int
997 %2 = OpFunction %void None %8
998 %18 = OpLabel
999 %19 = OpVariable %_ptr_Function__struct_3 Function
1000 %20 = OpAccessChain %_ptr_StorageBuffer_int %4 %int_0 %int_0
1001 OpBranch %21
1002 %21 = OpLabel
1003 %22 = OpPhi %_ptr_StorageBuffer_int %20 %18 %23 %24
1004 OpLoopMerge %25 %24 None
1005 OpBranchConditional %true %26 %25
1006 %26 = OpLabel
1007 OpStore %22 %int_0
1008 OpBranch %24
1009 %24 = OpLabel
1010 %23 = OpPtrAccessChain %_ptr_StorageBuffer_int %22 %int_1
1011 OpBranch %21
1012 %25 = OpLabel
1013 %27 = OpAccessChain %_ptr_Function_int %19 %int_0 %int_0
1014 %28 = OpLoad %int %27
1015 OpReturn
1016 OpFunctionEnd
1017 )";
1018 
1019   SinglePassRunAndCheck<LocalAccessChainConvertPass>(test, test, false, true);
1020 }
1021 
TEST_F(LocalAccessChainConvertTest,IdOverflowReplacingLoad)1022 TEST_F(LocalAccessChainConvertTest, IdOverflowReplacingLoad) {
1023   const std::string text =
1024       R"(
1025                OpCapability Shader
1026                OpMemoryModel Logical GLSL450
1027                OpEntryPoint Fragment %4 "PSMain"
1028                OpExecutionMode %4 OriginUpperLeft
1029                OpDecorate %10 Location 47360
1030        %void = OpTypeVoid
1031           %3 = OpTypeFunction %void
1032       %float = OpTypeFloat 32
1033     %v4float = OpTypeVector %float 4
1034   %_struct_8 = OpTypeStruct %v4float
1035 %_ptr_Function__struct_8 = OpTypePointer Function %_struct_8
1036         %int = OpTypeInt 32 1
1037       %int_0 = OpConstant %int 0
1038 %_ptr_Function_v4float = OpTypePointer Function %v4float
1039           %4 = OpFunction %void None %3
1040           %5 = OpLabel
1041          %10 = OpVariable %_ptr_Function__struct_8 Function
1042     %4194301 = OpAccessChain %_ptr_Function_v4float %10 %int_0
1043     %4194302 = OpLoad %v4float %4194301
1044                OpReturn
1045                OpFunctionEnd
1046 )";
1047 
1048   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1049 
1050   std::vector<Message> messages = {
1051       {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}};
1052   SetMessageConsumer(GetTestMessageConsumer(messages));
1053   auto result = SinglePassRunToBinary<LocalAccessChainConvertPass>(text, true);
1054   EXPECT_EQ(Pass::Status::Failure, std::get<1>(result));
1055 }
1056 
TEST_F(LocalAccessChainConvertTest,IdOverflowReplacingStore1)1057 TEST_F(LocalAccessChainConvertTest, IdOverflowReplacingStore1) {
1058   const std::string text =
1059       R"(
1060                OpCapability Shader
1061                OpMemoryModel Logical GLSL450
1062                OpEntryPoint Fragment %4 "PSMain"
1063                OpExecutionMode %4 OriginUpperLeft
1064                OpDecorate %10 Location 47360
1065        %void = OpTypeVoid
1066           %3 = OpTypeFunction %void
1067       %float = OpTypeFloat 32
1068     %v4float = OpTypeVector %float 4
1069   %_struct_7 = OpTypeStruct %v4float
1070 %_ptr_Function__struct_7 = OpTypePointer Function %_struct_7
1071         %int = OpTypeInt 32 1
1072       %int_0 = OpConstant %int 0
1073 %_ptr_Function_v4float = OpTypePointer Function %v4float
1074          %13 = OpConstantNull %v4float
1075           %4 = OpFunction %void None %3
1076           %5 = OpLabel
1077          %10 = OpVariable %_ptr_Function__struct_7 Function
1078     %4194302 = OpAccessChain %_ptr_Function_v4float %10 %int_0
1079                OpStore %4194302 %13
1080                OpReturn
1081                OpFunctionEnd
1082 )";
1083 
1084   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1085 
1086   std::vector<Message> messages = {
1087       {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}};
1088   SetMessageConsumer(GetTestMessageConsumer(messages));
1089   auto result = SinglePassRunToBinary<LocalAccessChainConvertPass>(text, true);
1090   EXPECT_EQ(Pass::Status::Failure, std::get<1>(result));
1091 }
1092 
TEST_F(LocalAccessChainConvertTest,IdOverflowReplacingStore2)1093 TEST_F(LocalAccessChainConvertTest, IdOverflowReplacingStore2) {
1094   const std::string text =
1095       R"(
1096                OpCapability Shader
1097                OpMemoryModel Logical GLSL450
1098                OpEntryPoint Fragment %4 "PSMain"
1099                OpExecutionMode %4 OriginUpperLeft
1100                OpDecorate %10 Location 47360
1101        %void = OpTypeVoid
1102           %3 = OpTypeFunction %void
1103       %float = OpTypeFloat 32
1104     %v4float = OpTypeVector %float 4
1105   %_struct_7 = OpTypeStruct %v4float
1106 %_ptr_Function__struct_7 = OpTypePointer Function %_struct_7
1107         %int = OpTypeInt 32 1
1108       %int_0 = OpConstant %int 0
1109 %_ptr_Function_v4float = OpTypePointer Function %v4float
1110          %13 = OpConstantNull %v4float
1111           %4 = OpFunction %void None %3
1112           %5 = OpLabel
1113          %10 = OpVariable %_ptr_Function__struct_7 Function
1114     %4194301 = OpAccessChain %_ptr_Function_v4float %10 %int_0
1115                OpStore %4194301 %13
1116                OpReturn
1117                OpFunctionEnd
1118 )";
1119 
1120   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1121 
1122   std::vector<Message> messages = {
1123       {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}};
1124   SetMessageConsumer(GetTestMessageConsumer(messages));
1125   auto result = SinglePassRunToBinary<LocalAccessChainConvertPass>(text, true);
1126   EXPECT_EQ(Pass::Status::Failure, std::get<1>(result));
1127 }
1128 
TEST_F(LocalAccessChainConvertTest,AccessChainWithNoIndex)1129 TEST_F(LocalAccessChainConvertTest, AccessChainWithNoIndex) {
1130   const std::string before =
1131       R"(
1132 ; CHECK: OpFunction
1133 ; CHECK: [[var:%\w+]] = OpVariable
1134 ; CHECK: OpStore [[var]] %true
1135 ; CHECK: OpLoad %bool [[var]]
1136                OpCapability Shader
1137           %1 = OpExtInstImport "GLSL.std.450"
1138                OpMemoryModel Logical GLSL450
1139                OpEntryPoint Fragment %2 "main"
1140                OpExecutionMode %2 OriginUpperLeft
1141                OpSource ESSL 310
1142        %void = OpTypeVoid
1143           %4 = OpTypeFunction %void
1144        %bool = OpTypeBool
1145        %true = OpConstantTrue %bool
1146 %_ptr_Function_bool = OpTypePointer Function %bool
1147           %2 = OpFunction %void None %4
1148           %8 = OpLabel
1149           %9 = OpVariable %_ptr_Function_bool Function
1150          %10 = OpAccessChain %_ptr_Function_bool %9
1151                OpStore %10 %true
1152          %11 = OpLoad %bool %10
1153                OpReturn
1154                OpFunctionEnd
1155 )";
1156 
1157   SinglePassRunAndMatch<LocalAccessChainConvertPass>(before, true);
1158 }
1159 
1160 // TODO(greg-lunarg): Add tests to verify handling of these cases:
1161 //
1162 //    Assorted vector and matrix types
1163 //    Assorted struct array types
1164 //    Assorted scalar types
1165 //    Assorted non-target types
1166 //    OpInBoundsAccessChain
1167 //    Others?
1168 
1169 }  // namespace
1170 }  // namespace opt
1171 }  // namespace spvtools
1172