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 MSLVertexOutputTest : public MatchOutputCodeTest
19 {
20 public:
MSLVertexOutputTest()21 MSLVertexOutputTest() : MatchOutputCodeTest(GL_VERTEX_SHADER, 0, SH_MSL_METAL_OUTPUT) {}
22 };
23
24 class MSLOutputTest : public MatchOutputCodeTest
25 {
26 public:
MSLOutputTest()27 MSLOutputTest() : MatchOutputCodeTest(GL_FRAGMENT_SHADER, 0, SH_MSL_METAL_OUTPUT) {}
28 };
29
30 // Test that having dynamic indexing of a vector inside the right hand side of logical or doesn't
31 // trigger asserts in MSL output.
TEST_F(MSLOutputTest,DynamicIndexingOfVectorOnRightSideOfLogicalOr)32 TEST_F(MSLOutputTest, DynamicIndexingOfVectorOnRightSideOfLogicalOr)
33 {
34 const std::string &shaderString =
35 "#version 300 es\n"
36 "precision highp float;\n"
37 "out vec4 my_FragColor;\n"
38 "uniform int u1;\n"
39 "void main() {\n"
40 " bvec4 v = bvec4(true, true, true, false);\n"
41 " my_FragColor = vec4(v[u1 + 1] || v[u1]);\n"
42 "}\n";
43 compile(shaderString, SH_VARIABLES);
44 }
45
46 // Test that having an array constructor as a statement doesn't trigger an assert in MSL output.
TEST_F(MSLOutputTest,ArrayConstructorStatement)47 TEST_F(MSLOutputTest, ArrayConstructorStatement)
48 {
49 const std::string &shaderString =
50 R"(#version 300 es
51 precision mediump float;
52 out vec4 outColor;
53 void main()
54 {
55 outColor = vec4(0.0, 0.0, 0.0, 1.0);
56 float[1](outColor[1]++);
57 })";
58 compile(shaderString, SH_VARIABLES);
59 }
60
61 // Test an array of arrays constructor as a statement.
TEST_F(MSLOutputTest,ArrayOfArraysStatement)62 TEST_F(MSLOutputTest, ArrayOfArraysStatement)
63 {
64 const std::string &shaderString =
65 R"(#version 310 es
66 precision mediump float;
67 out vec4 outColor;
68 void main()
69 {
70 outColor = vec4(0.0, 0.0, 0.0, 1.0);
71 float[2][2](float[2](outColor[1]++, 0.0), float[2](1.0, 2.0));
72 })";
73 compile(shaderString, SH_VARIABLES);
74 }
75
76 // Test dynamic indexing of a vector. This makes sure that helper functions added for dynamic
77 // indexing have correct data that subsequent traversal steps rely on.
TEST_F(MSLOutputTest,VectorDynamicIndexing)78 TEST_F(MSLOutputTest, VectorDynamicIndexing)
79 {
80 const std::string &shaderString =
81 R"(#version 300 es
82 precision mediump float;
83 out vec4 outColor;
84 uniform int i;
85 void main()
86 {
87 vec4 foo = vec4(0.0, 0.0, 0.0, 1.0);
88 foo[i] = foo[i + 1];
89 outColor = foo;
90 })";
91 compile(shaderString, SH_VARIABLES);
92 }
93
94 // Test returning an array from a user-defined function. This makes sure that function symbols are
95 // changed consistently when the user-defined function is changed to have an array out parameter.
TEST_F(MSLOutputTest,ArrayReturnValue)96 TEST_F(MSLOutputTest, ArrayReturnValue)
97 {
98 const std::string &shaderString =
99 R"(#version 300 es
100 precision mediump float;
101 uniform float u;
102 out vec4 outColor;
103
104 float[2] getArray(float f)
105 {
106 return float[2](f, f + 1.0);
107 }
108
109 void main()
110 {
111 float[2] arr = getArray(u);
112 outColor = vec4(arr[0], arr[1], 0.0, 1.0);
113 })";
114 compile(shaderString, SH_VARIABLES);
115 }
116
117 // Test that writing parameters without a name doesn't assert.
TEST_F(MSLOutputTest,ParameterWithNoName)118 TEST_F(MSLOutputTest, ParameterWithNoName)
119 {
120 const std::string &shaderString =
121 R"(precision mediump float;
122
123 uniform vec4 v;
124
125 vec4 s(vec4)
126 {
127 return v;
128 }
129 void main()
130 {
131 gl_FragColor = s(v);
132 })";
133 compile(shaderString, SH_VARIABLES);
134 }
135
TEST_F(MSLOutputTest,Macro)136 TEST_F(MSLOutputTest, Macro)
137 {
138 const std::string &shaderString =
139 R"(#version 300 es
140 precision highp float;
141
142 #define FOO vec4
143
144 out vec4 outColor;
145
146 void main()
147 {
148 outColor = FOO(1.0, 2.0, 3.0, 4.0);
149 })";
150 compile(shaderString, SH_VARIABLES);
151 }
152
TEST_F(MSLOutputTest,UniformSimple)153 TEST_F(MSLOutputTest, UniformSimple)
154 {
155 const std::string &shaderString =
156 R"(#version 300 es
157 precision highp float;
158
159 out vec4 outColor;
160 uniform float x;
161
162 void main()
163 {
164 outColor = vec4(x, x, x, x);
165 })";
166 compile(shaderString, SH_VARIABLES);
167 }
168
TEST_F(MSLOutputTest,FragmentOutSimple)169 TEST_F(MSLOutputTest, FragmentOutSimple)
170 {
171 const std::string &shaderString =
172 R"(#version 300 es
173 precision highp float;
174
175 out vec4 outColor;
176
177 void main()
178 {
179 outColor = vec4(1.0, 2.0, 3.0, 4.0);
180 })";
181 compile(shaderString, SH_VARIABLES);
182 }
183
TEST_F(MSLOutputTest,FragmentOutIndirect1)184 TEST_F(MSLOutputTest, FragmentOutIndirect1)
185 {
186 const std::string &shaderString =
187 R"(#version 300 es
188 precision highp float;
189
190 out vec4 outColor;
191
192 void foo()
193 {
194 outColor = vec4(1.0, 2.0, 3.0, 4.0);
195 }
196
197 void bar()
198 {
199 foo();
200 }
201
202 void main()
203 {
204 bar();
205 })";
206 compile(shaderString, SH_VARIABLES);
207 }
208
TEST_F(MSLOutputTest,FragmentOutIndirect2)209 TEST_F(MSLOutputTest, FragmentOutIndirect2)
210 {
211 const std::string &shaderString =
212 R"(#version 300 es
213 precision highp float;
214
215 out vec4 outColor;
216
217 void foo();
218
219 void bar()
220 {
221 foo();
222 }
223
224 void foo()
225 {
226 outColor = vec4(1.0, 2.0, 3.0, 4.0);
227 }
228
229 void main()
230 {
231 bar();
232 })";
233 compile(shaderString, SH_VARIABLES);
234 }
235
TEST_F(MSLOutputTest,FragmentOutIndirect3)236 TEST_F(MSLOutputTest, FragmentOutIndirect3)
237 {
238 const std::string &shaderString =
239 R"(#version 300 es
240 precision highp float;
241
242 out vec4 outColor;
243
244 float foo(float x, float y)
245 {
246 outColor = vec4(x, y, 3.0, 4.0);
247 return 7.0;
248 }
249
250 float bar(float x)
251 {
252 return foo(x, 2.0);
253 }
254
255 float baz()
256 {
257 return 13.0;
258 }
259
260 float identity(float x)
261 {
262 return x;
263 }
264
265 void main()
266 {
267 identity(bar(baz()));
268 })";
269 compile(shaderString, SH_VARIABLES);
270 }
271
TEST_F(MSLOutputTest,VertexInOut)272 TEST_F(MSLOutputTest, VertexInOut)
273 {
274 const std::string &shaderString =
275 R"(#version 300 es
276 precision highp float;
277 in float in0;
278 out float out0;
279 void main()
280 {
281 out0 = in0;
282 })";
283 compile(shaderString, SH_VARIABLES);
284 }
285
TEST_F(MSLOutputTest,SymbolSharing)286 TEST_F(MSLOutputTest, SymbolSharing)
287 {
288 const std::string &shaderString =
289 R"(#version 300 es
290 precision highp float;
291
292 out vec4 outColor;
293
294 struct Foo {
295 float x;
296 float y;
297 };
298
299 void doFoo(Foo foo, float zw);
300
301 void doFoo(Foo foo, float zw)
302 {
303 foo.x = foo.y;
304 outColor = vec4(foo.x, foo.y, zw, zw);
305 }
306
307 void main()
308 {
309 Foo foo;
310 foo.x = 2.0;
311 foo.y = 2.0;
312 doFoo(foo, 3.0);
313 })";
314 compile(shaderString, SH_VARIABLES);
315 }
316
TEST_F(MSLOutputTest,StructDecl)317 TEST_F(MSLOutputTest, StructDecl)
318 {
319 const std::string &shaderString =
320 R"(#version 300 es
321 precision highp float;
322
323 out float out0;
324
325 struct Foo {
326 float value;
327 };
328
329 void main()
330 {
331 Foo foo;
332 out0 = foo.value;
333 }
334 )";
335 compile(shaderString, SH_VARIABLES);
336 }
337
TEST_F(MSLOutputTest,Structs)338 TEST_F(MSLOutputTest, Structs)
339 {
340 const std::string &shaderString =
341 R"(#version 300 es
342 precision highp float;
343
344 struct Foo {
345 float value;
346 };
347
348 out vec4 out0;
349
350 struct Bar {
351 Foo foo;
352 };
353
354 void go();
355
356 uniform UniInstance {
357 Bar bar;
358 float instance;
359 } uniInstance;
360
361 uniform UniGlobal {
362 Foo foo;
363 float global;
364 };
365
366 void main()
367 {
368 go();
369 }
370
371 struct Baz {
372 Bar bar;
373 } baz;
374
375 void go()
376 {
377 out0.x = baz.bar.foo.value;
378 out0.y = global;
379 out0.z = uniInstance.instance;
380 out0.w = 0.0;
381 }
382
383 )";
384 compile(shaderString, SH_VARIABLES);
385 }
386
TEST_F(MSLOutputTest,KeywordConflict)387 TEST_F(MSLOutputTest, KeywordConflict)
388 {
389 const std::string &shaderString =
390 R"(#version 300 es
391 precision highp float;
392
393 struct fragment {
394 float kernel;
395 } device;
396
397 struct Foo {
398 fragment frag;
399 } foo;
400
401 out float vertex;
402 float kernel;
403
404 float stage_in(float x)
405 {
406 return x;
407 }
408
409 void metal(float metal, float fragment);
410 void metal(float metal, float fragment)
411 {
412 vertex = metal * fragment * foo.frag.kernel;
413 }
414
415 void main()
416 {
417 metal(stage_in(stage_in(kernel * device.kernel)), foo.frag.kernel);
418 })";
419 compile(shaderString, SH_VARIABLES);
420 }
421
TEST_F(MSLVertexOutputTest,Vertex)422 TEST_F(MSLVertexOutputTest, Vertex)
423 {
424 const std::string &shaderString =
425 R"(#version 300 es
426 precision highp float;
427 void main()
428 {
429 gl_Position = vec4(1.0,1.0,1.0,1.0);
430 })";
431 compile(shaderString, SH_VARIABLES);
432 }
433
TEST_F(MSLVertexOutputTest,LastReturn)434 TEST_F(MSLVertexOutputTest, LastReturn)
435 {
436 const std::string &shaderString =
437 R"(#version 300 es
438 in highp vec4 a_position;
439 in highp vec4 a_coords;
440 out highp vec4 v_color;
441
442 void main (void)
443 {
444 gl_Position = a_position;
445 v_color = vec4(a_coords.xyz, 1.0);
446 return;
447 })";
448 compile(shaderString, SH_VARIABLES);
449 }
450
TEST_F(MSLOutputTest,LastReturn)451 TEST_F(MSLOutputTest, LastReturn)
452 {
453 const std::string &shaderString =
454 R"(#version 300 es
455 in mediump vec4 v_coords;
456 layout(location = 0) out mediump vec4 o_color;
457
458 void main (void)
459 {
460 o_color = vec4(v_coords.xyz, 1.0);
461 return;
462 })";
463 compile(shaderString, SH_VARIABLES);
464 }
465
TEST_F(MSLOutputTest,FragColor)466 TEST_F(MSLOutputTest, FragColor)
467 {
468 const std::string &shaderString = R"(
469 void main ()
470 {
471 gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);
472 })";
473 compile(shaderString, SH_VARIABLES);
474 }
475
TEST_F(MSLOutputTest,MatrixIn)476 TEST_F(MSLOutputTest, MatrixIn)
477 {
478 const std::string &shaderString =
479 R"(#version 300 es
480 precision highp float;
481
482 in mat4 mat;
483 out float out0;
484
485 void main()
486 {
487 out0 = mat[0][0];
488 }
489 )";
490 compile(shaderString, SH_VARIABLES);
491 }
492
TEST_F(MSLOutputTest,WhileTrue)493 TEST_F(MSLOutputTest, WhileTrue)
494 {
495 const std::string &shaderString =
496 R"(#version 300 es
497 precision mediump float;
498
499 uniform float uf;
500 out vec4 my_FragColor;
501
502 void main()
503 {
504 my_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
505 while (true)
506 {
507 break;
508 }
509 })";
510 compile(shaderString, SH_VARIABLES);
511 }
512
TEST_F(MSLOutputTest,ForTrue)513 TEST_F(MSLOutputTest, ForTrue)
514 {
515 const std::string &shaderString =
516 R"(#version 300 es
517 precision mediump float;
518
519 uniform float uf;
520 out vec4 my_FragColor;
521
522 void main()
523 {
524 my_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
525 for (;true;)
526 {
527 break;
528 }
529 })";
530 compile(shaderString, SH_VARIABLES);
531 }
532
TEST_F(MSLOutputTest,ForEmpty)533 TEST_F(MSLOutputTest, ForEmpty)
534 {
535 const std::string &shaderString =
536 R"(#version 300 es
537 precision mediump float;
538
539 uniform float uf;
540 out vec4 my_FragColor;
541
542 void main()
543 {
544 my_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
545 for (;;)
546 {
547 break;
548 }
549 })";
550 compile(shaderString, SH_VARIABLES);
551 }
552
TEST_F(MSLOutputTest,ForComplex)553 TEST_F(MSLOutputTest, ForComplex)
554 {
555 const std::string &shaderString =
556 R"(#version 300 es
557 precision mediump float;
558
559 uniform float uf;
560 out vec4 my_FragColor;
561
562 void main()
563 {
564 my_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
565 for (int i = 0, j = 2; i < j; ++i) {
566 if (i == 0) continue;
567 if (i == 42) break;
568 my_FragColor.x += float(i);
569 }
570 })";
571 compile(shaderString, SH_VARIABLES);
572 }
573
TEST_F(MSLOutputTest,ForSymbol)574 TEST_F(MSLOutputTest, ForSymbol)
575 {
576 const std::string &shaderString =
577 R"(#version 300 es
578 precision mediump float;
579
580 uniform float uf;
581 out vec4 my_FragColor;
582
583 void main()
584 {
585 bool cond = true;
586 for (;cond;)
587 {
588 my_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
589 cond = false;
590 }
591 })";
592 compile(shaderString, SH_VARIABLES);
593 }
594
TEST_F(MSLOutputTest,DoWhileSymbol)595 TEST_F(MSLOutputTest, DoWhileSymbol)
596 {
597 const std::string &shaderString =
598 R"(#version 300 es
599 precision mediump float;
600
601 uniform float uf;
602 out vec4 my_FragColor;
603
604 void main()
605 {
606 bool cond = false;
607 do
608 {
609 my_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
610 } while (cond);
611 })";
612 compile(shaderString, SH_VARIABLES);
613 }
614
TEST_F(MSLOutputTest,AnonymousStruct)615 TEST_F(MSLOutputTest, AnonymousStruct)
616 {
617 const std::string &shaderString =
618 R"(
619 precision mediump float;
620 struct { vec4 v; } anonStruct;
621 void main() {
622 anonStruct.v = vec4(0.0,1.0,0.0,1.0);
623 gl_FragColor = anonStruct.v;
624 })";
625 compile(shaderString, SH_VARIABLES);
626 // TODO(anglebug.com/6395): This success condition is expected to fail now.
627 // When WebKit build is able to run the tests, this should be changed to something else.
628 // ASSERT_TRUE(foundInCode(SH_MSL_METAL_OUTPUT, "__unnamed"));
629 }
630