1 //
2 // Copyright 2017 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // MSLOutput_test.cpp:
7 // Tests for MSL output.
8 //
9
10 #include <regex>
11 #include "GLSLANG/ShaderLang.h"
12 #include "angle_gl.h"
13 #include "gtest/gtest.h"
14 #include "tests/test_utils/compiler_test.h"
15
16 using namespace sh;
17
18 class MSLOutputTestBase : public MatchOutputCodeTest
19 {
20 public:
MSLOutputTestBase(GLenum shaderType)21 MSLOutputTestBase(GLenum shaderType) : MatchOutputCodeTest(shaderType, SH_MSL_METAL_OUTPUT)
22 {
23 setDefaultCompileOptions(defaultOptions());
24 }
defaultOptions()25 static ShCompileOptions defaultOptions()
26 {
27 ShCompileOptions options = {};
28 // Default options that are forced for MSL output.
29 options.rescopeGlobalVariables = true;
30 options.simplifyLoopConditions = true;
31 options.initializeUninitializedLocals = true;
32 options.separateCompoundStructDeclarations = true;
33 // The tests also test that validation succeeds. This should be also the
34 // default forced option, but currently MSL backend does not generate
35 // valid trees. Once validateAST is forced, move to above hunk.
36 options.validateAST = true;
37 return options;
38 }
39 };
40
41 class MSLOutputTest : public MSLOutputTestBase
42 {
43 public:
MSLOutputTest()44 MSLOutputTest() : MSLOutputTestBase(GL_FRAGMENT_SHADER) {}
45 };
46
47 class MSLVertexOutputTest : public MSLOutputTestBase
48 {
49 public:
MSLVertexOutputTest()50 MSLVertexOutputTest() : MSLOutputTestBase(GL_VERTEX_SHADER) {}
51 };
52
53 // Test that having dynamic indexing of a vector inside the right hand side of logical or doesn't
54 // trigger asserts in MSL output.
TEST_F(MSLOutputTest,DynamicIndexingOfVectorOnRightSideOfLogicalOr)55 TEST_F(MSLOutputTest, DynamicIndexingOfVectorOnRightSideOfLogicalOr)
56 {
57 const std::string &shaderString =
58 "#version 300 es\n"
59 "precision highp float;\n"
60 "out vec4 my_FragColor;\n"
61 "uniform int u1;\n"
62 "void main() {\n"
63 " bvec4 v = bvec4(true, true, true, false);\n"
64 " my_FragColor = vec4(v[u1 + 1] || v[u1]);\n"
65 "}\n";
66 compile(shaderString);
67 }
68
69 // Test that having an array constructor as a statement doesn't trigger an assert in MSL output.
TEST_F(MSLOutputTest,ArrayConstructorStatement)70 TEST_F(MSLOutputTest, ArrayConstructorStatement)
71 {
72 const std::string &shaderString =
73 R"(#version 300 es
74 precision mediump float;
75 out vec4 outColor;
76 void main()
77 {
78 outColor = vec4(0.0, 0.0, 0.0, 1.0);
79 float[1](outColor[1]++);
80 })";
81 compile(shaderString);
82 }
83
84 // Test an array of arrays constructor as a statement.
TEST_F(MSLOutputTest,ArrayOfArraysStatement)85 TEST_F(MSLOutputTest, ArrayOfArraysStatement)
86 {
87 const std::string &shaderString =
88 R"(#version 310 es
89 precision mediump float;
90 out vec4 outColor;
91 void main()
92 {
93 outColor = vec4(0.0, 0.0, 0.0, 1.0);
94 float[2][2](float[2](outColor[1]++, 0.0), float[2](1.0, 2.0));
95 })";
96 compile(shaderString);
97 }
98
99 // Test dynamic indexing of a vector. This makes sure that helper functions added for dynamic
100 // indexing have correct data that subsequent traversal steps rely on.
TEST_F(MSLOutputTest,VectorDynamicIndexing)101 TEST_F(MSLOutputTest, VectorDynamicIndexing)
102 {
103 const std::string &shaderString =
104 R"(#version 300 es
105 precision mediump float;
106 out vec4 outColor;
107 uniform int i;
108 void main()
109 {
110 vec4 foo = vec4(0.0, 0.0, 0.0, 1.0);
111 foo[i] = foo[i + 1];
112 outColor = foo;
113 })";
114 compile(shaderString);
115 }
116
117 // Test returning an array from a user-defined function. This makes sure that function symbols are
118 // changed consistently when the user-defined function is changed to have an array out parameter.
TEST_F(MSLOutputTest,ArrayReturnValue)119 TEST_F(MSLOutputTest, ArrayReturnValue)
120 {
121 const std::string &shaderString =
122 R"(#version 300 es
123 precision mediump float;
124 uniform float u;
125 out vec4 outColor;
126
127 float[2] getArray(float f)
128 {
129 return float[2](f, f + 1.0);
130 }
131
132 void main()
133 {
134 float[2] arr = getArray(u);
135 outColor = vec4(arr[0], arr[1], 0.0, 1.0);
136 })";
137 compile(shaderString);
138 }
139
140 // Test that writing parameters without a name doesn't assert.
TEST_F(MSLOutputTest,ParameterWithNoName)141 TEST_F(MSLOutputTest, ParameterWithNoName)
142 {
143 const std::string &shaderString =
144 R"(precision mediump float;
145
146 uniform vec4 v;
147
148 vec4 s(vec4)
149 {
150 return v;
151 }
152 void main()
153 {
154 gl_FragColor = s(v);
155 })";
156 compile(shaderString);
157 }
158
TEST_F(MSLOutputTest,Macro)159 TEST_F(MSLOutputTest, Macro)
160 {
161 const std::string &shaderString =
162 R"(#version 300 es
163 precision highp float;
164
165 #define FOO vec4
166
167 out vec4 outColor;
168
169 void main()
170 {
171 outColor = FOO(1.0, 2.0, 3.0, 4.0);
172 })";
173 compile(shaderString);
174 }
175
TEST_F(MSLOutputTest,UniformSimple)176 TEST_F(MSLOutputTest, UniformSimple)
177 {
178 const std::string &shaderString =
179 R"(#version 300 es
180 precision highp float;
181
182 out vec4 outColor;
183 uniform float x;
184
185 void main()
186 {
187 outColor = vec4(x, x, x, x);
188 })";
189 compile(shaderString);
190 }
191
TEST_F(MSLOutputTest,FragmentOutSimple)192 TEST_F(MSLOutputTest, FragmentOutSimple)
193 {
194 const std::string &shaderString =
195 R"(#version 300 es
196 precision highp float;
197
198 out vec4 outColor;
199
200 void main()
201 {
202 outColor = vec4(1.0, 2.0, 3.0, 4.0);
203 })";
204 compile(shaderString);
205 }
206
TEST_F(MSLOutputTest,FragmentOutIndirect1)207 TEST_F(MSLOutputTest, FragmentOutIndirect1)
208 {
209 const std::string &shaderString =
210 R"(#version 300 es
211 precision highp float;
212
213 out vec4 outColor;
214
215 void foo()
216 {
217 outColor = vec4(1.0, 2.0, 3.0, 4.0);
218 }
219
220 void bar()
221 {
222 foo();
223 }
224
225 void main()
226 {
227 bar();
228 })";
229 compile(shaderString);
230 }
231
TEST_F(MSLOutputTest,FragmentOutIndirect2)232 TEST_F(MSLOutputTest, FragmentOutIndirect2)
233 {
234 const std::string &shaderString =
235 R"(#version 300 es
236 precision highp float;
237
238 out vec4 outColor;
239
240 void foo();
241
242 void bar()
243 {
244 foo();
245 }
246
247 void foo()
248 {
249 outColor = vec4(1.0, 2.0, 3.0, 4.0);
250 }
251
252 void main()
253 {
254 bar();
255 })";
256 compile(shaderString);
257 }
258
TEST_F(MSLOutputTest,FragmentOutIndirect3)259 TEST_F(MSLOutputTest, FragmentOutIndirect3)
260 {
261 const std::string &shaderString =
262 R"(#version 300 es
263 precision highp float;
264
265 out vec4 outColor;
266
267 float foo(float x, float y)
268 {
269 outColor = vec4(x, y, 3.0, 4.0);
270 return 7.0;
271 }
272
273 float bar(float x)
274 {
275 return foo(x, 2.0);
276 }
277
278 float baz()
279 {
280 return 13.0;
281 }
282
283 float identity(float x)
284 {
285 return x;
286 }
287
288 void main()
289 {
290 identity(bar(baz()));
291 })";
292 compile(shaderString);
293 }
294
TEST_F(MSLOutputTest,VertexInOut)295 TEST_F(MSLOutputTest, VertexInOut)
296 {
297 const std::string &shaderString =
298 R"(#version 300 es
299 precision highp float;
300 in float in0;
301 out float out0;
302 void main()
303 {
304 out0 = in0;
305 })";
306 compile(shaderString);
307 }
308
TEST_F(MSLOutputTest,SymbolSharing)309 TEST_F(MSLOutputTest, SymbolSharing)
310 {
311 const std::string &shaderString =
312 R"(#version 300 es
313 precision highp float;
314
315 out vec4 outColor;
316
317 struct Foo {
318 float x;
319 float y;
320 };
321
322 void doFoo(Foo foo, float zw);
323
324 void doFoo(Foo foo, float zw)
325 {
326 foo.x = foo.y;
327 outColor = vec4(foo.x, foo.y, zw, zw);
328 }
329
330 void main()
331 {
332 Foo foo;
333 foo.x = 2.0;
334 foo.y = 2.0;
335 doFoo(foo, 3.0);
336 })";
337 compile(shaderString);
338 }
339
TEST_F(MSLOutputTest,StructDecl)340 TEST_F(MSLOutputTest, StructDecl)
341 {
342 const std::string &shaderString =
343 R"(#version 300 es
344 precision highp float;
345
346 out float out0;
347
348 struct Foo {
349 float value;
350 };
351
352 void main()
353 {
354 Foo foo;
355 out0 = foo.value;
356 }
357 )";
358 compile(shaderString);
359 }
360
TEST_F(MSLOutputTest,Structs)361 TEST_F(MSLOutputTest, Structs)
362 {
363 const std::string &shaderString =
364 R"(#version 300 es
365 precision highp float;
366
367 struct Foo {
368 float value;
369 };
370
371 out vec4 out0;
372
373 struct Bar {
374 Foo foo;
375 };
376
377 void go();
378
379 uniform UniInstance {
380 Bar bar;
381 float instance;
382 } uniInstance;
383
384 uniform UniGlobal {
385 Foo foo;
386 float global;
387 };
388
389 void main()
390 {
391 go();
392 }
393
394 struct Baz {
395 Bar bar;
396 } baz;
397
398 void go()
399 {
400 out0.x = baz.bar.foo.value;
401 out0.y = global;
402 out0.z = uniInstance.instance;
403 out0.w = 0.0;
404 }
405
406 )";
407 compile(shaderString);
408 }
409
TEST_F(MSLOutputTest,KeywordConflict)410 TEST_F(MSLOutputTest, KeywordConflict)
411 {
412 const std::string &shaderString =
413 R"(#version 300 es
414 precision highp float;
415
416 struct fragment {
417 float kernel;
418 } device;
419
420 struct Foo {
421 fragment frag;
422 } foo;
423
424 out float vertex;
425 float kernel;
426
427 float stage_in(float x)
428 {
429 return x;
430 }
431
432 void metal(float metal, float fragment);
433 void metal(float metal, float fragment)
434 {
435 vertex = metal * fragment * foo.frag.kernel;
436 }
437
438 void main()
439 {
440 metal(stage_in(stage_in(kernel * device.kernel)), foo.frag.kernel);
441 })";
442 compile(shaderString);
443 }
444
TEST_F(MSLVertexOutputTest,Vertex)445 TEST_F(MSLVertexOutputTest, Vertex)
446 {
447 const std::string &shaderString =
448 R"(#version 300 es
449 precision highp float;
450 void main()
451 {
452 gl_Position = vec4(1.0,1.0,1.0,1.0);
453 })";
454 compile(shaderString);
455 }
456
TEST_F(MSLVertexOutputTest,LastReturn)457 TEST_F(MSLVertexOutputTest, LastReturn)
458 {
459 const std::string &shaderString =
460 R"(#version 300 es
461 in highp vec4 a_position;
462 in highp vec4 a_coords;
463 out highp vec4 v_color;
464
465 void main (void)
466 {
467 gl_Position = a_position;
468 v_color = vec4(a_coords.xyz, 1.0);
469 return;
470 })";
471 compile(shaderString);
472 }
473
TEST_F(MSLOutputTest,LastReturn)474 TEST_F(MSLOutputTest, LastReturn)
475 {
476 const std::string &shaderString =
477 R"(#version 300 es
478 in mediump vec4 v_coords;
479 layout(location = 0) out mediump vec4 o_color;
480
481 void main (void)
482 {
483 o_color = vec4(v_coords.xyz, 1.0);
484 return;
485 })";
486 compile(shaderString);
487 }
488
TEST_F(MSLOutputTest,FragColor)489 TEST_F(MSLOutputTest, FragColor)
490 {
491 const std::string &shaderString = R"(
492 void main ()
493 {
494 gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);
495 })";
496 compile(shaderString);
497 }
498
TEST_F(MSLOutputTest,MatrixIn)499 TEST_F(MSLOutputTest, MatrixIn)
500 {
501 const std::string &shaderString =
502 R"(#version 300 es
503 precision highp float;
504
505 in mat4 mat;
506 out float out0;
507
508 void main()
509 {
510 out0 = mat[0][0];
511 }
512 )";
513 compile(shaderString);
514 }
515
TEST_F(MSLOutputTest,WhileTrue)516 TEST_F(MSLOutputTest, WhileTrue)
517 {
518 const std::string &shaderString =
519 R"(#version 300 es
520 precision mediump float;
521
522 uniform float uf;
523 out vec4 my_FragColor;
524
525 void main()
526 {
527 my_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
528 while (true)
529 {
530 break;
531 }
532 })";
533 compile(shaderString);
534 }
535
TEST_F(MSLOutputTest,ForTrue)536 TEST_F(MSLOutputTest, ForTrue)
537 {
538 const std::string &shaderString =
539 R"(#version 300 es
540 precision mediump float;
541
542 uniform float uf;
543 out vec4 my_FragColor;
544
545 void main()
546 {
547 my_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
548 for (;true;)
549 {
550 break;
551 }
552 })";
553 compile(shaderString);
554 }
555
TEST_F(MSLOutputTest,ForEmpty)556 TEST_F(MSLOutputTest, ForEmpty)
557 {
558 const std::string &shaderString =
559 R"(#version 300 es
560 precision mediump float;
561
562 uniform float uf;
563 out vec4 my_FragColor;
564
565 void main()
566 {
567 my_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
568 for (;;)
569 {
570 break;
571 }
572 })";
573 compile(shaderString);
574 }
575
TEST_F(MSLOutputTest,ForComplex)576 TEST_F(MSLOutputTest, ForComplex)
577 {
578 const std::string &shaderString =
579 R"(#version 300 es
580 precision mediump float;
581
582 uniform float uf;
583 out vec4 my_FragColor;
584
585 void main()
586 {
587 my_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
588 for (int i = 0, j = 2; i < j; ++i) {
589 if (i == 0) continue;
590 if (i == 42) break;
591 my_FragColor.x += float(i);
592 }
593 })";
594 compile(shaderString);
595 }
596
TEST_F(MSLOutputTest,ForSymbol)597 TEST_F(MSLOutputTest, ForSymbol)
598 {
599 const std::string &shaderString =
600 R"(#version 300 es
601 precision mediump float;
602
603 uniform float uf;
604 out vec4 my_FragColor;
605
606 void main()
607 {
608 bool cond = true;
609 for (;cond;)
610 {
611 my_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
612 cond = false;
613 }
614 })";
615 compile(shaderString);
616 }
617
TEST_F(MSLOutputTest,DoWhileSymbol)618 TEST_F(MSLOutputTest, DoWhileSymbol)
619 {
620 const std::string &shaderString =
621 R"(#version 300 es
622 precision mediump float;
623
624 uniform float uf;
625 out vec4 my_FragColor;
626
627 void main()
628 {
629 bool cond = false;
630 do
631 {
632 my_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
633 } while (cond);
634 })";
635 compile(shaderString);
636 }
637
TEST_F(MSLOutputTest,AnonymousStruct)638 TEST_F(MSLOutputTest, AnonymousStruct)
639 {
640 const std::string &shaderString =
641 R"(
642 precision mediump float;
643 struct { vec4 v; } anonStruct;
644 void main() {
645 anonStruct.v = vec4(0.0,1.0,0.0,1.0);
646 gl_FragColor = anonStruct.v;
647 })";
648 compile(shaderString);
649 // TODO(anglebug.com/42264909): This success condition is expected to fail now.
650 // When WebKit build is able to run the tests, this should be changed to something else.
651 // ASSERT_TRUE(foundInCode(SH_MSL_METAL_OUTPUT, "__unnamed"));
652 }
653
TEST_F(MSLOutputTest,GlobalRescopingSimple)654 TEST_F(MSLOutputTest, GlobalRescopingSimple)
655 {
656 const std::string &shaderString =
657 R"(#version 300 es
658 precision mediump float;
659
660 // Should rescope uf into main
661
662 float uf;
663 out vec4 my_FragColor;
664
665 void main()
666 {
667 uf += 1.0f;
668 my_FragColor = vec4(uf, 0.0, 0.0, 1.0);
669 })";
670 compile(shaderString);
671 }
672
TEST_F(MSLOutputTest,GlobalRescopingNoRescope)673 TEST_F(MSLOutputTest, GlobalRescopingNoRescope)
674 {
675 const std::string &shaderString =
676 R"(#version 300 es
677 precision mediump float;
678
679 // Should not rescope any variable
680
681 float uf;
682 out vec4 my_FragColor;
683 void modifyGlobal()
684 {
685 uf = 1.0f;
686 }
687 void main()
688 {
689 modifyGlobal();
690 my_FragColor = vec4(uf, 0.0, 0.0, 1.0);
691 })";
692 compile(shaderString);
693 }
694
TEST_F(MSLOutputTest,GlobalRescopingInitializer)695 TEST_F(MSLOutputTest, GlobalRescopingInitializer)
696 {
697 const std::string &shaderString =
698 R"(#version 300 es
699 precision mediump float;
700
701 // Should rescope uf into main
702
703 float uf = 1.0f;
704 out vec4 my_FragColor;
705
706 void main()
707 {
708 uf += 1.0;
709 my_FragColor = vec4(uf, 0.0, 0.0, 1.0);
710 })";
711 compile(shaderString);
712 }
713
TEST_F(MSLOutputTest,GlobalRescopingInitializerNoRescope)714 TEST_F(MSLOutputTest, GlobalRescopingInitializerNoRescope)
715 {
716 const std::string &shaderString =
717 R"(#version 300 es
718 precision mediump float;
719
720 // Should not rescope any variable
721
722 float uf = 1.0f;
723 out vec4 my_FragColor;
724
725 void modifyGlobal()
726 {
727 uf =+ 1.0f;
728 }
729 void main()
730 {
731 modifyGlobal();
732 my_FragColor = vec4(uf, 0.0, 0.0, 1.0);
733 })";
734 compile(shaderString);
735 }
736
TEST_F(MSLOutputTest,GlobalRescopingNestedFunction)737 TEST_F(MSLOutputTest, GlobalRescopingNestedFunction)
738 {
739 const std::string &shaderString =
740 R"(#version 300 es
741 precision mediump float;
742
743 // Should rescope a info modifyGlobal
744
745 float a = 1.0f;
746 float uf = 1.0f;
747 out vec4 my_FragColor;
748
749 void modifyGlobal()
750 {
751 uf =+ a;
752 }
753 void main()
754 {
755 modifyGlobal();
756 my_FragColor = vec4(uf, 0.0, 0.0, 1.0);
757 })";
758 compile(shaderString);
759 }
760
TEST_F(MSLOutputTest,GlobalRescopingMultipleUses)761 TEST_F(MSLOutputTest, GlobalRescopingMultipleUses)
762 {
763 const std::string &shaderString =
764 R"(#version 300 es
765 precision mediump float;
766
767 // Should rescope uf into main
768
769 float uf = 1.0f;
770 out vec4 my_FragColor;
771
772 void main()
773 {
774 uf =+ 1.0;
775 if (uf > 0.0)
776 {
777 uf =- 0.5;
778 }
779 my_FragColor = vec4(uf, 0.0, 0.0, 1.0);
780 })";
781 compile(shaderString);
782 }
783
TEST_F(MSLOutputTest,GlobalRescopingGloballyReferencedVar)784 TEST_F(MSLOutputTest, GlobalRescopingGloballyReferencedVar)
785 {
786 const std::string &shaderString =
787 R"(#version 300 es
788 precision mediump float;
789
790 // Should rescope uf into main
791
792 const float a = 1.0f;
793 float uf = a;
794 out vec4 my_FragColor;
795
796 void main()
797 {
798 my_FragColor = vec4(uf, 0.0, a, 0.0);
799 })";
800 compile(shaderString);
801 }
802
TEST_F(MSLOutputTest,GlobalRescopingDeclarationAfterFunction)803 TEST_F(MSLOutputTest, GlobalRescopingDeclarationAfterFunction)
804 {
805 const std::string &shaderString =
806 R"(#version 300 es
807 precision mediump float;
808
809 // Should rescope c and b into main
810
811 float a = 1.0f;
812 float c = 1.0f;
813 out vec4 my_FragColor;
814
815 void modifyGlobal()
816 {
817 a =+ 1.0f;
818 }
819
820 float b = 1.0f;
821
822 void main()
823 {
824 modifyGlobal();
825 my_FragColor = vec4(a, b, c, 0.0);
826 }
827
828 )";
829 compile(shaderString);
830 }
831
TEST_F(MSLOutputTest,ReusedOutVarName)832 TEST_F(MSLOutputTest, ReusedOutVarName)
833 {
834 const std::string &shaderString =
835 R"(#version 300 es
836 precision mediump float;
837
838 out vec4 my_FragColor;
839
840 void funcWith1Out(
841 out float outC) {
842 outC = 1.0;
843 }
844
845 void funcWith4Outs(
846 out float outA,
847 out float outB,
848 out float outC,
849 out float outD) {
850 outA = 1.0;
851 outB = 1.0;
852 outD = 1.0;
853 }
854
855
856 void main()
857 {
858 funcWith1Out(my_FragColor.g);
859 funcWith4Outs(my_FragColor.r, my_FragColor.g, my_FragColor.b, my_FragColor.a);
860 }
861
862 )";
863 compile(shaderString);
864 }
865
866 // Test that for loops without body do not crash. At the time of writing, constant hoisting would
867 // traverse such ASTs and crash when loop bodies were not present.
TEST_F(MSLOutputTest,RemovedForBodyNoCrash)868 TEST_F(MSLOutputTest, RemovedForBodyNoCrash)
869 {
870 const char kShader[] = R"(#version 310 es
871 void main() {
872 for(;;)if(2==0);
873 })";
874 compile(kShader);
875 }
876
877 // Test that accessing array element of array of anonymous struct instances does not fail
878 // validation.
TEST_F(MSLOutputTest,AnonymousStructArrayValidationNoCrash)879 TEST_F(MSLOutputTest, AnonymousStructArrayValidationNoCrash)
880 {
881 const char kShader[] = R"(
882 precision mediump float;
883 void main() {
884 struct { vec4 field; } s1[1];
885 gl_FragColor = s1[0].field;
886 })";
887 compile(kShader);
888 }
889
890 // Tests that rewriting varyings for per-element element access does not cause crash.
891 // At the time of writing a_ would be confused with a due to matrixes being flattened
892 // for fragment inputs, and the new variables would be given semantic names separated
893 // with _. This would cause confusion because semantic naming would filter underscores.
TEST_F(MSLOutputTest,VaryingRewriteUnderscoreNoCrash)894 TEST_F(MSLOutputTest, VaryingRewriteUnderscoreNoCrash)
895 {
896 const char kShader[] = R"(precision mediump float;
897 varying mat2 a_;
898 varying mat3 a;
899 void main(){
900 gl_FragColor = vec4(a_) + vec4(a);
901 })";
902 compile(kShader);
903 }
904
905 // Tests that rewriting varyings for per-element element access does not cause crash.
906 // Test for a clash between a[0] and a_0. Both could be clashing at a_0.
TEST_F(MSLVertexOutputTest,VaryingRewriteUnderscoreNoCrash)907 TEST_F(MSLVertexOutputTest, VaryingRewriteUnderscoreNoCrash)
908 {
909 const char kShader[] = R"(precision mediump float;
910 varying mat2 a_0;
911 varying mat3 a[1];
912 void main(){
913 a_0 = mat2(0,1,2,3);
914 a[0] = mat3(0,1,2,3,4,5,6,7,8);
915 gl_Position = vec4(1);
916 })";
917 compile(kShader);
918 }
919
920 // Tests that rewriting varyings for per-element element access does not cause crash.
921 // ES3 variant.
922 // Test for a clash between a[0] and a_0. Both could be clashing at a_0.
TEST_F(MSLVertexOutputTest,VaryingRewriteUnderscoreNoCrash2)923 TEST_F(MSLVertexOutputTest, VaryingRewriteUnderscoreNoCrash2)
924 {
925 const char kShader[] = R"(#version 300 es
926 precision mediump float;
927 out mat2 a_0;
928 out mat3 a[1];
929 void main(){
930 a_0 = mat2(0,1,2,3);
931 a[0] = mat3(0,1,2,3,4,5,6,7,8);
932 })";
933 compile(kShader);
934 }
935
936 // Tests that rewriting varyings for per-element element access does not cause crash.
937 // Test for a clash between a_[0] and a._0. Both could be clashing at a__0.
TEST_F(MSLVertexOutputTest,VaryingRewriteUnderscoreNoCrash3)938 TEST_F(MSLVertexOutputTest, VaryingRewriteUnderscoreNoCrash3)
939 {
940 const char kShader[] = R"(#version 300 es
941 precision mediump float;
942 out mat3 a_[1];
943 struct s {
944 mat2 _0;
945 };
946 out s a;
947 void main(){
948 a._0 = mat2(0,1,2,3);
949 a_[0] = mat3(0,1,2,3,4,5,6,7,8);
950 })";
951 compile(kShader);
952 }
953
954 // Tests that rewriting attributes for per-element element access does not cause crash.
955 // At the time of writing a_ would be confused with a due to matrixes being flattened
956 // for fragment inputs, and the new variables would be given semantic names separated
957 // with _. This would cause confusion because semantic naming would filter underscores.
TEST_F(MSLVertexOutputTest,AttributeRewriteUnderscoreNoCrash)958 TEST_F(MSLVertexOutputTest, AttributeRewriteUnderscoreNoCrash)
959 {
960 const char kShader[] = R"(precision mediump float;
961 attribute mat2 a_;
962 attribute mat3 a;
963 void main(){
964 gl_Position = vec4(a_) + vec4(a);
965 })";
966 compile(kShader);
967 }
968
969 // Test that emulated clip distance varying passes AST validation
TEST_F(MSLVertexOutputTest,ClipDistanceVarying)970 TEST_F(MSLVertexOutputTest, ClipDistanceVarying)
971 {
972 getResources()->ANGLE_clip_cull_distance = 1;
973 const char kShader[] = R"(#version 300 es
974 #extension GL_ANGLE_clip_cull_distance:require
975 void main(){gl_ClipDistance[0];})";
976 compile(kShader);
977 }
978
TEST_F(MSLVertexOutputTest,VertexIDIvecNoCrash)979 TEST_F(MSLVertexOutputTest, VertexIDIvecNoCrash)
980 {
981 const char kShader[] = R"(#version 300 es
982 void main(){ivec2 xy=ivec2((+gl_VertexID));gl_Position=vec4((xy), 0,1);})";
983 compile(kShader);
984 }
985
TEST_F(MSLVertexOutputTest,StructEqualityNoCrash)986 TEST_F(MSLVertexOutputTest, StructEqualityNoCrash)
987 {
988 const char kShader[] = R"(#version 300 es
989 struct S{mediump vec2 i;};S a,b;void main(){if (a==b){}})";
990 compile(kShader);
991 }
992
TEST_F(MSLOutputTest,StructAndVarDeclarationNoCrash)993 TEST_F(MSLOutputTest, StructAndVarDeclarationNoCrash)
994 {
995 const char kShader[] = R"(#version 300 es
996 void main(){struct S{mediump vec4 v;};S a;a=a,1;})";
997 compile(kShader);
998 }
999
TEST_F(MSLOutputTest,StructAndVarDeclarationSeparationNoCrash)1000 TEST_F(MSLOutputTest, StructAndVarDeclarationSeparationNoCrash)
1001 {
1002 const char kShader[] = R"(#version 300 es
1003 void main(){struct S{mediump vec4 v;}a;a=a,1;})";
1004 compile(kShader);
1005 }
1006
TEST_F(MSLOutputTest,StructAndVarDeclarationSeparationNoCrash2)1007 TEST_F(MSLOutputTest, StructAndVarDeclarationSeparationNoCrash2)
1008 {
1009 const char kShader[] = R"(#version 300 es
1010 void main(){struct S{mediump vec4 v;}a,b;a=b,1;})";
1011 compile(kShader);
1012 }
1013
TEST_F(MSLOutputTest,StructAndVarDeclarationSeparationNoCrash3)1014 TEST_F(MSLOutputTest, StructAndVarDeclarationSeparationNoCrash3)
1015 {
1016 const char kShader[] = R"(#version 300 es
1017 void main(){struct S1{mediump vec4 v;}l;struct S2{S1 s1;}s2;s2=s2,l=l,1;})";
1018 compile(kShader);
1019 }
1020
TEST_F(MSLOutputTest,MultisampleInterpolationNoCrash)1021 TEST_F(MSLOutputTest, MultisampleInterpolationNoCrash)
1022 {
1023 getResources()->OES_shader_multisample_interpolation = 1;
1024 const char kShader[] = R"(#version 300 es
1025 #extension GL_OES_shader_multisample_interpolation : require
1026 precision highp float;
1027 in float i; out vec4 c; void main() { c = vec4(interpolateAtOffset(i, vec2(i))); })";
1028 compile(kShader);
1029 }
1030
TEST_F(MSLVertexOutputTest,ClipCullDistanceNoCrash)1031 TEST_F(MSLVertexOutputTest, ClipCullDistanceNoCrash)
1032 {
1033 getResources()->ANGLE_clip_cull_distance = 1;
1034 const char kShader[] = R"(#version 300 es
1035 #extension GL_ANGLE_clip_cull_distance : require
1036 void main() { gl_Position = vec4(0.0, 0.0, 0.0, 1.0); gl_ClipDistance[1] = 1.0;})";
1037 compile(kShader);
1038 }
1039
TEST_F(MSLOutputTest,UnnamedOutParameterNoCrash)1040 TEST_F(MSLOutputTest, UnnamedOutParameterNoCrash)
1041 {
1042 const char kShader[] = R"(void f(out int){}void main(){int a;f(a);})";
1043 compile(kShader);
1044 }
1045
TEST_F(MSLOutputTest,ExplicitBoolCastsNoCrash)1046 TEST_F(MSLOutputTest, ExplicitBoolCastsNoCrash)
1047 {
1048 ShCompileOptions options = defaultOptions();
1049 options.addExplicitBoolCasts = 1;
1050 const char kShader[] = R"(
1051 precision mediump float;
1052 void main(){vec2 c;bvec2 U=bvec2(c.xx);if (U.x) gl_FragColor = vec4(1);})";
1053 compile(kShader, options);
1054 }
1055