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