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 "source/opt/simplification_pass.h"
19 #include "test/opt/pass_fixture.h"
20 #include "test/opt/pass_utils.h"
21
22 namespace spvtools {
23 namespace opt {
24 namespace {
25
26 using InsertExtractElimTest = PassTest<::testing::Test>;
27
TEST_F(InsertExtractElimTest,Simple)28 TEST_F(InsertExtractElimTest, Simple) {
29 // Note: The SPIR-V assembly has had store/load elimination
30 // performed to allow the inserts and extracts to directly
31 // reference each other.
32 //
33 // #version 140
34 //
35 // in vec4 BaseColor;
36 //
37 // struct S_t {
38 // vec4 v0;
39 // vec4 v1;
40 // };
41 //
42 // void main()
43 // {
44 // S_t s0;
45 // s0.v1 = BaseColor;
46 // gl_FragColor = s0.v1;
47 // }
48
49 const std::string predefs =
50 R"(OpCapability Shader
51 %1 = OpExtInstImport "GLSL.std.450"
52 OpMemoryModel Logical GLSL450
53 OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
54 OpExecutionMode %main OriginUpperLeft
55 OpSource GLSL 140
56 OpName %main "main"
57 OpName %S_t "S_t"
58 OpMemberName %S_t 0 "v0"
59 OpMemberName %S_t 1 "v1"
60 OpName %s0 "s0"
61 OpName %BaseColor "BaseColor"
62 OpName %gl_FragColor "gl_FragColor"
63 %void = OpTypeVoid
64 %8 = OpTypeFunction %void
65 %float = OpTypeFloat 32
66 %v4float = OpTypeVector %float 4
67 %S_t = OpTypeStruct %v4float %v4float
68 %_ptr_Function_S_t = OpTypePointer Function %S_t
69 %int = OpTypeInt 32 1
70 %int_1 = OpConstant %int 1
71 %_ptr_Input_v4float = OpTypePointer Input %v4float
72 %BaseColor = OpVariable %_ptr_Input_v4float Input
73 %_ptr_Function_v4float = OpTypePointer Function %v4float
74 %_ptr_Output_v4float = OpTypePointer Output %v4float
75 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
76 )";
77
78 const std::string before =
79 R"(%main = OpFunction %void None %8
80 %17 = OpLabel
81 %s0 = OpVariable %_ptr_Function_S_t Function
82 %18 = OpLoad %v4float %BaseColor
83 %19 = OpLoad %S_t %s0
84 %20 = OpCompositeInsert %S_t %18 %19 1
85 OpStore %s0 %20
86 %21 = OpCompositeExtract %v4float %20 1
87 OpStore %gl_FragColor %21
88 OpReturn
89 OpFunctionEnd
90 )";
91
92 const std::string after =
93 R"(%main = OpFunction %void None %8
94 %17 = OpLabel
95 %s0 = OpVariable %_ptr_Function_S_t Function
96 %18 = OpLoad %v4float %BaseColor
97 %19 = OpLoad %S_t %s0
98 %20 = OpCompositeInsert %S_t %18 %19 1
99 OpStore %s0 %20
100 OpStore %gl_FragColor %18
101 OpReturn
102 OpFunctionEnd
103 )";
104
105 SinglePassRunAndCheck<SimplificationPass>(predefs + before, predefs + after,
106 true, true);
107 }
108
TEST_F(InsertExtractElimTest,OptimizeAcrossNonConflictingInsert)109 TEST_F(InsertExtractElimTest, OptimizeAcrossNonConflictingInsert) {
110 // Note: The SPIR-V assembly has had store/load elimination
111 // performed to allow the inserts and extracts to directly
112 // reference each other.
113 //
114 // #version 140
115 //
116 // in vec4 BaseColor;
117 //
118 // struct S_t {
119 // vec4 v0;
120 // vec4 v1;
121 // };
122 //
123 // void main()
124 // {
125 // S_t s0;
126 // s0.v1 = BaseColor;
127 // s0.v0[2] = 0.0;
128 // gl_FragColor = s0.v1;
129 // }
130
131 const std::string predefs =
132 R"(OpCapability Shader
133 %1 = OpExtInstImport "GLSL.std.450"
134 OpMemoryModel Logical GLSL450
135 OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
136 OpExecutionMode %main OriginUpperLeft
137 OpSource GLSL 140
138 OpName %main "main"
139 OpName %S_t "S_t"
140 OpMemberName %S_t 0 "v0"
141 OpMemberName %S_t 1 "v1"
142 OpName %s0 "s0"
143 OpName %BaseColor "BaseColor"
144 OpName %gl_FragColor "gl_FragColor"
145 %void = OpTypeVoid
146 %8 = OpTypeFunction %void
147 %float = OpTypeFloat 32
148 %v4float = OpTypeVector %float 4
149 %S_t = OpTypeStruct %v4float %v4float
150 %_ptr_Function_S_t = OpTypePointer Function %S_t
151 %int = OpTypeInt 32 1
152 %int_1 = OpConstant %int 1
153 %float_0 = OpConstant %float 0
154 %_ptr_Input_v4float = OpTypePointer Input %v4float
155 %BaseColor = OpVariable %_ptr_Input_v4float Input
156 %_ptr_Function_v4float = OpTypePointer Function %v4float
157 %_ptr_Output_v4float = OpTypePointer Output %v4float
158 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
159 )";
160
161 const std::string before =
162 R"(%main = OpFunction %void None %8
163 %18 = OpLabel
164 %s0 = OpVariable %_ptr_Function_S_t Function
165 %19 = OpLoad %v4float %BaseColor
166 %20 = OpLoad %S_t %s0
167 %21 = OpCompositeInsert %S_t %19 %20 1
168 %22 = OpCompositeInsert %S_t %float_0 %21 0 2
169 OpStore %s0 %22
170 %23 = OpCompositeExtract %v4float %22 1
171 OpStore %gl_FragColor %23
172 OpReturn
173 OpFunctionEnd
174 )";
175
176 const std::string after =
177 R"(%main = OpFunction %void None %8
178 %18 = OpLabel
179 %s0 = OpVariable %_ptr_Function_S_t Function
180 %19 = OpLoad %v4float %BaseColor
181 %20 = OpLoad %S_t %s0
182 %21 = OpCompositeInsert %S_t %19 %20 1
183 %22 = OpCompositeInsert %S_t %float_0 %21 0 2
184 OpStore %s0 %22
185 OpStore %gl_FragColor %19
186 OpReturn
187 OpFunctionEnd
188 )";
189
190 SinglePassRunAndCheck<SimplificationPass>(predefs + before, predefs + after,
191 true, true);
192 }
193
TEST_F(InsertExtractElimTest,OptimizeOpaque)194 TEST_F(InsertExtractElimTest, OptimizeOpaque) {
195 // SPIR-V not representable in GLSL; not generatable from HLSL
196 // for the moment.
197
198 const std::string predefs =
199 R"(OpCapability Shader
200 %1 = OpExtInstImport "GLSL.std.450"
201 OpMemoryModel Logical GLSL450
202 OpEntryPoint Fragment %main "main" %outColor %texCoords
203 OpExecutionMode %main OriginUpperLeft
204 OpSource GLSL 140
205 OpName %main "main"
206 OpName %S_t "S_t"
207 OpMemberName %S_t 0 "v0"
208 OpMemberName %S_t 1 "v1"
209 OpMemberName %S_t 2 "smp"
210 OpName %outColor "outColor"
211 OpName %sampler15 "sampler15"
212 OpName %s0 "s0"
213 OpName %texCoords "texCoords"
214 OpDecorate %sampler15 DescriptorSet 0
215 %void = OpTypeVoid
216 %9 = OpTypeFunction %void
217 %float = OpTypeFloat 32
218 %v2float = OpTypeVector %float 2
219 %v4float = OpTypeVector %float 4
220 %_ptr_Output_v4float = OpTypePointer Output %v4float
221 %outColor = OpVariable %_ptr_Output_v4float Output
222 %14 = OpTypeImage %float 2D 0 0 0 1 Unknown
223 %15 = OpTypeSampledImage %14
224 %S_t = OpTypeStruct %v2float %v2float %15
225 %_ptr_Function_S_t = OpTypePointer Function %S_t
226 %17 = OpTypeFunction %void %_ptr_Function_S_t
227 %_ptr_UniformConstant_15 = OpTypePointer UniformConstant %15
228 %_ptr_Function_15 = OpTypePointer Function %15
229 %sampler15 = OpVariable %_ptr_UniformConstant_15 UniformConstant
230 %int = OpTypeInt 32 1
231 %int_0 = OpConstant %int 0
232 %int_2 = OpConstant %int 2
233 %_ptr_Function_v2float = OpTypePointer Function %v2float
234 %_ptr_Input_v2float = OpTypePointer Input %v2float
235 %texCoords = OpVariable %_ptr_Input_v2float Input
236 )";
237
238 const std::string before =
239 R"(%main = OpFunction %void None %9
240 %25 = OpLabel
241 %s0 = OpVariable %_ptr_Function_S_t Function
242 %26 = OpLoad %v2float %texCoords
243 %27 = OpLoad %S_t %s0
244 %28 = OpCompositeInsert %S_t %26 %27 0
245 %29 = OpLoad %15 %sampler15
246 %30 = OpCompositeInsert %S_t %29 %28 2
247 OpStore %s0 %30
248 %31 = OpCompositeExtract %15 %30 2
249 %32 = OpCompositeExtract %v2float %30 0
250 %33 = OpImageSampleImplicitLod %v4float %31 %32
251 OpStore %outColor %33
252 OpReturn
253 OpFunctionEnd
254 )";
255
256 const std::string after =
257 R"(%main = OpFunction %void None %9
258 %25 = OpLabel
259 %s0 = OpVariable %_ptr_Function_S_t Function
260 %26 = OpLoad %v2float %texCoords
261 %27 = OpLoad %S_t %s0
262 %28 = OpCompositeInsert %S_t %26 %27 0
263 %29 = OpLoad %15 %sampler15
264 %30 = OpCompositeInsert %S_t %29 %28 2
265 OpStore %s0 %30
266 %33 = OpImageSampleImplicitLod %v4float %29 %26
267 OpStore %outColor %33
268 OpReturn
269 OpFunctionEnd
270 )";
271
272 SinglePassRunAndCheck<SimplificationPass>(predefs + before, predefs + after,
273 true, true);
274 }
275
TEST_F(InsertExtractElimTest,OptimizeNestedStruct)276 TEST_F(InsertExtractElimTest, OptimizeNestedStruct) {
277 // The following HLSL has been pre-optimized to get the SPIR-V:
278 // struct S0
279 // {
280 // int x;
281 // SamplerState ss;
282 // };
283 //
284 // struct S1
285 // {
286 // float b;
287 // S0 s0;
288 // };
289 //
290 // struct S2
291 // {
292 // int a1;
293 // S1 resources;
294 // };
295 //
296 // SamplerState samp;
297 // Texture2D tex;
298 //
299 // float4 main(float4 vpos : VPOS) : COLOR0
300 // {
301 // S1 s1;
302 // S2 s2;
303 // s1.s0.ss = samp;
304 // s2.resources = s1;
305 // return tex.Sample(s2.resources.s0.ss, float2(0.5));
306 // }
307
308 const std::string predefs =
309 R"(OpCapability Shader
310 %1 = OpExtInstImport "GLSL.std.450"
311 OpMemoryModel Logical GLSL450
312 OpEntryPoint Fragment %main "main" %_entryPointOutput
313 OpExecutionMode %main OriginUpperLeft
314 OpSource HLSL 500
315 OpName %main "main"
316 OpName %S0 "S0"
317 OpMemberName %S0 0 "x"
318 OpMemberName %S0 1 "ss"
319 OpName %S1 "S1"
320 OpMemberName %S1 0 "b"
321 OpMemberName %S1 1 "s0"
322 OpName %samp "samp"
323 OpName %S2 "S2"
324 OpMemberName %S2 0 "a1"
325 OpMemberName %S2 1 "resources"
326 OpName %tex "tex"
327 OpName %_entryPointOutput "@entryPointOutput"
328 OpDecorate %samp DescriptorSet 0
329 OpDecorate %tex DescriptorSet 0
330 OpDecorate %_entryPointOutput Location 0
331 %void = OpTypeVoid
332 %10 = OpTypeFunction %void
333 %float = OpTypeFloat 32
334 %v4float = OpTypeVector %float 4
335 %_ptr_Function_v4float = OpTypePointer Function %v4float
336 %14 = OpTypeFunction %v4float %_ptr_Function_v4float
337 %int = OpTypeInt 32 1
338 %16 = OpTypeSampler
339 %S0 = OpTypeStruct %int %16
340 %S1 = OpTypeStruct %float %S0
341 %_ptr_Function_S1 = OpTypePointer Function %S1
342 %int_1 = OpConstant %int 1
343 %_ptr_UniformConstant_16 = OpTypePointer UniformConstant %16
344 %samp = OpVariable %_ptr_UniformConstant_16 UniformConstant
345 %_ptr_Function_16 = OpTypePointer Function %16
346 %S2 = OpTypeStruct %int %S1
347 %_ptr_Function_S2 = OpTypePointer Function %S2
348 %22 = OpTypeImage %float 2D 0 0 0 1 Unknown
349 %_ptr_UniformConstant_22 = OpTypePointer UniformConstant %22
350 %tex = OpVariable %_ptr_UniformConstant_22 UniformConstant
351 %24 = OpTypeSampledImage %22
352 %v2float = OpTypeVector %float 2
353 %float_0_5 = OpConstant %float 0.5
354 %27 = OpConstantComposite %v2float %float_0_5 %float_0_5
355 %_ptr_Input_v4float = OpTypePointer Input %v4float
356 %_ptr_Output_v4float = OpTypePointer Output %v4float
357 %_entryPointOutput = OpVariable %_ptr_Output_v4float Output
358 )";
359
360 const std::string before =
361 R"(%main = OpFunction %void None %10
362 %30 = OpLabel
363 %31 = OpVariable %_ptr_Function_S1 Function
364 %32 = OpVariable %_ptr_Function_S2 Function
365 %33 = OpLoad %16 %samp
366 %34 = OpLoad %S1 %31
367 %35 = OpCompositeInsert %S1 %33 %34 1 1
368 OpStore %31 %35
369 %36 = OpLoad %S2 %32
370 %37 = OpCompositeInsert %S2 %35 %36 1
371 OpStore %32 %37
372 %38 = OpLoad %22 %tex
373 %39 = OpCompositeExtract %16 %37 1 1 1
374 %40 = OpSampledImage %24 %38 %39
375 %41 = OpImageSampleImplicitLod %v4float %40 %27
376 OpStore %_entryPointOutput %41
377 OpReturn
378 OpFunctionEnd
379 )";
380
381 const std::string after =
382 R"(%main = OpFunction %void None %10
383 %30 = OpLabel
384 %31 = OpVariable %_ptr_Function_S1 Function
385 %32 = OpVariable %_ptr_Function_S2 Function
386 %33 = OpLoad %16 %samp
387 %34 = OpLoad %S1 %31
388 %35 = OpCompositeInsert %S1 %33 %34 1 1
389 OpStore %31 %35
390 %36 = OpLoad %S2 %32
391 %37 = OpCompositeInsert %S2 %35 %36 1
392 OpStore %32 %37
393 %38 = OpLoad %22 %tex
394 %40 = OpSampledImage %24 %38 %33
395 %41 = OpImageSampleImplicitLod %v4float %40 %27
396 OpStore %_entryPointOutput %41
397 OpReturn
398 OpFunctionEnd
399 )";
400
401 SinglePassRunAndCheck<SimplificationPass>(predefs + before, predefs + after,
402 true, true);
403 }
404
TEST_F(InsertExtractElimTest,ConflictingInsertPreventsOptimization)405 TEST_F(InsertExtractElimTest, ConflictingInsertPreventsOptimization) {
406 // Note: The SPIR-V assembly has had store/load elimination
407 // performed to allow the inserts and extracts to directly
408 // reference each other.
409 //
410 // #version 140
411 //
412 // in vec4 BaseColor;
413 //
414 // struct S_t {
415 // vec4 v0;
416 // vec4 v1;
417 // };
418 //
419 // void main()
420 // {
421 // S_t s0;
422 // s0.v1 = BaseColor;
423 // s0.v1[2] = 0.0;
424 // gl_FragColor = s0.v1;
425 // }
426
427 const std::string assembly =
428 R"(OpCapability Shader
429 %1 = OpExtInstImport "GLSL.std.450"
430 OpMemoryModel Logical GLSL450
431 OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
432 OpExecutionMode %main OriginUpperLeft
433 OpSource GLSL 140
434 OpName %main "main"
435 OpName %S_t "S_t"
436 OpMemberName %S_t 0 "v0"
437 OpMemberName %S_t 1 "v1"
438 OpName %s0 "s0"
439 OpName %BaseColor "BaseColor"
440 OpName %gl_FragColor "gl_FragColor"
441 %void = OpTypeVoid
442 %8 = OpTypeFunction %void
443 %float = OpTypeFloat 32
444 %v4float = OpTypeVector %float 4
445 %S_t = OpTypeStruct %v4float %v4float
446 %_ptr_Function_S_t = OpTypePointer Function %S_t
447 %int = OpTypeInt 32 1
448 %int_1 = OpConstant %int 1
449 %float_0 = OpConstant %float 0
450 %_ptr_Input_v4float = OpTypePointer Input %v4float
451 %BaseColor = OpVariable %_ptr_Input_v4float Input
452 %_ptr_Function_v4float = OpTypePointer Function %v4float
453 %_ptr_Output_v4float = OpTypePointer Output %v4float
454 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
455 %main = OpFunction %void None %8
456 %18 = OpLabel
457 %s0 = OpVariable %_ptr_Function_S_t Function
458 %19 = OpLoad %v4float %BaseColor
459 %20 = OpLoad %S_t %s0
460 %21 = OpCompositeInsert %S_t %19 %20 1
461 %22 = OpCompositeInsert %S_t %float_0 %21 1 2
462 OpStore %s0 %22
463 %23 = OpCompositeExtract %v4float %22 1
464 OpStore %gl_FragColor %23
465 OpReturn
466 OpFunctionEnd
467 )";
468
469 SinglePassRunAndCheck<SimplificationPass>(assembly, assembly, true, true);
470 }
471
TEST_F(InsertExtractElimTest,ConflictingInsertPreventsOptimization2)472 TEST_F(InsertExtractElimTest, ConflictingInsertPreventsOptimization2) {
473 // Note: The SPIR-V assembly has had store/load elimination
474 // performed to allow the inserts and extracts to directly
475 // reference each other.
476 //
477 // #version 140
478 //
479 // in vec4 BaseColor;
480 //
481 // struct S_t {
482 // vec4 v0;
483 // vec4 v1;
484 // };
485 //
486 // void main()
487 // {
488 // S_t s0;
489 // s0.v1[1] = 1.0; // dead
490 // s0.v1 = Baseline;
491 // gl_FragColor = vec4(s0.v1[1], 0.0, 0.0, 0.0);
492 // }
493
494 const std::string before_predefs =
495 R"(OpCapability Shader
496 %1 = OpExtInstImport "GLSL.std.450"
497 OpMemoryModel Logical GLSL450
498 OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
499 OpExecutionMode %main OriginUpperLeft
500 OpSource GLSL 140
501 OpName %main "main"
502 OpName %S_t "S_t"
503 OpMemberName %S_t 0 "v0"
504 OpMemberName %S_t 1 "v1"
505 OpName %s0 "s0"
506 OpName %BaseColor "BaseColor"
507 OpName %gl_FragColor "gl_FragColor"
508 %void = OpTypeVoid
509 %8 = OpTypeFunction %void
510 %float = OpTypeFloat 32
511 %v4float = OpTypeVector %float 4
512 %S_t = OpTypeStruct %v4float %v4float
513 %_ptr_Function_S_t = OpTypePointer Function %S_t
514 %int = OpTypeInt 32 1
515 %int_1 = OpConstant %int 1
516 %float_1 = OpConstant %float 1
517 %uint = OpTypeInt 32 0
518 %uint_1 = OpConstant %uint 1
519 %_ptr_Function_float = OpTypePointer Function %float
520 %_ptr_Input_v4float = OpTypePointer Input %v4float
521 %BaseColor = OpVariable %_ptr_Input_v4float Input
522 %_ptr_Function_v4float = OpTypePointer Function %v4float
523 %_ptr_Output_v4float = OpTypePointer Output %v4float
524 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
525 %float_0 = OpConstant %float 0
526 )";
527
528 const std::string after_predefs =
529 R"(OpCapability Shader
530 %1 = OpExtInstImport "GLSL.std.450"
531 OpMemoryModel Logical GLSL450
532 OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
533 OpExecutionMode %main OriginUpperLeft
534 OpSource GLSL 140
535 OpName %main "main"
536 OpName %S_t "S_t"
537 OpMemberName %S_t 0 "v0"
538 OpMemberName %S_t 1 "v1"
539 OpName %s0 "s0"
540 OpName %BaseColor "BaseColor"
541 OpName %gl_FragColor "gl_FragColor"
542 %void = OpTypeVoid
543 %8 = OpTypeFunction %void
544 %float = OpTypeFloat 32
545 %v4float = OpTypeVector %float 4
546 %S_t = OpTypeStruct %v4float %v4float
547 %_ptr_Function_S_t = OpTypePointer Function %S_t
548 %int = OpTypeInt 32 1
549 %int_1 = OpConstant %int 1
550 %float_1 = OpConstant %float 1
551 %uint = OpTypeInt 32 0
552 %uint_1 = OpConstant %uint 1
553 %_ptr_Function_float = OpTypePointer Function %float
554 %_ptr_Input_v4float = OpTypePointer Input %v4float
555 %BaseColor = OpVariable %_ptr_Input_v4float Input
556 %_ptr_Function_v4float = OpTypePointer Function %v4float
557 %_ptr_Output_v4float = OpTypePointer Output %v4float
558 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
559 %float_0 = OpConstant %float 0
560 )";
561
562 const std::string before =
563 R"(%main = OpFunction %void None %8
564 %22 = OpLabel
565 %s0 = OpVariable %_ptr_Function_S_t Function
566 %23 = OpLoad %S_t %s0
567 %24 = OpCompositeInsert %S_t %float_1 %23 1 1
568 %25 = OpLoad %v4float %BaseColor
569 %26 = OpCompositeInsert %S_t %25 %24 1
570 %27 = OpCompositeExtract %float %26 1 1
571 %28 = OpCompositeConstruct %v4float %27 %float_0 %float_0 %float_0
572 OpStore %gl_FragColor %28
573 OpReturn
574 OpFunctionEnd
575 )";
576
577 const std::string after =
578 R"(%main = OpFunction %void None %8
579 %22 = OpLabel
580 %s0 = OpVariable %_ptr_Function_S_t Function
581 %23 = OpLoad %S_t %s0
582 %24 = OpCompositeInsert %S_t %float_1 %23 1 1
583 %25 = OpLoad %v4float %BaseColor
584 %26 = OpCompositeInsert %S_t %25 %24 1
585 %27 = OpCompositeExtract %float %25 1
586 %28 = OpCompositeConstruct %v4float %27 %float_0 %float_0 %float_0
587 OpStore %gl_FragColor %28
588 OpReturn
589 OpFunctionEnd
590 )";
591
592 SinglePassRunAndCheck<SimplificationPass>(before_predefs + before,
593 after_predefs + after, true, true);
594 }
595
TEST_F(InsertExtractElimTest,MixWithConstants)596 TEST_F(InsertExtractElimTest, MixWithConstants) {
597 // Extract component of FMix with 0.0 or 1.0 as the a-value.
598 //
599 // Note: The SPIR-V assembly has had store/load elimination
600 // performed to allow the inserts and extracts to directly
601 // reference each other.
602 //
603 // #version 450
604 //
605 // layout (location=0) in float bc;
606 // layout (location=1) in float bc2;
607 // layout (location=2) in float m;
608 // layout (location=3) in float m2;
609 // layout (location=0) out vec4 OutColor;
610 //
611 // void main()
612 // {
613 // vec4 bcv = vec4(bc, bc2, 0.0, 1.0);
614 // vec4 bcv2 = vec4(bc2, bc, 1.0, 0.0);
615 // vec4 v = mix(bcv, bcv2, vec4(0.0,1.0,m,m2));
616 // OutColor = vec4(v.y);
617 // }
618
619 const std::string predefs =
620 R"(OpCapability Shader
621 %1 = OpExtInstImport "GLSL.std.450"
622 OpMemoryModel Logical GLSL450
623 OpEntryPoint Fragment %main "main" %bc %bc2 %m %m2 %OutColor
624 OpExecutionMode %main OriginUpperLeft
625 OpSource GLSL 450
626 OpName %main "main"
627 OpName %bc "bc"
628 OpName %bc2 "bc2"
629 OpName %m "m"
630 OpName %m2 "m2"
631 OpName %OutColor "OutColor"
632 OpDecorate %bc Location 0
633 OpDecorate %bc2 Location 1
634 OpDecorate %m Location 2
635 OpDecorate %m2 Location 3
636 OpDecorate %OutColor Location 0
637 %void = OpTypeVoid
638 %9 = OpTypeFunction %void
639 %float = OpTypeFloat 32
640 %v4float = OpTypeVector %float 4
641 %_ptr_Function_v4float = OpTypePointer Function %v4float
642 %_ptr_Input_float = OpTypePointer Input %float
643 %bc = OpVariable %_ptr_Input_float Input
644 %bc2 = OpVariable %_ptr_Input_float Input
645 %float_0 = OpConstant %float 0
646 %float_1 = OpConstant %float 1
647 %m = OpVariable %_ptr_Input_float Input
648 %m2 = OpVariable %_ptr_Input_float Input
649 %_ptr_Output_v4float = OpTypePointer Output %v4float
650 %OutColor = OpVariable %_ptr_Output_v4float Output
651 %uint = OpTypeInt 32 0
652 %_ptr_Function_float = OpTypePointer Function %float
653 )";
654
655 const std::string before =
656 R"(%main = OpFunction %void None %9
657 %19 = OpLabel
658 %20 = OpLoad %float %bc
659 %21 = OpLoad %float %bc2
660 %22 = OpCompositeConstruct %v4float %20 %21 %float_0 %float_1
661 %23 = OpLoad %float %bc2
662 %24 = OpLoad %float %bc
663 %25 = OpCompositeConstruct %v4float %23 %24 %float_1 %float_0
664 %26 = OpLoad %float %m
665 %27 = OpLoad %float %m2
666 %28 = OpCompositeConstruct %v4float %float_0 %float_1 %26 %27
667 %29 = OpExtInst %v4float %1 FMix %22 %25 %28
668 %30 = OpCompositeExtract %float %29 1
669 %31 = OpCompositeConstruct %v4float %30 %30 %30 %30
670 OpStore %OutColor %31
671 OpReturn
672 OpFunctionEnd
673 )";
674
675 const std::string after =
676 R"(%main = OpFunction %void None %9
677 %19 = OpLabel
678 %20 = OpLoad %float %bc
679 %21 = OpLoad %float %bc2
680 %22 = OpCompositeConstruct %v4float %20 %21 %float_0 %float_1
681 %23 = OpLoad %float %bc2
682 %24 = OpLoad %float %bc
683 %25 = OpCompositeConstruct %v4float %23 %24 %float_1 %float_0
684 %26 = OpLoad %float %m
685 %27 = OpLoad %float %m2
686 %28 = OpCompositeConstruct %v4float %float_0 %float_1 %26 %27
687 %29 = OpExtInst %v4float %1 FMix %22 %25 %28
688 %31 = OpCompositeConstruct %v4float %24 %24 %24 %24
689 OpStore %OutColor %31
690 OpReturn
691 OpFunctionEnd
692 )";
693
694 SinglePassRunAndCheck<SimplificationPass>(predefs + before, predefs + after,
695 true, true);
696 }
697
TEST_F(InsertExtractElimTest,VectorShuffle1)698 TEST_F(InsertExtractElimTest, VectorShuffle1) {
699 // Extract component from first vector in VectorShuffle
700 //
701 // Note: The SPIR-V assembly has had store/load elimination
702 // performed to allow the inserts and extracts to directly
703 // reference each other.
704 //
705 // #version 450
706 //
707 // layout (location=0) in float bc;
708 // layout (location=1) in float bc2;
709 // layout (location=0) out vec4 OutColor;
710 //
711 // void main()
712 // {
713 // vec4 bcv = vec4(bc, bc2, 0.0, 1.0);
714 // vec4 v = bcv.zwxy;
715 // OutColor = vec4(v.y);
716 // }
717
718 const std::string predefs_before =
719 R"(OpCapability Shader
720 %1 = OpExtInstImport "GLSL.std.450"
721 OpMemoryModel Logical GLSL450
722 OpEntryPoint Fragment %main "main" %bc %bc2 %OutColor
723 OpExecutionMode %main OriginUpperLeft
724 OpSource GLSL 450
725 OpName %main "main"
726 OpName %bc "bc"
727 OpName %bc2 "bc2"
728 OpName %OutColor "OutColor"
729 OpDecorate %bc Location 0
730 OpDecorate %bc2 Location 1
731 OpDecorate %OutColor Location 0
732 %void = OpTypeVoid
733 %7 = OpTypeFunction %void
734 %float = OpTypeFloat 32
735 %v4float = OpTypeVector %float 4
736 %_ptr_Function_v4float = OpTypePointer Function %v4float
737 %_ptr_Input_float = OpTypePointer Input %float
738 %bc = OpVariable %_ptr_Input_float Input
739 %bc2 = OpVariable %_ptr_Input_float Input
740 %float_0 = OpConstant %float 0
741 %float_1 = OpConstant %float 1
742 %_ptr_Output_v4float = OpTypePointer Output %v4float
743 %OutColor = OpVariable %_ptr_Output_v4float Output
744 %uint = OpTypeInt 32 0
745 %_ptr_Function_float = OpTypePointer Function %float
746 )";
747
748 const std::string predefs_after = predefs_before +
749 "%24 = OpConstantComposite %v4float "
750 "%float_1 %float_1 %float_1 %float_1\n";
751
752 const std::string before =
753 R"(%main = OpFunction %void None %7
754 %17 = OpLabel
755 %18 = OpLoad %float %bc
756 %19 = OpLoad %float %bc2
757 %20 = OpCompositeConstruct %v4float %18 %19 %float_0 %float_1
758 %21 = OpVectorShuffle %v4float %20 %20 2 3 0 1
759 %22 = OpCompositeExtract %float %21 1
760 %23 = OpCompositeConstruct %v4float %22 %22 %22 %22
761 OpStore %OutColor %23
762 OpReturn
763 OpFunctionEnd
764 )";
765
766 const std::string after =
767 R"(%main = OpFunction %void None %7
768 %17 = OpLabel
769 %18 = OpLoad %float %bc
770 %19 = OpLoad %float %bc2
771 %20 = OpCompositeConstruct %v4float %18 %19 %float_0 %float_1
772 %21 = OpVectorShuffle %v4float %20 %20 2 3 0 1
773 OpStore %OutColor %24
774 OpReturn
775 OpFunctionEnd
776 )";
777
778 SinglePassRunAndCheck<SimplificationPass>(predefs_before + before,
779 predefs_after + after, true, true);
780 }
781
TEST_F(InsertExtractElimTest,VectorShuffle2)782 TEST_F(InsertExtractElimTest, VectorShuffle2) {
783 // Extract component from second vector in VectorShuffle
784 // Identical to test VectorShuffle1 except for the vector
785 // shuffle index of 7.
786 //
787 // Note: The SPIR-V assembly has had store/load elimination
788 // performed to allow the inserts and extracts to directly
789 // reference each other.
790 //
791 // #version 450
792 //
793 // layout (location=0) in float bc;
794 // layout (location=1) in float bc2;
795 // layout (location=0) out vec4 OutColor;
796 //
797 // void main()
798 // {
799 // vec4 bcv = vec4(bc, bc2, 0.0, 1.0);
800 // vec4 v = bcv.zwxy;
801 // OutColor = vec4(v.y);
802 // }
803
804 const std::string predefs_before =
805 R"(OpCapability Shader
806 %1 = OpExtInstImport "GLSL.std.450"
807 OpMemoryModel Logical GLSL450
808 OpEntryPoint Fragment %main "main" %bc %bc2 %OutColor
809 OpExecutionMode %main OriginUpperLeft
810 OpSource GLSL 450
811 OpName %main "main"
812 OpName %bc "bc"
813 OpName %bc2 "bc2"
814 OpName %OutColor "OutColor"
815 OpDecorate %bc Location 0
816 OpDecorate %bc2 Location 1
817 OpDecorate %OutColor Location 0
818 %void = OpTypeVoid
819 %7 = OpTypeFunction %void
820 %float = OpTypeFloat 32
821 %v4float = OpTypeVector %float 4
822 %_ptr_Function_v4float = OpTypePointer Function %v4float
823 %_ptr_Input_float = OpTypePointer Input %float
824 %bc = OpVariable %_ptr_Input_float Input
825 %bc2 = OpVariable %_ptr_Input_float Input
826 %float_0 = OpConstant %float 0
827 %float_1 = OpConstant %float 1
828 %_ptr_Output_v4float = OpTypePointer Output %v4float
829 %OutColor = OpVariable %_ptr_Output_v4float Output
830 %uint = OpTypeInt 32 0
831 %_ptr_Function_float = OpTypePointer Function %float
832 )";
833
834 const std::string predefs_after =
835 R"(OpCapability Shader
836 %1 = OpExtInstImport "GLSL.std.450"
837 OpMemoryModel Logical GLSL450
838 OpEntryPoint Fragment %main "main" %bc %bc2 %OutColor
839 OpExecutionMode %main OriginUpperLeft
840 OpSource GLSL 450
841 OpName %main "main"
842 OpName %bc "bc"
843 OpName %bc2 "bc2"
844 OpName %OutColor "OutColor"
845 OpDecorate %bc Location 0
846 OpDecorate %bc2 Location 1
847 OpDecorate %OutColor Location 0
848 %void = OpTypeVoid
849 %7 = OpTypeFunction %void
850 %float = OpTypeFloat 32
851 %v4float = OpTypeVector %float 4
852 %_ptr_Function_v4float = OpTypePointer Function %v4float
853 %_ptr_Input_float = OpTypePointer Input %float
854 %bc = OpVariable %_ptr_Input_float Input
855 %bc2 = OpVariable %_ptr_Input_float Input
856 %float_0 = OpConstant %float 0
857 %float_1 = OpConstant %float 1
858 %_ptr_Output_v4float = OpTypePointer Output %v4float
859 %OutColor = OpVariable %_ptr_Output_v4float Output
860 %uint = OpTypeInt 32 0
861 %_ptr_Function_float = OpTypePointer Function %float
862 %24 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
863 )";
864
865 const std::string before =
866 R"(%main = OpFunction %void None %7
867 %17 = OpLabel
868 %18 = OpLoad %float %bc
869 %19 = OpLoad %float %bc2
870 %20 = OpCompositeConstruct %v4float %18 %19 %float_0 %float_1
871 %21 = OpVectorShuffle %v4float %20 %20 2 7 0 1
872 %22 = OpCompositeExtract %float %21 1
873 %23 = OpCompositeConstruct %v4float %22 %22 %22 %22
874 OpStore %OutColor %23
875 OpReturn
876 OpFunctionEnd
877 )";
878
879 const std::string after =
880 R"(%main = OpFunction %void None %7
881 %17 = OpLabel
882 %18 = OpLoad %float %bc
883 %19 = OpLoad %float %bc2
884 %20 = OpCompositeConstruct %v4float %18 %19 %float_0 %float_1
885 %21 = OpVectorShuffle %v4float %20 %20 2 7 0 1
886 OpStore %OutColor %24
887 OpReturn
888 OpFunctionEnd
889 )";
890
891 SinglePassRunAndCheck<SimplificationPass>(predefs_before + before,
892 predefs_after + after, true, true);
893 }
894
895 // TODO(greg-lunarg): Add tests to verify handling of these cases:
896 //
897
898 } // namespace
899 } // namespace opt
900 } // namespace spvtools
901