xref: /aosp_15_r20/external/angle/src/tests/compiler_tests/MSLOutput_test.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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