blob: d130d632e8c5fefc1ecb45039d24ef5573b13a53 [file] [log] [blame]
Jamie Madill55def582015-05-04 11:24:57 -04001//
2// Copyright 2015 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
Corentin Wallezd3970de2015-05-14 11:07:48 -04007#include "test_utils/ANGLETest.h"
Jamie Madill96509e42014-05-29 14:33:27 -04008
Jamie Madill1048e432016-07-23 18:51:28 -04009#include "test_utils/gl_raii.h"
Jamie Madill55def582015-05-04 11:24:57 -040010
Jamie Madillfa05f602015-05-07 13:47:11 -040011using namespace angle;
Austin Kinross18b931d2014-09-29 12:58:31 -070012
Jamie Madill6c9503e2016-08-16 14:06:32 -040013namespace
14{
15
Jamie Madill2bf8b372014-06-16 17:18:51 -040016class GLSLTest : public ANGLETest
Jamie Madill96509e42014-05-29 14:33:27 -040017{
Jamie Madillfa05f602015-05-07 13:47:11 -040018 protected:
19 GLSLTest()
Jamie Madill96509e42014-05-29 14:33:27 -040020 {
21 setWindowWidth(128);
22 setWindowHeight(128);
23 setConfigRedBits(8);
24 setConfigGreenBits(8);
25 setConfigBlueBits(8);
26 setConfigAlphaBits(8);
27 }
Jamie Madillbfa91f42014-06-05 15:45:18 -040028
29 virtual void SetUp()
30 {
31 ANGLETest::SetUp();
32
Olli Etuahoa20af6d2017-09-18 13:32:29 +030033 mSimpleVSSource =
34 R"(attribute vec4 inputAttribute;
Jamie Madillbfa91f42014-06-05 15:45:18 -040035 void main()
36 {
37 gl_Position = inputAttribute;
Olli Etuahoa20af6d2017-09-18 13:32:29 +030038 })";
Jamie Madillbfa91f42014-06-05 15:45:18 -040039 }
40
Austin Kinrossaf875522014-08-25 21:06:07 -070041 std::string GenerateVaryingType(GLint vectorSize)
42 {
43 char varyingType[10];
44
45 if (vectorSize == 1)
46 {
47 sprintf(varyingType, "float");
48 }
49 else
50 {
51 sprintf(varyingType, "vec%d", vectorSize);
52 }
53
54 return std::string(varyingType);
55 }
56
57 std::string GenerateVectorVaryingDeclaration(GLint vectorSize, GLint arraySize, GLint id)
58 {
59 char buff[100];
60
61 if (arraySize == 1)
62 {
63 sprintf(buff, "varying %s v%d;\n", GenerateVaryingType(vectorSize).c_str(), id);
64 }
65 else
66 {
67 sprintf(buff, "varying %s v%d[%d];\n", GenerateVaryingType(vectorSize).c_str(), id, arraySize);
68 }
69
70 return std::string(buff);
71 }
72
73 std::string GenerateVectorVaryingSettingCode(GLint vectorSize, GLint arraySize, GLint id)
74 {
75 std::string returnString;
76 char buff[100];
77
78 if (arraySize == 1)
79 {
80 sprintf(buff, "\t v%d = %s(1.0);\n", id, GenerateVaryingType(vectorSize).c_str());
81 returnString += buff;
82 }
83 else
84 {
85 for (int i = 0; i < arraySize; i++)
86 {
87 sprintf(buff, "\t v%d[%d] = %s(1.0);\n", id, i, GenerateVaryingType(vectorSize).c_str());
88 returnString += buff;
89 }
90 }
91
92 return returnString;
93 }
94
95 std::string GenerateVectorVaryingUseCode(GLint arraySize, GLint id)
96 {
97 if (arraySize == 1)
98 {
99 char buff[100];
100 sprintf(buff, "v%d + ", id);
101 return std::string(buff);
102 }
103 else
104 {
105 std::string returnString;
106 for (int i = 0; i < arraySize; i++)
107 {
108 char buff[100];
109 sprintf(buff, "v%d[%d] + ", id, i);
110 returnString += buff;
111 }
112 return returnString;
113 }
114 }
115
Austin Kinross8b695ee2015-03-12 13:12:20 -0700116 void GenerateGLSLWithVaryings(GLint floatCount, GLint floatArrayCount, GLint vec2Count, GLint vec2ArrayCount, GLint vec3Count, GLint vec3ArrayCount,
117 GLint vec4Count, GLint vec4ArrayCount, bool useFragCoord, bool usePointCoord, bool usePointSize,
118 std::string* fragmentShader, std::string* vertexShader)
Austin Kinrossaf875522014-08-25 21:06:07 -0700119 {
120 // Generate a string declaring the varyings, to share between the fragment shader and the vertex shader.
121 std::string varyingDeclaration;
122
123 unsigned int varyingCount = 0;
124
125 for (GLint i = 0; i < floatCount; i++)
126 {
127 varyingDeclaration += GenerateVectorVaryingDeclaration(1, 1, varyingCount);
128 varyingCount += 1;
129 }
130
131 for (GLint i = 0; i < floatArrayCount; i++)
132 {
133 varyingDeclaration += GenerateVectorVaryingDeclaration(1, 2, varyingCount);
134 varyingCount += 1;
135 }
136
137 for (GLint i = 0; i < vec2Count; i++)
138 {
139 varyingDeclaration += GenerateVectorVaryingDeclaration(2, 1, varyingCount);
140 varyingCount += 1;
141 }
142
143 for (GLint i = 0; i < vec2ArrayCount; i++)
144 {
145 varyingDeclaration += GenerateVectorVaryingDeclaration(2, 2, varyingCount);
146 varyingCount += 1;
147 }
148
149 for (GLint i = 0; i < vec3Count; i++)
150 {
151 varyingDeclaration += GenerateVectorVaryingDeclaration(3, 1, varyingCount);
152 varyingCount += 1;
153 }
154
155 for (GLint i = 0; i < vec3ArrayCount; i++)
156 {
157 varyingDeclaration += GenerateVectorVaryingDeclaration(3, 2, varyingCount);
158 varyingCount += 1;
159 }
160
Austin Kinross8b695ee2015-03-12 13:12:20 -0700161 for (GLint i = 0; i < vec4Count; i++)
162 {
163 varyingDeclaration += GenerateVectorVaryingDeclaration(4, 1, varyingCount);
164 varyingCount += 1;
165 }
166
167 for (GLint i = 0; i < vec4ArrayCount; i++)
168 {
169 varyingDeclaration += GenerateVectorVaryingDeclaration(4, 2, varyingCount);
170 varyingCount += 1;
171 }
172
Austin Kinrossaf875522014-08-25 21:06:07 -0700173 // Generate the vertex shader
174 vertexShader->clear();
175 vertexShader->append(varyingDeclaration);
176 vertexShader->append("\nvoid main()\n{\n");
177
178 unsigned int currentVSVarying = 0;
179
180 for (GLint i = 0; i < floatCount; i++)
181 {
182 vertexShader->append(GenerateVectorVaryingSettingCode(1, 1, currentVSVarying));
183 currentVSVarying += 1;
184 }
185
186 for (GLint i = 0; i < floatArrayCount; i++)
187 {
188 vertexShader->append(GenerateVectorVaryingSettingCode(1, 2, currentVSVarying));
189 currentVSVarying += 1;
190 }
191
192 for (GLint i = 0; i < vec2Count; i++)
193 {
194 vertexShader->append(GenerateVectorVaryingSettingCode(2, 1, currentVSVarying));
195 currentVSVarying += 1;
196 }
197
198 for (GLint i = 0; i < vec2ArrayCount; i++)
199 {
200 vertexShader->append(GenerateVectorVaryingSettingCode(2, 2, currentVSVarying));
201 currentVSVarying += 1;
202 }
203
204 for (GLint i = 0; i < vec3Count; i++)
205 {
206 vertexShader->append(GenerateVectorVaryingSettingCode(3, 1, currentVSVarying));
207 currentVSVarying += 1;
208 }
209
210 for (GLint i = 0; i < vec3ArrayCount; i++)
211 {
212 vertexShader->append(GenerateVectorVaryingSettingCode(3, 2, currentVSVarying));
213 currentVSVarying += 1;
214 }
215
Austin Kinross8b695ee2015-03-12 13:12:20 -0700216 for (GLint i = 0; i < vec4Count; i++)
217 {
218 vertexShader->append(GenerateVectorVaryingSettingCode(4, 1, currentVSVarying));
219 currentVSVarying += 1;
220 }
221
222 for (GLint i = 0; i < vec4ArrayCount; i++)
223 {
224 vertexShader->append(GenerateVectorVaryingSettingCode(4, 2, currentVSVarying));
225 currentVSVarying += 1;
226 }
227
228 if (usePointSize)
229 {
230 vertexShader->append("gl_PointSize = 1.0;\n");
231 }
232
Austin Kinrossaf875522014-08-25 21:06:07 -0700233 vertexShader->append("}\n");
234
235 // Generate the fragment shader
236 fragmentShader->clear();
237 fragmentShader->append("precision highp float;\n");
238 fragmentShader->append(varyingDeclaration);
239 fragmentShader->append("\nvoid main() \n{ \n\tvec4 retColor = vec4(0,0,0,0);\n");
240
241 unsigned int currentFSVarying = 0;
242
243 // Make use of the float varyings
244 fragmentShader->append("\tretColor += vec4(");
245
246 for (GLint i = 0; i < floatCount; i++)
247 {
248 fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying));
249 currentFSVarying += 1;
250 }
251
252 for (GLint i = 0; i < floatArrayCount; i++)
253 {
254 fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying));
255 currentFSVarying += 1;
256 }
257
258 fragmentShader->append("0.0, 0.0, 0.0, 0.0);\n");
259
260 // Make use of the vec2 varyings
261 fragmentShader->append("\tretColor += vec4(");
262
263 for (GLint i = 0; i < vec2Count; i++)
264 {
265 fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying));
266 currentFSVarying += 1;
267 }
268
269 for (GLint i = 0; i < vec2ArrayCount; i++)
270 {
271 fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying));
272 currentFSVarying += 1;
273 }
274
275 fragmentShader->append("vec2(0.0, 0.0), 0.0, 0.0);\n");
276
277 // Make use of the vec3 varyings
278 fragmentShader->append("\tretColor += vec4(");
279
280 for (GLint i = 0; i < vec3Count; i++)
281 {
282 fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying));
283 currentFSVarying += 1;
284 }
285
286 for (GLint i = 0; i < vec3ArrayCount; i++)
287 {
288 fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying));
289 currentFSVarying += 1;
290 }
291
292 fragmentShader->append("vec3(0.0, 0.0, 0.0), 0.0);\n");
Austin Kinross8b695ee2015-03-12 13:12:20 -0700293
294 // Make use of the vec4 varyings
295 fragmentShader->append("\tretColor += ");
296
297 for (GLint i = 0; i < vec4Count; i++)
298 {
299 fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying));
300 currentFSVarying += 1;
301 }
302
303 for (GLint i = 0; i < vec4ArrayCount; i++)
304 {
305 fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying));
306 currentFSVarying += 1;
307 }
308
309 fragmentShader->append("vec4(0.0, 0.0, 0.0, 0.0);\n");
310
311 // Set gl_FragColor, and use special variables if requested
312 fragmentShader->append("\tgl_FragColor = retColor");
313
314 if (useFragCoord)
315 {
316 fragmentShader->append(" + gl_FragCoord");
317 }
318
319 if (usePointCoord)
320 {
321 fragmentShader->append(" + vec4(gl_PointCoord, 0.0, 0.0)");
322 }
323
324 fragmentShader->append(";\n}");
325 }
326
327 void VaryingTestBase(GLint floatCount, GLint floatArrayCount, GLint vec2Count, GLint vec2ArrayCount, GLint vec3Count, GLint vec3ArrayCount,
328 GLint vec4Count, GLint vec4ArrayCount, bool useFragCoord, bool usePointCoord, bool usePointSize, bool expectSuccess)
329 {
330 std::string fragmentShaderSource;
331 std::string vertexShaderSource;
332
333 GenerateGLSLWithVaryings(floatCount, floatArrayCount, vec2Count, vec2ArrayCount, vec3Count, vec3ArrayCount,
334 vec4Count, vec4ArrayCount, useFragCoord, usePointCoord, usePointSize,
335 &fragmentShaderSource, &vertexShaderSource);
336
337 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
338
339 if (expectSuccess)
340 {
341 EXPECT_NE(0u, program);
342 }
343 else
344 {
345 EXPECT_EQ(0u, program);
346 }
Austin Kinrossaf875522014-08-25 21:06:07 -0700347 }
348
Austin Kinross7a3e8e22015-10-08 15:50:06 -0700349 void CompileGLSLWithUniformsAndSamplers(GLint vertexUniformCount,
350 GLint fragmentUniformCount,
351 GLint vertexSamplersCount,
352 GLint fragmentSamplersCount,
353 bool expectSuccess)
354 {
355 std::stringstream vertexShader;
356 std::stringstream fragmentShader;
357
358 // Generate the vertex shader
359 vertexShader << "precision mediump float;\n";
360
361 for (int i = 0; i < vertexUniformCount; i++)
362 {
363 vertexShader << "uniform vec4 v" << i << ";\n";
364 }
365
366 for (int i = 0; i < vertexSamplersCount; i++)
367 {
368 vertexShader << "uniform sampler2D s" << i << ";\n";
369 }
370
371 vertexShader << "void main()\n{\n";
372
373 for (int i = 0; i < vertexUniformCount; i++)
374 {
375 vertexShader << " gl_Position += v" << i << ";\n";
376 }
377
378 for (int i = 0; i < vertexSamplersCount; i++)
379 {
380 vertexShader << " gl_Position += texture2D(s" << i << ", vec2(0.0, 0.0));\n";
381 }
382
383 if (vertexUniformCount == 0 && vertexSamplersCount == 0)
384 {
385 vertexShader << " gl_Position = vec4(0.0);\n";
386 }
387
388 vertexShader << "}\n";
389
390 // Generate the fragment shader
391 fragmentShader << "precision mediump float;\n";
392
393 for (int i = 0; i < fragmentUniformCount; i++)
394 {
395 fragmentShader << "uniform vec4 v" << i << ";\n";
396 }
397
398 for (int i = 0; i < fragmentSamplersCount; i++)
399 {
400 fragmentShader << "uniform sampler2D s" << i << ";\n";
401 }
402
403 fragmentShader << "void main()\n{\n";
404
405 for (int i = 0; i < fragmentUniformCount; i++)
406 {
407 fragmentShader << " gl_FragColor += v" << i << ";\n";
408 }
409
410 for (int i = 0; i < fragmentSamplersCount; i++)
411 {
412 fragmentShader << " gl_FragColor += texture2D(s" << i << ", vec2(0.0, 0.0));\n";
413 }
414
415 if (fragmentUniformCount == 0 && fragmentSamplersCount == 0)
416 {
417 fragmentShader << " gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n";
418 }
419
420 fragmentShader << "}\n";
421
422 GLuint program = CompileProgram(vertexShader.str(), fragmentShader.str());
423
424 if (expectSuccess)
425 {
426 EXPECT_NE(0u, program);
427 }
428 else
429 {
430 EXPECT_EQ(0u, program);
431 }
432 }
433
Jamie Madill2bf8b372014-06-16 17:18:51 -0400434 std::string mSimpleVSSource;
Jamie Madill96509e42014-05-29 14:33:27 -0400435};
436
Jamie Madille1faacb2016-12-13 12:42:14 -0500437class GLSLTestNoValidation : public GLSLTest
438{
439 public:
440 GLSLTestNoValidation() { setNoErrorEnabled(true); }
441};
442
Jamie Madillfa05f602015-05-07 13:47:11 -0400443class GLSLTest_ES3 : public GLSLTest
Gregoire Payen de La Garanderieb3dced22015-01-12 14:54:55 +0000444{
Olli Etuahoe1d199b2016-07-19 17:14:27 +0300445 void SetUp() override
446 {
447 ANGLETest::SetUp();
448
449 mSimpleVSSource =
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300450 R"(#version 300 es
451 in vec4 inputAttribute;
452 void main()
453 {
454 gl_Position = inputAttribute;
455 })";
Olli Etuahoe1d199b2016-07-19 17:14:27 +0300456 }
Gregoire Payen de La Garanderieb3dced22015-01-12 14:54:55 +0000457};
458
Olli Etuaho9250cb22017-01-21 10:51:27 +0000459class GLSLTest_ES31 : public GLSLTest
460{
461 void SetUp() override
462 {
463 ANGLETest::SetUp();
464
465 mSimpleVSSource =
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300466 R"(#version 310 es
467 in vec4 inputAttribute;
468 void main()
469 {
470 gl_Position = inputAttribute;
471 })";
Olli Etuaho9250cb22017-01-21 10:51:27 +0000472 }
473};
474
Jamie Madillfa05f602015-05-07 13:47:11 -0400475TEST_P(GLSLTest, NamelessScopedStructs)
Jamie Madill96509e42014-05-29 14:33:27 -0400476{
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300477 const std::string fragmentShaderSource =
478 R"(precision mediump float;
Jamie Madill96509e42014-05-29 14:33:27 -0400479 void main()
480 {
Jamie Madillbfa91f42014-06-05 15:45:18 -0400481 struct
482 {
483 float q;
484 } b;
485
486 gl_FragColor = vec4(1, 0, 0, 1);
487 gl_FragColor.a += b.q;
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300488 })";
Jamie Madill96509e42014-05-29 14:33:27 -0400489
Jamie Madill5599c8f2014-08-26 13:16:39 -0400490 GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
Jamie Madillbfa91f42014-06-05 15:45:18 -0400491 EXPECT_NE(0u, program);
492}
Austin Kinross18b931d2014-09-29 12:58:31 -0700493
Jamie Madillfa05f602015-05-07 13:47:11 -0400494TEST_P(GLSLTest, ScopedStructsOrderBug)
Jamie Madillbfa91f42014-06-05 15:45:18 -0400495{
Geoff Lange0cc2a42016-01-20 10:58:17 -0500496 // TODO(geofflang): Find out why this doesn't compile on Apple OpenGL drivers
497 // (http://anglebug.com/1292)
Geoff Lang5103f4c2016-01-26 11:40:18 -0500498 // TODO(geofflang): Find out why this doesn't compile on AMD OpenGL drivers
Geoff Lange0cc2a42016-01-20 10:58:17 -0500499 // (http://anglebug.com/1291)
Corentin Wallezc7f59d02016-06-20 10:12:08 -0400500 if (IsDesktopOpenGL() && (IsOSX() || !IsNVIDIA()))
Geoff Lange0cc2a42016-01-20 10:58:17 -0500501 {
Jamie Madill518b9fa2016-03-02 11:26:02 -0500502 std::cout << "Test disabled on this OpenGL configuration." << std::endl;
Geoff Lange0cc2a42016-01-20 10:58:17 -0500503 return;
504 }
Geoff Lange0cc2a42016-01-20 10:58:17 -0500505
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300506 const std::string fragmentShaderSource =
507 R"(precision mediump float;
Jamie Madillbfa91f42014-06-05 15:45:18 -0400508
509 struct T
510 {
511 float f;
512 };
513
514 void main()
515 {
516 T a;
517
518 struct T
519 {
520 float q;
521 };
522
523 T b;
524
525 gl_FragColor = vec4(1, 0, 0, 1);
526 gl_FragColor.a += a.f;
527 gl_FragColor.a += b.q;
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300528 })";
Jamie Madillbfa91f42014-06-05 15:45:18 -0400529
Jamie Madill5599c8f2014-08-26 13:16:39 -0400530 GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
Jamie Madillbfa91f42014-06-05 15:45:18 -0400531 EXPECT_NE(0u, program);
532}
533
Jamie Madillfa05f602015-05-07 13:47:11 -0400534TEST_P(GLSLTest, ScopedStructsBug)
Jamie Madillbfa91f42014-06-05 15:45:18 -0400535{
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300536 const std::string fragmentShaderSource =
537 R"(precision mediump float;
Jamie Madill96509e42014-05-29 14:33:27 -0400538
539 struct T_0
540 {
541 float f;
542 };
543
544 void main()
545 {
546 gl_FragColor = vec4(1, 0, 0, 1);
547
548 struct T
549 {
550 vec2 v;
551 };
552
553 T_0 a;
554 T b;
555
556 gl_FragColor.a += a.f;
557 gl_FragColor.a += b.v.x;
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300558 })";
Jamie Madill96509e42014-05-29 14:33:27 -0400559
Jamie Madill5599c8f2014-08-26 13:16:39 -0400560 GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
Jamie Madill2bf8b372014-06-16 17:18:51 -0400561 EXPECT_NE(0u, program);
562}
563
Jamie Madillfa05f602015-05-07 13:47:11 -0400564TEST_P(GLSLTest, DxPositionBug)
Jamie Madill2bf8b372014-06-16 17:18:51 -0400565{
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300566 const std::string &vertexShaderSource =
567 R"(attribute vec4 inputAttribute;
Jamie Madill2bf8b372014-06-16 17:18:51 -0400568 varying float dx_Position;
569 void main()
570 {
571 gl_Position = vec4(inputAttribute);
572 dx_Position = 0.0;
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300573 })";
Jamie Madill2bf8b372014-06-16 17:18:51 -0400574
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300575 const std::string &fragmentShaderSource =
576 R"(precision mediump float;
Jamie Madill2bf8b372014-06-16 17:18:51 -0400577
578 varying float dx_Position;
579
580 void main()
581 {
582 gl_FragColor = vec4(dx_Position, 0, 0, 1);
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300583 })";
Jamie Madill2bf8b372014-06-16 17:18:51 -0400584
Jamie Madill5599c8f2014-08-26 13:16:39 -0400585 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
Jamie Madill96509e42014-05-29 14:33:27 -0400586 EXPECT_NE(0u, program);
587}
Jamie Madill4836d222014-07-24 06:55:51 -0400588
Jamie Madillfa05f602015-05-07 13:47:11 -0400589TEST_P(GLSLTest, ElseIfRewriting)
Jamie Madill4836d222014-07-24 06:55:51 -0400590{
591 const std::string &vertexShaderSource =
592 "attribute vec4 a_position;\n"
593 "varying float v;\n"
594 "void main() {\n"
595 " gl_Position = a_position;\n"
596 " v = 1.0;\n"
597 " if (a_position.x <= 0.5) {\n"
598 " v = 0.0;\n"
599 " } else if (a_position.x >= 0.5) {\n"
600 " v = 2.0;\n"
601 " }\n"
602 "}\n";
603
604 const std::string &fragmentShaderSource =
605 "precision highp float;\n"
606 "varying float v;\n"
607 "void main() {\n"
608 " vec4 color = vec4(1.0, 0.0, 0.0, 1.0);\n"
609 " if (v >= 1.0) color = vec4(0.0, 1.0, 0.0, 1.0);\n"
610 " if (v >= 2.0) color = vec4(0.0, 0.0, 1.0, 1.0);\n"
611 " gl_FragColor = color;\n"
612 "}\n";
613
Jamie Madill5599c8f2014-08-26 13:16:39 -0400614 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
Jamie Madill4836d222014-07-24 06:55:51 -0400615 ASSERT_NE(0u, program);
616
617 drawQuad(program, "a_position", 0.5f);
Jamie Madill4836d222014-07-24 06:55:51 -0400618
619 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
620 EXPECT_PIXEL_EQ(getWindowWidth()-1, 0, 0, 255, 0, 255);
621}
622
Jamie Madillfa05f602015-05-07 13:47:11 -0400623TEST_P(GLSLTest, TwoElseIfRewriting)
Jamie Madill4836d222014-07-24 06:55:51 -0400624{
625 const std::string &vertexShaderSource =
626 "attribute vec4 a_position;\n"
627 "varying float v;\n"
628 "void main() {\n"
629 " gl_Position = a_position;\n"
Jamie Madill778d5272014-08-04 13:13:25 -0400630 " if (a_position.x == 0.0) {\n"
Jamie Madill4836d222014-07-24 06:55:51 -0400631 " v = 1.0;\n"
632 " } else if (a_position.x > 0.5) {\n"
633 " v = 0.0;\n"
634 " } else if (a_position.x > 0.75) {\n"
635 " v = 0.5;\n"
636 " }\n"
637 "}\n";
638
639 const std::string &fragmentShaderSource =
640 "precision highp float;\n"
641 "varying float v;\n"
642 "void main() {\n"
643 " gl_FragColor = vec4(v, 0.0, 0.0, 1.0);\n"
644 "}\n";
645
Jamie Madill5599c8f2014-08-26 13:16:39 -0400646 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
Jamie Madill4836d222014-07-24 06:55:51 -0400647 EXPECT_NE(0u, program);
648}
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400649
Jamie Madillfa05f602015-05-07 13:47:11 -0400650TEST_P(GLSLTest, FrontFacingAndVarying)
Jamie Madille6256f82014-09-17 10:31:15 -0400651{
Geoff Langdd323e92015-06-09 15:16:31 -0400652 EGLPlatformParameters platform = GetParam().eglParameters;
Austin Kinross8b695ee2015-03-12 13:12:20 -0700653
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300654 const std::string vertexShaderSource =
655 R"(attribute vec4 a_position;
Jamie Madille6256f82014-09-17 10:31:15 -0400656 varying float v_varying;
657 void main()
658 {
659 v_varying = a_position.x;
660 gl_Position = a_position;
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300661 })";
Jamie Madille6256f82014-09-17 10:31:15 -0400662
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300663 const std::string fragmentShaderSource =
664 R"(precision mediump float;
Jamie Madille6256f82014-09-17 10:31:15 -0400665 varying float v_varying;
666 void main()
667 {
668 vec4 c;
669
670 if (gl_FrontFacing)
671 {
672 c = vec4(v_varying, 0, 0, 1.0);
673 }
674 else
675 {
676 c = vec4(0, v_varying, 0, 1.0);
677 }
678 gl_FragColor = c;
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300679 })";
Jamie Madille6256f82014-09-17 10:31:15 -0400680
681 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
Austin Kinross02df7962015-07-01 10:03:42 -0700682
683 // Compilation should fail on D3D11 feature level 9_3, since gl_FrontFacing isn't supported.
684 if (platform.renderer == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
685 {
686 if (platform.majorVersion == 9 && platform.minorVersion == 3)
687 {
688 EXPECT_EQ(0u, program);
689 return;
690 }
691 }
692
693 // Otherwise, compilation should succeed
Jamie Madille6256f82014-09-17 10:31:15 -0400694 EXPECT_NE(0u, program);
695}
696
Jamie Madill2f348d22017-06-05 10:50:59 -0400697// Test that we can release the shader compiler and still compile things properly.
698TEST_P(GLSLTest, ReleaseCompilerThenCompile)
699{
700 const std::string &simpleVS =
701 "attribute vec4 position; void main() { gl_Position = position; }";
702 const std::string &simpleFS = "void main() { gl_FragColor = vec4(1, 0, 0, 1); }";
703
704 // Draw with the first program.
705 ANGLE_GL_PROGRAM(program1, simpleVS, simpleFS);
706 drawQuad(program1, "position", 0.5f);
707 ASSERT_GL_NO_ERROR();
708 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
709
710 // Clear and release shader compiler.
711 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
712 glClear(GL_COLOR_BUFFER_BIT);
713 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
714 glReleaseShaderCompiler();
715 ASSERT_GL_NO_ERROR();
716
717 // Draw with a second program.
718 ANGLE_GL_PROGRAM(program2, simpleVS, simpleFS);
719 drawQuad(program2, "position", 0.5f);
720 ASSERT_GL_NO_ERROR();
721 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
722}
723
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400724// Verify that linking shaders declaring different shading language versions fails.
725TEST_P(GLSLTest_ES3, VersionMismatch)
726{
727 const std::string fragmentShaderSource100 =
728 "precision mediump float;\n"
729 "varying float v_varying;\n"
730 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
731
732 const std::string vertexShaderSource100 =
733 "attribute vec4 a_position;\n"
734 "varying float v_varying;\n"
735 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
736
737 const std::string fragmentShaderSource300 =
738 "#version 300 es\n"
739 "precision mediump float;\n"
740 "in float v_varying;\n"
741 "out vec4 my_FragColor;\n"
742 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
743
744 const std::string vertexShaderSource300 =
745 "#version 300 es\n"
746 "in vec4 a_position;\n"
747 "out float v_varying;\n"
748 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
749
750 GLuint program = CompileProgram(vertexShaderSource300, fragmentShaderSource100);
751 EXPECT_EQ(0u, program);
752
753 program = CompileProgram(vertexShaderSource100, fragmentShaderSource300);
754 EXPECT_EQ(0u, program);
755}
756
757// Verify that declaring varying as invariant only in vertex shader fails in ESSL 1.00.
758TEST_P(GLSLTest, InvariantVaryingOut)
759{
760 const std::string fragmentShaderSource =
761 "precision mediump float;\n"
762 "varying float v_varying;\n"
763 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
764
765 const std::string vertexShaderSource =
766 "attribute vec4 a_position;\n"
767 "invariant varying float v_varying;\n"
768 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
769
770 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
771 EXPECT_EQ(0u, program);
772}
773
774// Verify that declaring varying as invariant only in vertex shader succeeds in ESSL 3.00.
775TEST_P(GLSLTest_ES3, InvariantVaryingOut)
776{
777 // TODO: ESSL 3.00 -> GLSL 1.20 translation should add "invariant" in fragment shader
778 // for varyings which are invariant in vertex shader (http://anglebug.com/1293)
Corentin Wallezc7f59d02016-06-20 10:12:08 -0400779 if (IsDesktopOpenGL())
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400780 {
781 std::cout << "Test disabled on OpenGL." << std::endl;
782 return;
783 }
784
785 const std::string fragmentShaderSource =
786 "#version 300 es\n"
787 "precision mediump float;\n"
788 "in float v_varying;\n"
789 "out vec4 my_FragColor;\n"
790 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
791
792 const std::string vertexShaderSource =
793 "#version 300 es\n"
794 "in vec4 a_position;\n"
795 "invariant out float v_varying;\n"
796 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
797
798 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
799 EXPECT_NE(0u, program);
800}
801
802// Verify that declaring varying as invariant only in fragment shader fails in ESSL 1.00.
Jamie Madillfa05f602015-05-07 13:47:11 -0400803TEST_P(GLSLTest, InvariantVaryingIn)
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400804{
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400805 const std::string fragmentShaderSource =
806 "precision mediump float;\n"
807 "invariant varying float v_varying;\n"
808 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
Geoff Lange0cc2a42016-01-20 10:58:17 -0500809
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400810 const std::string vertexShaderSource =
811 "attribute vec4 a_position;\n"
812 "varying float v_varying;\n"
813 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400814
Jamie Madill5599c8f2014-08-26 13:16:39 -0400815 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400816 EXPECT_EQ(0u, program);
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400817}
818
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400819// Verify that declaring varying as invariant only in fragment shader fails in ESSL 3.00.
820TEST_P(GLSLTest_ES3, InvariantVaryingIn)
821{
822 const std::string fragmentShaderSource =
823 "#version 300 es\n"
824 "precision mediump float;\n"
825 "invariant in float v_varying;\n"
826 "out vec4 my_FragColor;\n"
827 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
828
829 const std::string vertexShaderSource =
830 "#version 300 es\n"
831 "in vec4 a_position;\n"
832 "out float v_varying;\n"
833 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
834
835 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
836 EXPECT_EQ(0u, program);
837}
838
839// Verify that declaring varying as invariant in both shaders succeeds in ESSL 1.00.
Jamie Madillfa05f602015-05-07 13:47:11 -0400840TEST_P(GLSLTest, InvariantVaryingBoth)
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400841{
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400842 const std::string fragmentShaderSource =
843 "precision mediump float;\n"
844 "invariant varying float v_varying;\n"
845 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400846
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400847 const std::string vertexShaderSource =
848 "attribute vec4 a_position;\n"
849 "invariant varying float v_varying;\n"
850 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400851
Jamie Madill5599c8f2014-08-26 13:16:39 -0400852 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400853 EXPECT_NE(0u, program);
854}
855
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400856// Verify that declaring varying as invariant in both shaders fails in ESSL 3.00.
857TEST_P(GLSLTest_ES3, InvariantVaryingBoth)
858{
859 const std::string fragmentShaderSource =
860 "#version 300 es\n"
861 "precision mediump float;\n"
862 "invariant in float v_varying;\n"
863 "out vec4 my_FragColor;\n"
864 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
865
866 const std::string vertexShaderSource =
867 "#version 300 es\n"
868 "in vec4 a_position;\n"
869 "invariant out float v_varying;\n"
870 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
871
872 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
873 EXPECT_EQ(0u, program);
874}
875
876// Verify that declaring gl_Position as invariant succeeds in ESSL 1.00.
Jamie Madillfa05f602015-05-07 13:47:11 -0400877TEST_P(GLSLTest, InvariantGLPosition)
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400878{
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400879 const std::string fragmentShaderSource =
880 "precision mediump float;\n"
881 "varying float v_varying;\n"
882 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400883
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400884 const std::string vertexShaderSource =
885 "attribute vec4 a_position;\n"
886 "invariant gl_Position;\n"
887 "varying float v_varying;\n"
888 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400889
Jamie Madill5599c8f2014-08-26 13:16:39 -0400890 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400891 EXPECT_NE(0u, program);
892}
893
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400894// Verify that declaring gl_Position as invariant succeeds in ESSL 3.00.
895TEST_P(GLSLTest_ES3, InvariantGLPosition)
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400896{
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400897 const std::string fragmentShaderSource =
898 "#version 300 es\n"
899 "precision mediump float;\n"
900 "in float v_varying;\n"
901 "out vec4 my_FragColor;\n"
902 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
903
904 const std::string vertexShaderSource =
905 "#version 300 es\n"
906 "in vec4 a_position;\n"
907 "invariant gl_Position;\n"
908 "out float v_varying;\n"
909 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
910
911 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
912 EXPECT_NE(0u, program);
913}
914
915// Verify that using invariant(all) in both shaders succeeds in ESSL 1.00.
916TEST_P(GLSLTest, InvariantAllBoth)
917{
918 // TODO: ESSL 1.00 -> GLSL 1.20 translation should add "invariant" in fragment shader
919 // for varyings which are invariant in vertex shader individually,
920 // and remove invariant(all) from fragment shader (http://anglebug.com/1293)
Corentin Wallezc7f59d02016-06-20 10:12:08 -0400921 if (IsDesktopOpenGL())
Geoff Lange0cc2a42016-01-20 10:58:17 -0500922 {
923 std::cout << "Test disabled on OpenGL." << std::endl;
924 return;
925 }
926
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400927 const std::string fragmentShaderSource =
928 "#pragma STDGL invariant(all)\n"
929 "precision mediump float;\n"
930 "varying float v_varying;\n"
931 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400932
933 const std::string vertexShaderSource =
934 "#pragma STDGL invariant(all)\n"
935 "attribute vec4 a_position;\n"
936 "varying float v_varying;\n"
937 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
938
Jamie Madill5599c8f2014-08-26 13:16:39 -0400939 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400940 EXPECT_NE(0u, program);
941}
Austin Kinrossaf875522014-08-25 21:06:07 -0700942
Geoff Lang156d7192016-07-21 16:11:00 -0400943// Verify that functions without return statements still compile
944TEST_P(GLSLTest, MissingReturnFloat)
945{
946 const std::string vertexShaderSource =
947 "varying float v_varying;\n"
948 "float f() { if (v_varying > 0.0) return 1.0; }\n"
949 "void main() { gl_Position = vec4(f(), 0, 0, 1); }\n";
950
951 const std::string fragmentShaderSource =
952 "precision mediump float;\n"
953 "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
954
955 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
956 EXPECT_NE(0u, program);
957}
958
959// Verify that functions without return statements still compile
960TEST_P(GLSLTest, MissingReturnVec2)
961{
962 const std::string vertexShaderSource =
963 "varying float v_varying;\n"
964 "vec2 f() { if (v_varying > 0.0) return vec2(1.0, 1.0); }\n"
965 "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
966
967 const std::string fragmentShaderSource =
968 "precision mediump float;\n"
969 "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
970
971 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
972 EXPECT_NE(0u, program);
973}
974
975// Verify that functions without return statements still compile
976TEST_P(GLSLTest, MissingReturnVec3)
977{
978 const std::string vertexShaderSource =
979 "varying float v_varying;\n"
980 "vec3 f() { if (v_varying > 0.0) return vec3(1.0, 1.0, 1.0); }\n"
981 "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
982
983 const std::string fragmentShaderSource =
984 "precision mediump float;\n"
985 "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
986
987 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
988 EXPECT_NE(0u, program);
989}
990
991// Verify that functions without return statements still compile
992TEST_P(GLSLTest, MissingReturnVec4)
993{
994 const std::string vertexShaderSource =
995 "varying float v_varying;\n"
996 "vec4 f() { if (v_varying > 0.0) return vec4(1.0, 1.0, 1.0, 1.0); }\n"
997 "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
998
999 const std::string fragmentShaderSource =
1000 "precision mediump float;\n"
1001 "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
1002
1003 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1004 EXPECT_NE(0u, program);
1005}
1006
1007// Verify that functions without return statements still compile
1008TEST_P(GLSLTest, MissingReturnIVec4)
1009{
1010 const std::string vertexShaderSource =
1011 "varying float v_varying;\n"
1012 "ivec4 f() { if (v_varying > 0.0) return ivec4(1, 1, 1, 1); }\n"
1013 "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
1014
1015 const std::string fragmentShaderSource =
1016 "precision mediump float;\n"
1017 "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
1018
1019 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1020 EXPECT_NE(0u, program);
1021}
1022
1023// Verify that functions without return statements still compile
1024TEST_P(GLSLTest, MissingReturnMat4)
1025{
1026 const std::string vertexShaderSource =
1027 "varying float v_varying;\n"
1028 "mat4 f() { if (v_varying > 0.0) return mat4(1.0); }\n"
1029 "void main() { gl_Position = vec4(f()[0][0], 0, 0, 1); }\n";
1030
1031 const std::string fragmentShaderSource =
1032 "precision mediump float;\n"
1033 "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
1034
1035 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1036 EXPECT_NE(0u, program);
1037}
1038
1039// Verify that functions without return statements still compile
1040TEST_P(GLSLTest, MissingReturnStruct)
1041{
1042 const std::string vertexShaderSource =
1043 "varying float v_varying;\n"
1044 "struct s { float a; int b; vec2 c; };\n"
1045 "s f() { if (v_varying > 0.0) return s(1.0, 1, vec2(1.0, 1.0)); }\n"
1046 "void main() { gl_Position = vec4(f().a, 0, 0, 1); }\n";
1047
1048 const std::string fragmentShaderSource =
1049 "precision mediump float;\n"
1050 "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
1051
1052 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1053 EXPECT_NE(0u, program);
1054}
1055
1056// Verify that functions without return statements still compile
1057TEST_P(GLSLTest_ES3, MissingReturnArray)
1058{
1059 const std::string vertexShaderSource =
1060 "#version 300 es\n"
1061 "in float v_varying;\n"
1062 "vec2[2] f() { if (v_varying > 0.0) { return vec2[2](vec2(1.0, 1.0), vec2(1.0, 1.0)); } }\n"
1063 "void main() { gl_Position = vec4(f()[0].x, 0, 0, 1); }\n";
1064
1065 const std::string fragmentShaderSource =
1066 "#version 300 es\n"
1067 "precision mediump float;\n"
1068 "out vec4 my_FragColor;\n"
1069 "void main() { my_FragColor = vec4(0, 0, 0, 1); }\n";
1070
1071 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1072 EXPECT_NE(0u, program);
1073}
1074
1075// Verify that functions without return statements still compile
1076TEST_P(GLSLTest_ES3, MissingReturnArrayOfStructs)
1077{
1078 const std::string vertexShaderSource =
1079 "#version 300 es\n"
1080 "in float v_varying;\n"
1081 "struct s { float a; int b; vec2 c; };\n"
1082 "s[2] f() { if (v_varying > 0.0) { return s[2](s(1.0, 1, vec2(1.0, 1.0)), s(1.0, 1, "
1083 "vec2(1.0, 1.0))); } }\n"
1084 "void main() { gl_Position = vec4(f()[0].a, 0, 0, 1); }\n";
1085
1086 const std::string fragmentShaderSource =
1087 "#version 300 es\n"
1088 "precision mediump float;\n"
1089 "out vec4 my_FragColor;\n"
1090 "void main() { my_FragColor = vec4(0, 0, 0, 1); }\n";
1091
1092 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1093 EXPECT_NE(0u, program);
1094}
1095
Corentin Wallez509e4562016-08-25 14:55:44 -04001096// Verify that functions without return statements still compile
1097TEST_P(GLSLTest_ES3, MissingReturnStructOfArrays)
1098{
Olli Etuahodf7d13e2017-05-30 13:53:45 +03001099 // TODO(cwallez) remove the suppression once NVIDIA drivers are updated across trybots, drivers
1100 // since late 2016 should have the fix. Last check on 2017-05-30 revealed that the Windows
1101 // Server 2008 bots still had the old, failing drivers.
Corentin Wallez509e4562016-08-25 14:55:44 -04001102 if (IsNVIDIA() && IsOpenGLES())
1103 {
1104 std::cout << "Test skipped on NVIDIA OpenGL ES because it disallows returning "
1105 "structure of arrays"
1106 << std::endl;
1107 return;
1108 }
1109
1110 const std::string vertexShaderSource =
1111 "#version 300 es\n"
1112 "in float v_varying;\n"
1113 "struct s { float a[2]; int b[2]; vec2 c[2]; };\n"
1114 "s f() { if (v_varying > 0.0) { return s(float[2](1.0, 1.0), int[2](1, 1),"
1115 "vec2[2](vec2(1.0, 1.0), vec2(1.0, 1.0))); } }\n"
1116 "void main() { gl_Position = vec4(f().a[0], 0, 0, 1); }\n";
1117
1118 const std::string fragmentShaderSource =
1119 "#version 300 es\n"
1120 "precision mediump float;\n"
1121 "out vec4 my_FragColor;\n"
1122 "void main() { my_FragColor = vec4(0, 0, 0, 1); }\n";
1123
1124 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1125 EXPECT_NE(0u, program);
1126}
1127
Yuly Novikova1f6dc92016-06-15 23:27:04 -04001128// Verify that using invariant(all) in both shaders fails in ESSL 3.00.
1129TEST_P(GLSLTest_ES3, InvariantAllBoth)
1130{
1131 const std::string fragmentShaderSource =
1132 "#version 300 es\n"
1133 "#pragma STDGL invariant(all)\n"
1134 "precision mediump float;\n"
1135 "in float v_varying;\n"
1136 "out vec4 my_FragColor;\n"
1137 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1138
1139 const std::string vertexShaderSource =
1140 "#version 300 es\n"
1141 "#pragma STDGL invariant(all)\n"
1142 "in vec4 a_position;\n"
1143 "out float v_varying;\n"
1144 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1145
1146 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1147 EXPECT_EQ(0u, program);
1148}
1149
1150// Verify that using invariant(all) only in fragment shader fails in ESSL 1.00.
1151TEST_P(GLSLTest, InvariantAllIn)
1152{
1153 const std::string fragmentShaderSource =
1154 "#pragma STDGL invariant(all)\n"
1155 "precision mediump float;\n"
1156 "varying float v_varying;\n"
1157 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1158
1159 const std::string vertexShaderSource =
1160 "attribute vec4 a_position;\n"
1161 "varying float v_varying;\n"
1162 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1163
1164 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1165 EXPECT_EQ(0u, program);
1166}
1167
1168// Verify that using invariant(all) only in fragment shader fails in ESSL 3.00.
1169TEST_P(GLSLTest_ES3, InvariantAllIn)
1170{
1171 const std::string fragmentShaderSource =
1172 "#version 300 es\n"
1173 "#pragma STDGL invariant(all)\n"
1174 "precision mediump float;\n"
1175 "in float v_varying;\n"
1176 "out vec4 my_FragColor;\n"
1177 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1178
1179 const std::string vertexShaderSource =
1180 "#version 300 es\n"
1181 "in vec4 a_position;\n"
1182 "out float v_varying;\n"
1183 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1184
1185 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1186 EXPECT_EQ(0u, program);
1187}
1188
1189// Verify that using invariant(all) only in vertex shader fails in ESSL 1.00.
1190TEST_P(GLSLTest, InvariantAllOut)
1191{
1192 const std::string fragmentShaderSource =
1193 "precision mediump float;\n"
1194 "varying float v_varying;\n"
1195 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1196
1197 const std::string vertexShaderSource =
1198 "#pragma STDGL invariant(all)\n"
1199 "attribute vec4 a_position;\n"
1200 "varying float v_varying;\n"
1201 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1202
1203 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1204 EXPECT_EQ(0u, program);
1205}
1206
1207// Verify that using invariant(all) only in vertex shader succeeds in ESSL 3.00.
1208TEST_P(GLSLTest_ES3, InvariantAllOut)
1209{
1210 // TODO: ESSL 3.00 -> GLSL 1.20 translation should add "invariant" in fragment shader
1211 // for varyings which are invariant in vertex shader,
1212 // because of invariant(all) being used in vertex shader (http://anglebug.com/1293)
Corentin Wallezc7f59d02016-06-20 10:12:08 -04001213 if (IsDesktopOpenGL())
Yuly Novikova1f6dc92016-06-15 23:27:04 -04001214 {
1215 std::cout << "Test disabled on OpenGL." << std::endl;
1216 return;
1217 }
1218
1219 const std::string fragmentShaderSource =
1220 "#version 300 es\n"
1221 "precision mediump float;\n"
1222 "in float v_varying;\n"
1223 "out vec4 my_FragColor;\n"
1224 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1225
1226 const std::string vertexShaderSource =
1227 "#version 300 es\n"
1228 "#pragma STDGL invariant(all)\n"
1229 "in vec4 a_position;\n"
1230 "out float v_varying;\n"
1231 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1232
1233 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1234 EXPECT_NE(0u, program);
1235}
1236
Jamie Madillfa05f602015-05-07 13:47:11 -04001237TEST_P(GLSLTest, MaxVaryingVec4)
Austin Kinross8b695ee2015-03-12 13:12:20 -07001238{
Geoff Lang69accbd2016-01-25 16:22:32 -05001239#if defined(__APPLE__)
1240 // TODO(geofflang): Find out why this doesn't compile on Apple AND OpenGL drivers
1241 // (http://anglebug.com/1291)
Jamie Madill518b9fa2016-03-02 11:26:02 -05001242 if (IsAMD() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
Geoff Lang69accbd2016-01-25 16:22:32 -05001243 {
1244 std::cout << "Test disabled on Apple AMD OpenGL." << std::endl;
1245 return;
1246 }
1247#endif
1248
Austin Kinross8b695ee2015-03-12 13:12:20 -07001249 GLint maxVaryings = 0;
1250 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1251
1252 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, false, false, false, true);
1253}
1254
Jamie Madillfa05f602015-05-07 13:47:11 -04001255TEST_P(GLSLTest, MaxMinusTwoVaryingVec4PlusTwoSpecialVariables)
Austin Kinross8b695ee2015-03-12 13:12:20 -07001256{
1257 GLint maxVaryings = 0;
1258 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1259
1260 // Generate shader code that uses gl_FragCoord and gl_PointCoord, two special fragment shader variables.
1261 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 2, 0, true, true, false, true);
1262}
1263
Jamie Madillfa05f602015-05-07 13:47:11 -04001264TEST_P(GLSLTest, MaxMinusTwoVaryingVec4PlusThreeSpecialVariables)
Austin Kinross8b695ee2015-03-12 13:12:20 -07001265{
Geoff Lange0cc2a42016-01-20 10:58:17 -05001266 // TODO(geofflang): Figure out why this fails on OpenGL AMD (http://anglebug.com/1291)
Jamie Madill518b9fa2016-03-02 11:26:02 -05001267 if (IsAMD() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
Geoff Lange0cc2a42016-01-20 10:58:17 -05001268 {
1269 std::cout << "Test disabled on OpenGL." << std::endl;
1270 return;
1271 }
1272
Austin Kinross8b695ee2015-03-12 13:12:20 -07001273 GLint maxVaryings = 0;
1274 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1275
1276 // Generate shader code that uses gl_FragCoord, gl_PointCoord and gl_PointSize.
1277 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 2, 0, true, true, true, true);
1278}
1279
Jamie Madillfa05f602015-05-07 13:47:11 -04001280TEST_P(GLSLTest, MaxVaryingVec3)
Austin Kinrossaf875522014-08-25 21:06:07 -07001281{
1282 GLint maxVaryings = 0;
1283 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1284
Austin Kinross8b695ee2015-03-12 13:12:20 -07001285 VaryingTestBase(0, 0, 0, 0, maxVaryings, 0, 0, 0, false, false, false, true);
Austin Kinrossaf875522014-08-25 21:06:07 -07001286}
1287
Jamie Madillfa05f602015-05-07 13:47:11 -04001288TEST_P(GLSLTest, MaxVaryingVec3Array)
Austin Kinrossaf875522014-08-25 21:06:07 -07001289{
1290 GLint maxVaryings = 0;
1291 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1292
Austin Kinross8b695ee2015-03-12 13:12:20 -07001293 VaryingTestBase(0, 0, 0, 0, 0, maxVaryings / 2, 0, 0, false, false, false, true);
Austin Kinrossaf875522014-08-25 21:06:07 -07001294}
1295
Jamie Madillbee59e02014-10-02 10:44:18 -04001296// Disabled because of a failure in D3D9
Jamie Madill9fc36822015-11-18 13:08:07 -05001297TEST_P(GLSLTest, MaxVaryingVec3AndOneFloat)
Austin Kinrossaf875522014-08-25 21:06:07 -07001298{
Jamie Madill518b9fa2016-03-02 11:26:02 -05001299 if (IsD3D9())
Jamie Madill9fc36822015-11-18 13:08:07 -05001300 {
1301 std::cout << "Test disabled on D3D9." << std::endl;
1302 return;
1303 }
1304
Austin Kinrossaf875522014-08-25 21:06:07 -07001305 GLint maxVaryings = 0;
1306 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1307
Austin Kinross8b695ee2015-03-12 13:12:20 -07001308 VaryingTestBase(1, 0, 0, 0, maxVaryings, 0, 0, 0, false, false, false, true);
Austin Kinrossaf875522014-08-25 21:06:07 -07001309}
1310
Jamie Madillbee59e02014-10-02 10:44:18 -04001311// Disabled because of a failure in D3D9
Jamie Madill9fc36822015-11-18 13:08:07 -05001312TEST_P(GLSLTest, MaxVaryingVec3ArrayAndOneFloatArray)
Austin Kinrossaf875522014-08-25 21:06:07 -07001313{
Jamie Madill518b9fa2016-03-02 11:26:02 -05001314 if (IsD3D9())
Jamie Madill9fc36822015-11-18 13:08:07 -05001315 {
1316 std::cout << "Test disabled on D3D9." << std::endl;
1317 return;
1318 }
1319
Austin Kinrossaf875522014-08-25 21:06:07 -07001320 GLint maxVaryings = 0;
1321 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1322
Austin Kinross8b695ee2015-03-12 13:12:20 -07001323 VaryingTestBase(0, 1, 0, 0, 0, maxVaryings / 2, 0, 0, false, false, false, true);
Austin Kinrossaf875522014-08-25 21:06:07 -07001324}
1325
Jamie Madillbee59e02014-10-02 10:44:18 -04001326// Disabled because of a failure in D3D9
Jamie Madill9fc36822015-11-18 13:08:07 -05001327TEST_P(GLSLTest, TwiceMaxVaryingVec2)
Austin Kinrossaf875522014-08-25 21:06:07 -07001328{
Jamie Madill518b9fa2016-03-02 11:26:02 -05001329 if (IsD3D9())
Jamie Madill9fc36822015-11-18 13:08:07 -05001330 {
1331 std::cout << "Test disabled on D3D9." << std::endl;
1332 return;
1333 }
1334
Geoff Lange0cc2a42016-01-20 10:58:17 -05001335 if (getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
1336 {
1337 // TODO(geofflang): Figure out why this fails on NVIDIA's GLES driver
1338 std::cout << "Test disabled on OpenGL ES." << std::endl;
1339 return;
1340 }
1341
Geoff Lang69accbd2016-01-25 16:22:32 -05001342#if defined(__APPLE__)
1343 // TODO(geofflang): Find out why this doesn't compile on Apple AND OpenGL drivers
1344 // (http://anglebug.com/1291)
Jamie Madill518b9fa2016-03-02 11:26:02 -05001345 if (IsAMD() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
Geoff Lang69accbd2016-01-25 16:22:32 -05001346 {
1347 std::cout << "Test disabled on Apple AMD OpenGL." << std::endl;
1348 return;
1349 }
1350#endif
1351
Austin Kinrossaf875522014-08-25 21:06:07 -07001352 GLint maxVaryings = 0;
1353 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1354
Austin Kinross8b695ee2015-03-12 13:12:20 -07001355 VaryingTestBase(0, 0, 2 * maxVaryings, 0, 0, 0, 0, 0, false, false, false, true);
Austin Kinrossaf875522014-08-25 21:06:07 -07001356}
1357
Jamie Madillbee59e02014-10-02 10:44:18 -04001358// Disabled because of a failure in D3D9
Jamie Madill9fc36822015-11-18 13:08:07 -05001359TEST_P(GLSLTest, MaxVaryingVec2Arrays)
Austin Kinrossaf875522014-08-25 21:06:07 -07001360{
Jamie Madill518b9fa2016-03-02 11:26:02 -05001361 if (IsD3DSM3())
Jamie Madill9fc36822015-11-18 13:08:07 -05001362 {
1363 std::cout << "Test disabled on SM3." << std::endl;
1364 return;
1365 }
1366
Geoff Lange0cc2a42016-01-20 10:58:17 -05001367 if (getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
1368 {
1369 // TODO(geofflang): Figure out why this fails on NVIDIA's GLES driver
1370 std::cout << "Test disabled on OpenGL ES." << std::endl;
1371 return;
1372 }
1373
Geoff Lang69accbd2016-01-25 16:22:32 -05001374#if defined(__APPLE__)
1375 // TODO(geofflang): Find out why this doesn't compile on Apple AND OpenGL drivers
1376 // (http://anglebug.com/1291)
Jamie Madill518b9fa2016-03-02 11:26:02 -05001377 if (IsAMD() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
Geoff Lang69accbd2016-01-25 16:22:32 -05001378 {
1379 std::cout << "Test disabled on Apple AMD OpenGL." << std::endl;
1380 return;
1381 }
1382#endif
1383
Austin Kinrossaf875522014-08-25 21:06:07 -07001384 GLint maxVaryings = 0;
1385 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1386
Jamie Madill192745a2016-12-22 15:58:21 -05001387 // Special case: because arrays of mat2 are packed as small grids of two rows by two columns,
1388 // we should be aware that when we're packing into an odd number of varying registers the
1389 // last row will be empty and can not fit the final vec2 arrary.
1390 GLint maxVec2Arrays = (maxVaryings >> 1) << 1;
1391
1392 VaryingTestBase(0, 0, 0, maxVec2Arrays, 0, 0, 0, 0, false, false, false, true);
Austin Kinrossaf875522014-08-25 21:06:07 -07001393}
1394
Geoff Langf60fab62014-11-24 11:21:20 -05001395// Verify shader source with a fixed length that is less than the null-terminated length will compile.
Jamie Madillfa05f602015-05-07 13:47:11 -04001396TEST_P(GLSLTest, FixedShaderLength)
Geoff Langf60fab62014-11-24 11:21:20 -05001397{
1398 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1399
1400 const std::string appendGarbage = "abcasdfasdfasdfasdfasdf";
1401 const std::string source = "void main() { gl_FragColor = vec4(0, 0, 0, 0); }" + appendGarbage;
1402 const char *sourceArray[1] = { source.c_str() };
Corentin Wallez973402f2015-05-11 13:42:22 -04001403 GLint lengths[1] = { static_cast<GLint>(source.length() - appendGarbage.length()) };
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001404 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
Geoff Langf60fab62014-11-24 11:21:20 -05001405 glCompileShader(shader);
1406
1407 GLint compileResult;
1408 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1409 EXPECT_NE(compileResult, 0);
1410}
1411
1412// Verify that a negative shader source length is treated as a null-terminated length.
Jamie Madillfa05f602015-05-07 13:47:11 -04001413TEST_P(GLSLTest, NegativeShaderLength)
Geoff Langf60fab62014-11-24 11:21:20 -05001414{
1415 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1416
1417 const char *sourceArray[1] = { "void main() { gl_FragColor = vec4(0, 0, 0, 0); }" };
1418 GLint lengths[1] = { -10 };
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001419 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
Geoff Langf60fab62014-11-24 11:21:20 -05001420 glCompileShader(shader);
1421
1422 GLint compileResult;
1423 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1424 EXPECT_NE(compileResult, 0);
1425}
1426
Corentin Wallez9a9c0482016-04-12 10:36:25 -04001427// Check that having an invalid char after the "." doesn't cause an assert.
1428TEST_P(GLSLTest, InvalidFieldFirstChar)
1429{
1430 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
1431 const char *source = "void main() {vec4 x; x.}";
1432 glShaderSource(shader, 1, &source, 0);
1433 glCompileShader(shader);
1434
1435 GLint compileResult;
1436 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1437 EXPECT_EQ(0, compileResult);
1438}
1439
Geoff Langf60fab62014-11-24 11:21:20 -05001440// Verify that a length array with mixed positive and negative values compiles.
Jamie Madillfa05f602015-05-07 13:47:11 -04001441TEST_P(GLSLTest, MixedShaderLengths)
Geoff Langf60fab62014-11-24 11:21:20 -05001442{
1443 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1444
1445 const char *sourceArray[] =
1446 {
1447 "void main()",
1448 "{",
1449 " gl_FragColor = vec4(0, 0, 0, 0);",
1450 "}",
1451 };
1452 GLint lengths[] =
1453 {
1454 -10,
1455 1,
Corentin Wallez973402f2015-05-11 13:42:22 -04001456 static_cast<GLint>(strlen(sourceArray[2])),
Geoff Langf60fab62014-11-24 11:21:20 -05001457 -1,
1458 };
1459 ASSERT_EQ(ArraySize(sourceArray), ArraySize(lengths));
1460
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001461 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
Geoff Langf60fab62014-11-24 11:21:20 -05001462 glCompileShader(shader);
1463
1464 GLint compileResult;
1465 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1466 EXPECT_NE(compileResult, 0);
1467}
1468
1469// Verify that zero-length shader source does not affect shader compilation.
Jamie Madillfa05f602015-05-07 13:47:11 -04001470TEST_P(GLSLTest, ZeroShaderLength)
Geoff Langf60fab62014-11-24 11:21:20 -05001471{
1472 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1473
1474 const char *sourceArray[] =
1475 {
1476 "adfasdf",
1477 "34534",
1478 "void main() { gl_FragColor = vec4(0, 0, 0, 0); }",
1479 "",
1480 "asdfasdfsdsdf",
1481 };
1482 GLint lengths[] =
1483 {
1484 0,
1485 0,
1486 -1,
1487 0,
1488 0,
1489 };
1490 ASSERT_EQ(ArraySize(sourceArray), ArraySize(lengths));
1491
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001492 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
Geoff Langf60fab62014-11-24 11:21:20 -05001493 glCompileShader(shader);
1494
1495 GLint compileResult;
1496 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1497 EXPECT_NE(compileResult, 0);
1498}
Jamie Madill21c1e452014-12-29 11:33:41 -05001499
1500// Tests that bad index expressions don't crash ANGLE's translator.
1501// https://code.google.com/p/angleproject/issues/detail?id=857
Jamie Madillfa05f602015-05-07 13:47:11 -04001502TEST_P(GLSLTest, BadIndexBug)
Jamie Madill21c1e452014-12-29 11:33:41 -05001503{
1504 const std::string &fragmentShaderSourceVec =
1505 "precision mediump float;\n"
1506 "uniform vec4 uniformVec;\n"
1507 "void main()\n"
1508 "{\n"
1509 " gl_FragColor = vec4(uniformVec[int()]);\n"
1510 "}";
1511
1512 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, fragmentShaderSourceVec);
1513 EXPECT_EQ(0u, shader);
1514
1515 if (shader != 0)
1516 {
1517 glDeleteShader(shader);
1518 }
1519
1520 const std::string &fragmentShaderSourceMat =
1521 "precision mediump float;\n"
1522 "uniform mat4 uniformMat;\n"
1523 "void main()\n"
1524 "{\n"
1525 " gl_FragColor = vec4(uniformMat[int()]);\n"
1526 "}";
1527
1528 shader = CompileShader(GL_FRAGMENT_SHADER, fragmentShaderSourceMat);
1529 EXPECT_EQ(0u, shader);
1530
1531 if (shader != 0)
1532 {
1533 glDeleteShader(shader);
1534 }
1535
1536 const std::string &fragmentShaderSourceArray =
1537 "precision mediump float;\n"
1538 "uniform vec4 uniformArray;\n"
1539 "void main()\n"
1540 "{\n"
1541 " gl_FragColor = vec4(uniformArray[int()]);\n"
1542 "}";
1543
1544 shader = CompileShader(GL_FRAGMENT_SHADER, fragmentShaderSourceArray);
1545 EXPECT_EQ(0u, shader);
1546
1547 if (shader != 0)
1548 {
1549 glDeleteShader(shader);
1550 }
Jamie Madill37997142015-01-28 10:06:34 -05001551}
1552
Jamie Madill2e295e22015-04-29 10:41:33 -04001553// Test that structs defined in uniforms are translated correctly.
Jamie Madillfa05f602015-05-07 13:47:11 -04001554TEST_P(GLSLTest, StructSpecifiersUniforms)
Jamie Madill2e295e22015-04-29 10:41:33 -04001555{
Olli Etuahoa20af6d2017-09-18 13:32:29 +03001556 const std::string fragmentShaderSource =
1557 R"(precision mediump float;
Jamie Madill2e295e22015-04-29 10:41:33 -04001558
1559 uniform struct S { float field;} s;
1560
1561 void main()
1562 {
1563 gl_FragColor = vec4(1, 0, 0, 1);
1564 gl_FragColor.a += s.field;
Olli Etuahoa20af6d2017-09-18 13:32:29 +03001565 })";
Jamie Madill2e295e22015-04-29 10:41:33 -04001566
1567 GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
1568 EXPECT_NE(0u, program);
1569}
Jamie Madill55def582015-05-04 11:24:57 -04001570
1571// Test that gl_DepthRange is not stored as a uniform location. Since uniforms
1572// beginning with "gl_" are filtered out by our validation logic, we must
1573// bypass the validation to test the behaviour of the implementation.
1574// (note this test is still Impl-independent)
Jamie Madille1faacb2016-12-13 12:42:14 -05001575TEST_P(GLSLTestNoValidation, DepthRangeUniforms)
Jamie Madill55def582015-05-04 11:24:57 -04001576{
Olli Etuahoa20af6d2017-09-18 13:32:29 +03001577 const std::string fragmentShaderSource =
1578 R"(precision mediump float;
Jamie Madill55def582015-05-04 11:24:57 -04001579
1580 void main()
1581 {
1582 gl_FragColor = vec4(gl_DepthRange.near, gl_DepthRange.far, gl_DepthRange.diff, 1);
Olli Etuahoa20af6d2017-09-18 13:32:29 +03001583 })";
Jamie Madill55def582015-05-04 11:24:57 -04001584
Jamie Madille1faacb2016-12-13 12:42:14 -05001585 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShaderSource);
Jamie Madill55def582015-05-04 11:24:57 -04001586
Jamie Madille1faacb2016-12-13 12:42:14 -05001587 // We need to bypass validation for this call.
1588 GLint nearIndex = glGetUniformLocation(program.get(), "gl_DepthRange.near");
Jamie Madill55def582015-05-04 11:24:57 -04001589 EXPECT_EQ(-1, nearIndex);
1590
1591 // Test drawing does not throw an exception.
Jamie Madille1faacb2016-12-13 12:42:14 -05001592 drawQuad(program.get(), "inputAttribute", 0.5f);
Jamie Madill55def582015-05-04 11:24:57 -04001593
1594 EXPECT_GL_NO_ERROR();
Jamie Madill55def582015-05-04 11:24:57 -04001595}
Jamie Madill4052dfc2015-05-06 15:18:49 -04001596
Jamie Madill6c9503e2016-08-16 14:06:32 -04001597std::string GenerateSmallPowShader(double base, double exponent)
1598{
1599 std::stringstream stream;
1600
1601 stream.precision(8);
1602
1603 double result = pow(base, exponent);
1604
1605 stream << "precision highp float;\n"
1606 << "float fun(float arg)\n"
1607 << "{\n"
1608 << " return pow(arg, " << std::fixed << exponent << ");\n"
1609 << "}\n"
1610 << "\n"
1611 << "void main()\n"
1612 << "{\n"
1613 << " const float a = " << std::scientific << base << ";\n"
1614 << " float b = fun(a);\n"
1615 << " if (abs(" << result << " - b) < " << std::abs(result * 0.001) << ")\n"
1616 << " {\n"
1617 << " gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
1618 << " }\n"
1619 << " else\n"
1620 << " {\n"
1621 << " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
1622 << " }\n"
1623 << "}\n";
1624
1625 return stream.str();
1626}
1627
Jamie Madill4052dfc2015-05-06 15:18:49 -04001628// Covers the WebGL test 'glsl/bugs/pow-of-small-constant-in-user-defined-function'
Jamie Madill1048e432016-07-23 18:51:28 -04001629// See http://anglebug.com/851
1630TEST_P(GLSLTest, PowOfSmallConstant)
Jamie Madill4052dfc2015-05-06 15:18:49 -04001631{
Jamie Madill6c9503e2016-08-16 14:06:32 -04001632 std::vector<double> bads;
1633 for (int eps = -1; eps <= 1; ++eps)
1634 {
1635 for (int i = -4; i <= 5; ++i)
Jamie Madill4052dfc2015-05-06 15:18:49 -04001636 {
Jamie Madill6c9503e2016-08-16 14:06:32 -04001637 if (i >= -1 && i <= 1)
1638 continue;
1639 const double epsilon = 1.0e-8;
1640 double bad = static_cast<double>(i) + static_cast<double>(eps) * epsilon;
1641 bads.push_back(bad);
Jamie Madill4052dfc2015-05-06 15:18:49 -04001642 }
Jamie Madill6c9503e2016-08-16 14:06:32 -04001643 }
Jamie Madill4052dfc2015-05-06 15:18:49 -04001644
Jamie Madill6c9503e2016-08-16 14:06:32 -04001645 for (double bad : bads)
1646 {
1647 const std::string &fragmentShaderSource = GenerateSmallPowShader(1.0e-6, bad);
Jamie Madill4052dfc2015-05-06 15:18:49 -04001648
Jamie Madill6c9503e2016-08-16 14:06:32 -04001649 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShaderSource);
Jamie Madill4052dfc2015-05-06 15:18:49 -04001650
Jamie Madill6c9503e2016-08-16 14:06:32 -04001651 drawQuad(program.get(), "inputAttribute", 0.5f);
1652
1653 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1654 EXPECT_GL_NO_ERROR();
1655 }
Jamie Madill4052dfc2015-05-06 15:18:49 -04001656}
Jamie Madillfa05f602015-05-07 13:47:11 -04001657
Cooper Partina5ef8d82015-08-19 14:52:21 -07001658// Test that fragment shaders which contain non-constant loop indexers and compiled for FL9_3 and
1659// below
1660// fail with a specific error message.
1661// Additionally test that the same fragment shader compiles successfully with feature levels greater
1662// than FL9_3.
1663TEST_P(GLSLTest, LoopIndexingValidation)
1664{
Olli Etuahoa20af6d2017-09-18 13:32:29 +03001665 const std::string fragmentShaderSource =
1666 R"(precision mediump float;
Cooper Partina5ef8d82015-08-19 14:52:21 -07001667
1668 uniform float loopMax;
1669
1670 void main()
1671 {
1672 gl_FragColor = vec4(1, 0, 0, 1);
1673 for (float l = 0.0; l < loopMax; l++)
1674 {
1675 if (loopMax > 3.0)
1676 {
1677 gl_FragColor.a += 0.1;
1678 }
1679 }
Olli Etuahoa20af6d2017-09-18 13:32:29 +03001680 })";
Cooper Partina5ef8d82015-08-19 14:52:21 -07001681
1682 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1683
1684 const char *sourceArray[1] = {fragmentShaderSource.c_str()};
1685 glShaderSource(shader, 1, sourceArray, nullptr);
1686 glCompileShader(shader);
1687
1688 GLint compileResult;
1689 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1690
1691 // If the test is configured to run limited to Feature Level 9_3, then it is
1692 // assumed that shader compilation will fail with an expected error message containing
1693 // "Loop index cannot be compared with non-constant expression"
Olli Etuaho814a54d2015-08-27 16:23:09 +03001694 if ((GetParam() == ES2_D3D11_FL9_3() || GetParam() == ES2_D3D9()))
Cooper Partina5ef8d82015-08-19 14:52:21 -07001695 {
1696 if (compileResult != 0)
1697 {
1698 FAIL() << "Shader compilation succeeded, expected failure";
1699 }
1700 else
1701 {
1702 GLint infoLogLength;
1703 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
1704
1705 std::string infoLog;
1706 infoLog.resize(infoLogLength);
Yunchao Hef81ce4a2017-04-24 10:49:17 +08001707 glGetShaderInfoLog(shader, static_cast<GLsizei>(infoLog.size()), nullptr, &infoLog[0]);
Cooper Partina5ef8d82015-08-19 14:52:21 -07001708
1709 if (infoLog.find("Loop index cannot be compared with non-constant expression") ==
1710 std::string::npos)
1711 {
1712 FAIL() << "Shader compilation failed with unexpected error message";
1713 }
1714 }
1715 }
1716 else
1717 {
1718 EXPECT_NE(0, compileResult);
1719 }
1720
1721 if (shader != 0)
1722 {
1723 glDeleteShader(shader);
1724 }
1725}
1726
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001727// Tests that the maximum uniforms count returned from querying GL_MAX_VERTEX_UNIFORM_VECTORS
1728// can actually be used.
1729TEST_P(GLSLTest, VerifyMaxVertexUniformVectors)
1730{
Zhenyao Mo1a256722017-01-12 11:52:57 -08001731 if (IsLinux() && IsIntel())
1732 {
1733 std::cout << "Test timed out on Linux Intel. See crbug.com/680631." << std::endl;
1734 return;
1735 }
1736
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001737 int maxUniforms = 10000;
1738 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
1739 EXPECT_GL_NO_ERROR();
1740 std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS = " << maxUniforms << std::endl;
1741
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001742 CompileGLSLWithUniformsAndSamplers(maxUniforms, 0, 0, 0, true);
1743}
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001744
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001745// Tests that the maximum uniforms count returned from querying GL_MAX_VERTEX_UNIFORM_VECTORS
1746// can actually be used along with the maximum number of texture samplers.
1747TEST_P(GLSLTest, VerifyMaxVertexUniformVectorsWithSamplers)
1748{
Geoff Lange0cc2a42016-01-20 10:58:17 -05001749 if (GetParam().eglParameters.renderer == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE ||
1750 GetParam().eglParameters.renderer == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
1751 {
1752 std::cout << "Test disabled on OpenGL." << std::endl;
1753 return;
1754 }
1755
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001756 int maxUniforms = 10000;
1757 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
1758 EXPECT_GL_NO_ERROR();
1759 std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS = " << maxUniforms << std::endl;
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001760
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001761 int maxTextureImageUnits = 0;
1762 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001763
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001764 CompileGLSLWithUniformsAndSamplers(maxUniforms, 0, maxTextureImageUnits, 0, true);
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001765}
1766
1767// Tests that the maximum uniforms count + 1 from querying GL_MAX_VERTEX_UNIFORM_VECTORS
1768// fails shader compilation.
1769TEST_P(GLSLTest, VerifyMaxVertexUniformVectorsExceeded)
1770{
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001771 int maxUniforms = 10000;
1772 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
1773 EXPECT_GL_NO_ERROR();
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001774 std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS + 1 = " << maxUniforms + 1 << std::endl;
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001775
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001776 CompileGLSLWithUniformsAndSamplers(maxUniforms + 1, 0, 0, 0, false);
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001777}
1778
1779// Tests that the maximum uniforms count returned from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
1780// can actually be used.
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001781TEST_P(GLSLTest, VerifyMaxFragmentUniformVectors)
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001782{
Zhenyao Mo1a256722017-01-12 11:52:57 -08001783 if (IsLinux() && IsIntel())
1784 {
1785 std::cout << "Test timed out on Linux Intel. See crbug.com/680631." << std::endl;
1786 return;
1787 }
1788
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001789 int maxUniforms = 10000;
1790 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
1791 EXPECT_GL_NO_ERROR();
1792 std::cout << "Validating GL_MAX_FRAGMENT_UNIFORM_VECTORS = " << maxUniforms << std::endl;
1793
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001794 CompileGLSLWithUniformsAndSamplers(0, maxUniforms, 0, 0, true);
1795}
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001796
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001797// Tests that the maximum uniforms count returned from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
1798// can actually be used along with the maximum number of texture samplers.
1799TEST_P(GLSLTest, VerifyMaxFragmentUniformVectorsWithSamplers)
1800{
Geoff Lange0cc2a42016-01-20 10:58:17 -05001801 if (GetParam().eglParameters.renderer == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE ||
1802 GetParam().eglParameters.renderer == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
1803 {
1804 std::cout << "Test disabled on OpenGL." << std::endl;
1805 return;
1806 }
1807
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001808 int maxUniforms = 10000;
1809 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
1810 EXPECT_GL_NO_ERROR();
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001811
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001812 int maxTextureImageUnits = 0;
1813 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001814
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001815 CompileGLSLWithUniformsAndSamplers(0, maxUniforms, 0, maxTextureImageUnits, true);
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001816}
1817
1818// Tests that the maximum uniforms count + 1 from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
1819// fails shader compilation.
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001820TEST_P(GLSLTest, VerifyMaxFragmentUniformVectorsExceeded)
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001821{
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001822 int maxUniforms = 10000;
1823 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
1824 EXPECT_GL_NO_ERROR();
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001825 std::cout << "Validating GL_MAX_FRAGMENT_UNIFORM_VECTORS + 1 = " << maxUniforms + 1
1826 << std::endl;
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001827
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001828 CompileGLSLWithUniformsAndSamplers(0, maxUniforms + 1, 0, 0, false);
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001829}
1830
Geoff Langba992ab2017-04-19 11:18:14 -04001831// Test compiling shaders using the GL_EXT_shader_texture_lod extension
1832TEST_P(GLSLTest, TextureLOD)
1833{
1834 if (!extensionEnabled("GL_EXT_shader_texture_lod"))
1835 {
1836 std::cout << "Test skipped due to missing GL_EXT_shader_texture_lod." << std::endl;
1837 return;
1838 }
1839
1840 const std::string source =
1841 "#extension GL_EXT_shader_texture_lod : require\n"
1842 "uniform sampler2D u_texture;\n"
1843 "void main() {\n"
1844 " gl_FragColor = texture2DGradEXT(u_texture, vec2(0.0, 0.0), vec2(0.0, 0.0), vec2(0.0, "
1845 "0.0));\n"
1846 "}\n";
1847
1848 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, source);
1849 ASSERT_NE(0u, shader);
1850 glDeleteShader(shader);
1851}
1852
Olli Etuahobe59c2f2016-03-07 11:32:34 +02001853// Test that two constructors which have vec4 and mat2 parameters get disambiguated (issue in
1854// HLSL).
1855TEST_P(GLSLTest_ES3, AmbiguousConstructorCall2x2)
1856{
1857 const std::string fragmentShaderSource =
1858 "#version 300 es\n"
1859 "precision highp float;\n"
1860 "out vec4 my_FragColor;\n"
1861 "void main()\n"
1862 "{\n"
1863 " my_FragColor = vec4(0.0);\n"
1864 "}";
1865
1866 const std::string vertexShaderSource =
1867 "#version 300 es\n"
1868 "precision highp float;\n"
1869 "in vec4 a_vec;\n"
1870 "in mat2 a_mat;\n"
1871 "void main()\n"
1872 "{\n"
1873 " gl_Position = vec4(a_vec) + vec4(a_mat);\n"
1874 "}";
1875
1876 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1877 EXPECT_NE(0u, program);
1878}
1879
1880// Test that two constructors which have mat2x3 and mat3x2 parameters get disambiguated.
1881// This was suspected to be an issue in HLSL, but HLSL seems to be able to natively choose between
1882// the function signatures in this case.
1883TEST_P(GLSLTest_ES3, AmbiguousConstructorCall2x3)
1884{
1885 const std::string fragmentShaderSource =
1886 "#version 300 es\n"
1887 "precision highp float;\n"
1888 "out vec4 my_FragColor;\n"
1889 "void main()\n"
1890 "{\n"
1891 " my_FragColor = vec4(0.0);\n"
1892 "}";
1893
1894 const std::string vertexShaderSource =
1895 "#version 300 es\n"
1896 "precision highp float;\n"
1897 "in mat3x2 a_matA;\n"
1898 "in mat2x3 a_matB;\n"
1899 "void main()\n"
1900 "{\n"
1901 " gl_Position = vec4(a_matA) + vec4(a_matB);\n"
1902 "}";
1903
1904 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1905 EXPECT_NE(0u, program);
1906}
1907
1908// Test that two functions which have vec4 and mat2 parameters get disambiguated (issue in HLSL).
1909TEST_P(GLSLTest_ES3, AmbiguousFunctionCall2x2)
1910{
1911 const std::string fragmentShaderSource =
1912 "#version 300 es\n"
1913 "precision highp float;\n"
1914 "out vec4 my_FragColor;\n"
1915 "void main()\n"
1916 "{\n"
1917 " my_FragColor = vec4(0.0);\n"
1918 "}";
1919
1920 const std::string vertexShaderSource =
1921 "#version 300 es\n"
1922 "precision highp float;\n"
1923 "in vec4 a_vec;\n"
1924 "in mat2 a_mat;\n"
1925 "vec4 foo(vec4 a)\n"
1926 "{\n"
1927 " return a;\n"
1928 "}\n"
1929 "vec4 foo(mat2 a)\n"
1930 "{\n"
1931 " return vec4(a[0][0]);\n"
1932 "}\n"
1933 "void main()\n"
1934 "{\n"
1935 " gl_Position = foo(a_vec) + foo(a_mat);\n"
1936 "}";
1937
1938 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1939 EXPECT_NE(0u, program);
1940}
1941
1942// Test that an user-defined function with a large number of float4 parameters doesn't fail due to
1943// the function name being too long.
1944TEST_P(GLSLTest_ES3, LargeNumberOfFloat4Parameters)
1945{
1946 const std::string fragmentShaderSource =
1947 "#version 300 es\n"
1948 "precision highp float;\n"
1949 "out vec4 my_FragColor;\n"
1950 "void main()\n"
1951 "{\n"
1952 " my_FragColor = vec4(0.0);\n"
1953 "}";
1954
1955 std::stringstream vertexShaderStream;
1956 const unsigned int paramCount = 1024u;
1957
1958 vertexShaderStream << "#version 300 es\n"
1959 "precision highp float;\n"
1960 "in vec4 a_vec;\n"
1961 "vec4 lotsOfVec4Parameters(";
1962 for (unsigned int i = 0; i < paramCount; ++i)
1963 {
1964 vertexShaderStream << "vec4 a" << i << ", ";
1965 }
1966 vertexShaderStream << "vec4 aLast)\n"
1967 "{\n"
1968 " return ";
1969 for (unsigned int i = 0; i < paramCount; ++i)
1970 {
1971 vertexShaderStream << "a" << i << " + ";
1972 }
1973 vertexShaderStream << "aLast;\n"
1974 "}\n"
1975 "void main()\n"
1976 "{\n"
1977 " gl_Position = lotsOfVec4Parameters(";
1978 for (unsigned int i = 0; i < paramCount; ++i)
1979 {
1980 vertexShaderStream << "a_vec, ";
1981 }
1982 vertexShaderStream << "a_vec);\n"
1983 "}";
1984
1985 GLuint program = CompileProgram(vertexShaderStream.str(), fragmentShaderSource);
1986 EXPECT_NE(0u, program);
1987}
1988
Olli Etuahod4f4c112016-04-15 15:11:24 +03001989// This test was written specifically to stress DeferGlobalInitializers AST transformation.
1990// Test a shader where a global constant array is initialized with an expression containing array
1991// indexing. This initializer is tricky to constant fold, so if it's not constant folded it needs to
1992// be handled in a way that doesn't generate statements in the global scope in HLSL output.
1993// Also includes multiple array initializers in one declaration, where only the second one has
1994// array indexing. This makes sure that the qualifier for the declaration is set correctly if
1995// transformations are applied to the declaration also in the case of ESSL output.
1996TEST_P(GLSLTest_ES3, InitGlobalArrayWithArrayIndexing)
1997{
Yuly Novikov41db2242016-06-25 00:14:28 -04001998 // TODO(ynovikov): re-enable once root cause of http://anglebug.com/1428 is fixed
1999 if (IsAndroid() && IsAdreno() && IsOpenGLES())
2000 {
2001 std::cout << "Test skipped on Adreno OpenGLES on Android." << std::endl;
2002 return;
2003 }
2004
Olli Etuahod4f4c112016-04-15 15:11:24 +03002005 const std::string vertexShaderSource =
2006 "#version 300 es\n"
2007 "precision highp float;\n"
2008 "in vec4 a_vec;\n"
2009 "void main()\n"
2010 "{\n"
2011 " gl_Position = vec4(a_vec);\n"
2012 "}";
2013
2014 const std::string fragmentShaderSource =
2015 "#version 300 es\n"
2016 "precision highp float;\n"
2017 "out vec4 my_FragColor;\n"
2018 "const highp float f[2] = float[2](0.1, 0.2);\n"
2019 "const highp float[2] g = float[2](0.3, 0.4), h = float[2](0.5, f[1]);\n"
2020 "void main()\n"
2021 "{\n"
2022 " my_FragColor = vec4(h[1]);\n"
2023 "}";
2024
2025 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
2026 EXPECT_NE(0u, program);
2027}
2028
Corentin Wallez419bfc92016-06-28 10:54:45 -07002029// Test that index-constant sampler array indexing is supported.
2030TEST_P(GLSLTest, IndexConstantSamplerArrayIndexing)
2031{
2032 if (IsD3D11_FL93()) {
2033 std::cout << "Test skipped on D3D11 FL 9.3." << std::endl;
2034 return;
2035 }
2036
2037 const std::string vertexShaderSource =
2038 "attribute vec4 vPosition;\n"
2039 "void main()\n"
2040 "{\n"
2041 " gl_Position = vPosition;\n"
2042 "}";
2043
2044 const std::string fragmentShaderSource =
2045 "precision mediump float;\n"
2046 "uniform sampler2D uni[2];\n"
2047 "\n"
2048 "float zero(int x)\n"
2049 "{\n"
2050 " return float(x) - float(x);\n"
2051 "}\n"
2052 "\n"
2053 "void main()\n"
2054 "{\n"
2055 " vec4 c = vec4(0,0,0,0);\n"
2056 " for (int ii = 1; ii < 3; ++ii) {\n"
2057 " if (c.x > 255.0) {\n"
2058 " c.x = 255.0 + zero(ii);\n"
2059 " break;\n"
2060 " }\n"
2061 // Index the sampler array with a predictable loop index (index-constant) as opposed to
2062 // a true constant. This is valid in OpenGL ES but isn't in many Desktop OpenGL versions,
2063 // without an extension.
2064 " c += texture2D(uni[ii - 1], vec2(0.5, 0.5));\n"
2065 " }\n"
2066 " gl_FragColor = c;\n"
2067 "}";
2068
2069 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
2070 EXPECT_NE(0u, program);
2071}
2072
Corentin Wallezb00dcee2016-07-11 17:42:58 -04002073// Test that the #pragma directive is supported and doesn't trigger a compilation failure on the
2074// native driver. The only pragma that gets passed to the OpenGL driver is "invariant" but we don't
2075// want to test its behavior, so don't use any varyings.
2076TEST_P(GLSLTest, PragmaDirective)
2077{
2078 const std::string vertexShaderSource =
2079 "#pragma STDGL invariant(all)\n"
2080 "void main()\n"
2081 "{\n"
2082 " gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
2083 "}\n";
2084
2085 const std::string fragmentShaderSource =
2086 "precision mediump float;\n"
2087 "void main()\n"
2088 "{\n"
2089 " gl_FragColor = vec4(1.0);\n"
2090 "}\n";
2091
2092 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
2093 EXPECT_NE(0u, program);
2094}
2095
Olli Etuahoe1d199b2016-07-19 17:14:27 +03002096// Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
2097// The function call that returns the array needs to be evaluated after ++j for the expression to
2098// return the correct value (true).
2099TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderArray)
2100{
2101 const std::string &fragmentShaderSource =
2102 "#version 300 es\n"
2103 "precision mediump float;\n"
2104 "out vec4 my_FragColor; \n"
2105 "int[2] func(int param) {\n"
2106 " return int[2](param, param);\n"
2107 "}\n"
2108 "void main() {\n"
2109 " int a[2]; \n"
2110 " for (int i = 0; i < 2; ++i) {\n"
2111 " a[i] = 1;\n"
2112 " }\n"
2113 " int j = 0; \n"
2114 " bool result = ((++j), (a == func(j)));\n"
2115 " my_FragColor = vec4(0.0, (result ? 1.0 : 0.0), 0.0, 1.0);\n"
2116 "}\n";
2117
2118 GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
2119 ASSERT_NE(0u, program);
2120
2121 drawQuad(program, "inputAttribute", 0.5f);
2122
2123 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2124}
2125
2126// Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
2127// The short-circuiting expression needs to be evaluated after ++j for the expression to return the
2128// correct value (true).
2129TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderShortCircuit)
2130{
2131 const std::string &fragmentShaderSource =
2132 "#version 300 es\n"
2133 "precision mediump float;\n"
2134 "out vec4 my_FragColor; \n"
2135 "void main() {\n"
2136 " int j = 0; \n"
2137 " bool result = ((++j), (j == 1 ? true : (++j == 3)));\n"
2138 " my_FragColor = vec4(0.0, ((result && j == 1) ? 1.0 : 0.0), 0.0, 1.0);\n"
2139 "}\n";
2140
2141 GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
2142 ASSERT_NE(0u, program);
2143
2144 drawQuad(program, "inputAttribute", 0.5f);
2145
2146 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2147}
2148
Jamie Madill666f65a2016-08-26 01:34:37 +00002149// Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
2150// Indexing the vector needs to be evaluated after func() for the right result.
2151TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderDynamicVectorIndexingInLValue)
2152{
2153 const std::string &fragmentShaderSource =
2154 "#version 300 es\n"
2155 "precision mediump float;\n"
2156 "out vec4 my_FragColor;\n"
2157 "uniform int u_zero;\n"
2158 "int sideEffectCount = 0;\n"
2159 "float func() {\n"
2160 " ++sideEffectCount;\n"
2161 " return -1.0;\n"
2162 "}\n"
2163 "void main() {\n"
2164 " vec4 v = vec4(0.0, 2.0, 4.0, 6.0); \n"
2165 " float f = (func(), (++v[u_zero + sideEffectCount]));\n"
2166 " bool green = abs(f - 3.0) < 0.01 && abs(v[1] - 3.0) < 0.01 && sideEffectCount == 1;\n"
2167 " my_FragColor = vec4(0.0, (green ? 1.0 : 0.0), 0.0, 1.0);\n"
2168 "}\n";
2169
2170 GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
2171 ASSERT_NE(0u, program);
2172
2173 drawQuad(program, "inputAttribute", 0.5f);
2174
2175 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2176}
2177
Jamie Madillc9bde922016-07-24 17:58:50 -04002178// Test that using gl_PointCoord with GL_TRIANGLES doesn't produce a link error.
2179// From WebGL test conformance/rendering/point-specific-shader-variables.html
2180// See http://anglebug.com/1380
2181TEST_P(GLSLTest, RenderTrisWithPointCoord)
2182{
2183 const std::string &vert =
2184 "attribute vec2 aPosition;\n"
2185 "void main()\n"
2186 "{\n"
2187 " gl_Position = vec4(aPosition, 0, 1);\n"
2188 " gl_PointSize = 1.0;\n"
2189 "}";
2190 const std::string &frag =
2191 "void main()\n"
2192 "{\n"
2193 " gl_FragColor = vec4(gl_PointCoord.xy, 0, 1);\n"
2194 " gl_FragColor = vec4(0, 1, 0, 1);\n"
2195 "}";
2196
2197 ANGLE_GL_PROGRAM(prog, vert, frag);
2198 drawQuad(prog.get(), "aPosition", 0.5f);
2199 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2200}
2201
Jamie Madill5655b842016-08-02 11:00:07 -04002202// Convers a bug with the integer pow statement workaround.
2203TEST_P(GLSLTest, NestedPowStatements)
2204{
2205 const std::string &vert =
2206 "attribute vec2 position;\n"
2207 "void main()\n"
2208 "{\n"
2209 " gl_Position = vec4(position, 0, 1);\n"
2210 "}";
2211 const std::string &frag =
2212 "precision mediump float;\n"
2213 "float func(float v)\n"
2214 "{\n"
2215 " float f1 = pow(v, 2.0);\n"
2216 " return pow(f1 + v, 2.0);\n"
2217 "}\n"
2218 "void main()\n"
2219 "{\n"
2220 " float v = func(2.0);\n"
2221 " gl_FragColor = abs(v - 36.0) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
2222 "}";
2223
2224 ANGLE_GL_PROGRAM(prog, vert, frag);
2225 drawQuad(prog.get(), "position", 0.5f);
2226 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2227}
2228
Qiankun Miaof52fe932016-12-07 13:39:15 +08002229// Test that -float calculation is correct.
2230TEST_P(GLSLTest_ES3, UnaryMinusOperatorFloat)
2231{
Qiankun Miaof52fe932016-12-07 13:39:15 +08002232 const std::string &vert =
2233 "#version 300 es\n"
2234 "in highp vec4 position;\n"
2235 "void main() {\n"
2236 " gl_Position = position;\n"
2237 "}\n";
2238 const std::string &frag =
2239 "#version 300 es\n"
2240 "out highp vec4 o_color;\n"
2241 "void main() {\n"
2242 " highp float f = -1.0;\n"
2243 " // atan(tan(0.5), -f) should be 0.5.\n"
2244 " highp float v = atan(tan(0.5), -f);\n"
2245 " o_color = abs(v - 0.5) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
2246 "}\n";
2247
2248 ANGLE_GL_PROGRAM(prog, vert, frag);
2249 drawQuad(prog.get(), "position", 0.5f);
2250 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2251}
2252
Olli Etuahoda9fb092016-12-09 17:32:29 +00002253// Test that atan(vec2, vec2) calculation is correct.
2254TEST_P(GLSLTest_ES3, AtanVec2)
2255{
2256 const std::string &vert =
2257 "#version 300 es\n"
2258 "in highp vec4 position;\n"
2259 "void main() {\n"
2260 " gl_Position = position;\n"
2261 "}\n";
2262 const std::string &frag =
2263 "#version 300 es\n"
2264 "out highp vec4 o_color;\n"
2265 "void main() {\n"
2266 " highp float f = 1.0;\n"
2267 " // atan(tan(0.5), f) should be 0.5.\n"
2268 " highp vec2 v = atan(vec2(tan(0.5)), vec2(f));\n"
2269 " o_color = (abs(v[0] - 0.5) < 0.001 && abs(v[1] - 0.5) < 0.001) ? vec4(0, 1, 0, 1) : "
2270 "vec4(1, 0, 0, 1);\n"
2271 "}\n";
2272
2273 ANGLE_GL_PROGRAM(prog, vert, frag);
2274 drawQuad(prog.get(), "position", 0.5f);
2275 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2276}
2277
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002278// Convers a bug with the unary minus operator on signed integer workaround.
2279TEST_P(GLSLTest_ES3, UnaryMinusOperatorSignedInt)
2280{
2281 const std::string &vert =
2282 "#version 300 es\n"
2283 "in highp vec4 position;\n"
2284 "out mediump vec4 v_color;\n"
2285 "uniform int ui_one;\n"
2286 "uniform int ui_two;\n"
2287 "uniform int ui_three;\n"
2288 "void main() {\n"
2289 " int s[3];\n"
2290 " s[0] = ui_one;\n"
2291 " s[1] = -(-(-ui_two + 1) + 1);\n" // s[1] = -ui_two
2292 " s[2] = ui_three;\n"
2293 " int result = 0;\n"
2294 " for (int i = 0; i < ui_three; i++) {\n"
2295 " result += s[i];\n"
2296 " }\n"
2297 " v_color = (result == 2) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
2298 " gl_Position = position;\n"
2299 "}\n";
2300 const std::string &frag =
2301 "#version 300 es\n"
2302 "in mediump vec4 v_color;\n"
2303 "layout(location=0) out mediump vec4 o_color;\n"
2304 "void main() {\n"
2305 " o_color = v_color;\n"
2306 "}\n";
2307
2308 ANGLE_GL_PROGRAM(prog, vert, frag);
2309
Jamie Madille1faacb2016-12-13 12:42:14 -05002310 GLint oneIndex = glGetUniformLocation(prog.get(), "ui_one");
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002311 ASSERT_NE(-1, oneIndex);
Jamie Madille1faacb2016-12-13 12:42:14 -05002312 GLint twoIndex = glGetUniformLocation(prog.get(), "ui_two");
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002313 ASSERT_NE(-1, twoIndex);
Jamie Madille1faacb2016-12-13 12:42:14 -05002314 GLint threeIndex = glGetUniformLocation(prog.get(), "ui_three");
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002315 ASSERT_NE(-1, threeIndex);
2316 glUseProgram(prog.get());
2317 glUniform1i(oneIndex, 1);
2318 glUniform1i(twoIndex, 2);
2319 glUniform1i(threeIndex, 3);
2320
2321 drawQuad(prog.get(), "position", 0.5f);
2322 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2323}
2324
2325// Convers a bug with the unary minus operator on unsigned integer workaround.
2326TEST_P(GLSLTest_ES3, UnaryMinusOperatorUnsignedInt)
2327{
2328 const std::string &vert =
2329 "#version 300 es\n"
2330 "in highp vec4 position;\n"
2331 "out mediump vec4 v_color;\n"
2332 "uniform uint ui_one;\n"
2333 "uniform uint ui_two;\n"
2334 "uniform uint ui_three;\n"
2335 "void main() {\n"
2336 " uint s[3];\n"
2337 " s[0] = ui_one;\n"
2338 " s[1] = -(-(-ui_two + 1u) + 1u);\n" // s[1] = -ui_two
2339 " s[2] = ui_three;\n"
2340 " uint result = 0u;\n"
2341 " for (uint i = 0u; i < ui_three; i++) {\n"
2342 " result += s[i];\n"
2343 " }\n"
2344 " v_color = (result == 2u) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
2345 " gl_Position = position;\n"
2346 "}\n";
2347 const std::string &frag =
2348 "#version 300 es\n"
2349 "in mediump vec4 v_color;\n"
2350 "layout(location=0) out mediump vec4 o_color;\n"
2351 "void main() {\n"
2352 " o_color = v_color;\n"
2353 "}\n";
2354
2355 ANGLE_GL_PROGRAM(prog, vert, frag);
2356
Jamie Madille1faacb2016-12-13 12:42:14 -05002357 GLint oneIndex = glGetUniformLocation(prog.get(), "ui_one");
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002358 ASSERT_NE(-1, oneIndex);
Jamie Madille1faacb2016-12-13 12:42:14 -05002359 GLint twoIndex = glGetUniformLocation(prog.get(), "ui_two");
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002360 ASSERT_NE(-1, twoIndex);
Jamie Madille1faacb2016-12-13 12:42:14 -05002361 GLint threeIndex = glGetUniformLocation(prog.get(), "ui_three");
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002362 ASSERT_NE(-1, threeIndex);
2363 glUseProgram(prog.get());
2364 glUniform1ui(oneIndex, 1u);
2365 glUniform1ui(twoIndex, 2u);
2366 glUniform1ui(threeIndex, 3u);
2367
2368 drawQuad(prog.get(), "position", 0.5f);
2369 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2370}
2371
Olli Etuahoab481642016-08-26 12:09:10 +03002372// Test a nested sequence operator with a ternary operator inside. The ternary operator is
2373// intended to be such that it gets converted to an if statement on the HLSL backend.
2374TEST_P(GLSLTest, NestedSequenceOperatorWithTernaryInside)
2375{
2376 const std::string &vert =
2377 "attribute vec2 position;\n"
2378 "void main()\n"
2379 "{\n"
2380 " gl_Position = vec4(position, 0, 1);\n"
2381 "}";
2382
2383 // Note that the uniform keep_flop_positive doesn't need to be set - the test expects it to have
2384 // its default value false.
2385 const std::string &frag =
2386 "precision mediump float;\n"
2387 "uniform bool keep_flop_positive;\n"
2388 "float flop;\n"
2389 "void main() {\n"
2390 " flop = -1.0,\n"
2391 " (flop *= -1.0,\n"
2392 " keep_flop_positive ? 0.0 : flop *= -1.0),\n"
2393 " gl_FragColor = vec4(0, -flop, 0, 1);\n"
2394 "}";
2395
2396 ANGLE_GL_PROGRAM(prog, vert, frag);
2397 drawQuad(prog.get(), "position", 0.5f);
2398 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2399}
2400
Geoff Lang28a97ee2016-09-22 13:01:26 -04002401// Test that using a sampler2D and samplerExternalOES in the same shader works (anglebug.com/1534)
2402TEST_P(GLSLTest, ExternalAnd2DSampler)
2403{
2404 if (!extensionEnabled("GL_OES_EGL_image_external"))
2405 {
2406 std::cout << "Test skipped because GL_OES_EGL_image_external is not available."
2407 << std::endl;
2408 return;
2409 }
2410
2411 const std::string fragmentShader =
Olli Etuaho703671e2017-11-08 17:47:18 +02002412 R"(
2413 #extension GL_OES_EGL_image_external : enable
2414 precision mediump float;
2415 uniform samplerExternalOES tex0;
2416 uniform sampler2D tex1;
2417 void main(void)
2418 {
2419 vec2 uv = vec2(0.0, 0.0);
2420 gl_FragColor = texture2D(tex0, uv) + texture2D(tex1, uv);
2421 })";
Geoff Lang28a97ee2016-09-22 13:01:26 -04002422
2423 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2424}
2425
Olli Etuaho56a2f952016-12-08 12:16:27 +00002426// Test that literal infinity can be written out from the shader translator.
2427// A similar test can't be made for NaNs, since ESSL 3.00.6 requirements for NaNs are very loose.
2428TEST_P(GLSLTest_ES3, LiteralInfinityOutput)
2429{
2430 const std::string &fragmentShader =
2431 "#version 300 es\n"
2432 "precision highp float;\n"
2433 "out vec4 out_color;\n"
2434 "uniform float u;\n"
2435 "void main()\n"
2436 "{\n"
2437 " float infVar = 1.0e40 - u;\n"
2438 " bool correct = isinf(infVar) && infVar > 0.0;\n"
2439 " out_color = correct ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
2440 "}\n";
2441
2442 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2443 drawQuad(program.get(), "inputAttribute", 0.5f);
2444 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2445}
2446
2447// Test that literal negative infinity can be written out from the shader translator.
2448// A similar test can't be made for NaNs, since ESSL 3.00.6 requirements for NaNs are very loose.
2449TEST_P(GLSLTest_ES3, LiteralNegativeInfinityOutput)
2450{
2451 const std::string &fragmentShader =
2452 "#version 300 es\n"
2453 "precision highp float;\n"
2454 "out vec4 out_color;\n"
2455 "uniform float u;\n"
2456 "void main()\n"
2457 "{\n"
2458 " float infVar = -1.0e40 + u;\n"
2459 " bool correct = isinf(infVar) && infVar < 0.0;\n"
2460 " out_color = correct ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
2461 "}\n";
2462
2463 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2464 drawQuad(program.get(), "inputAttribute", 0.5f);
2465 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2466}
2467
Corentin Wallez36fd1002016-12-08 11:30:44 -05002468// The following MultipleDeclaration* tests are testing TranslatorHLSL specific simplification
2469// passes. Because the interaction of multiple passes must be tested, it is difficult to write
2470// a unittest for them. Instead we add the tests as end2end so will in particular test
2471// TranslatorHLSL when run on Windows.
2472
2473// Test that passes splitting multiple declarations and comma operators are correctly ordered.
2474TEST_P(GLSLTest_ES3, MultipleDeclarationWithCommaOperator)
2475{
2476 const std::string &fragmentShader =
Olli Etuaho7caa80e2017-11-14 15:03:14 +02002477 R"(#version 300 es
2478 precision mediump float;
2479 out vec4 color;
2480
2481 uniform float u;
2482 float c = 0.0;
2483 float sideEffect()
2484 {
2485 c = u;
2486 return c;
2487 }
2488
2489 void main(void)
2490 {
2491 float a = 0.0, b = ((gl_FragCoord.x < 0.5 ? a : sideEffect()), a);
2492 color = vec4(b + c);
2493 })";
Corentin Wallez36fd1002016-12-08 11:30:44 -05002494
2495 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2496}
2497
2498// Test that passes splitting multiple declarations and comma operators and for loops are
2499// correctly ordered.
2500TEST_P(GLSLTest_ES3, MultipleDeclarationWithCommaOperatorInForLoop)
2501{
2502 const std::string &fragmentShader =
Olli Etuaho7caa80e2017-11-14 15:03:14 +02002503 R"(#version 300 es
2504 precision mediump float;
2505 out vec4 color;
2506
2507 uniform float u;
2508 float c = 0.0;
2509 float sideEffect()
2510 {
2511 c = u;
2512 return c;
2513 }
2514
2515 void main(void)
2516 {
2517 for(float a = 0.0, b = ((gl_FragCoord.x < 0.5 ? a : sideEffect()), a); a < 10.0; a++)
2518 {
2519 b += 1.0;
2520 color = vec4(b);
2521 }
2522 })";
Corentin Wallez36fd1002016-12-08 11:30:44 -05002523
2524 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2525}
2526
2527// Test that splitting multiple declaration in for loops works with no loop condition
2528TEST_P(GLSLTest_ES3, MultipleDeclarationInForLoopEmptyCondition)
2529{
2530 const std::string &fragmentShader =
2531 "#version 300 es\n"
2532 "precision mediump float;\n"
2533 "out vec4 color;\n"
2534 "void main(void)\n"
2535 "{\n"
2536 " for(float a = 0.0, b = 1.0;; a++)\n"
2537 " {\n"
2538 " b += 1.0;\n"
2539 " if (a > 10.0) {break;}\n"
2540 " color = vec4(b);\n"
2541 " }\n"
2542 "}\n";
2543
2544 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2545}
2546
2547// Test that splitting multiple declaration in for loops works with no loop expression
2548TEST_P(GLSLTest_ES3, MultipleDeclarationInForLoopEmptyExpression)
2549{
2550 const std::string &fragmentShader =
2551 "#version 300 es\n"
2552 "precision mediump float;\n"
2553 "out vec4 color;\n"
2554 "void main(void)\n"
2555 "{\n"
2556 " for(float a = 0.0, b = 1.0; a < 10.0;)\n"
2557 " {\n"
2558 " b += 1.0;\n"
2559 " a += 1.0;\n"
2560 " color = vec4(b);\n"
2561 " }\n"
2562 "}\n";
2563
2564 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2565}
2566
Olli Etuaho8f6eb2a2017-01-12 17:04:58 +00002567// Test that dynamic indexing of a matrix inside a dynamic indexing of a vector in an l-value works
2568// correctly.
2569TEST_P(GLSLTest_ES3, NestedDynamicIndexingInLValue)
2570{
2571 const std::string &fragmentShader =
2572 "#version 300 es\n"
2573 "precision mediump float;\n"
2574 "out vec4 my_FragColor;\n"
2575 "uniform int u_zero;\n"
2576 "void main() {\n"
2577 " mat2 m = mat2(0.0, 0.0, 0.0, 0.0);\n"
2578 " m[u_zero + 1][u_zero + 1] = float(u_zero + 1);\n"
2579 " float f = m[1][1];\n"
2580 " my_FragColor = vec4(1.0 - f, f, 0.0, 1.0);\n"
2581 "}\n";
2582
2583 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2584 drawQuad(program.get(), "inputAttribute", 0.5f);
2585 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2586}
2587
Jamie Madill192745a2016-12-22 15:58:21 -05002588class WebGLGLSLTest : public GLSLTest
2589{
2590 protected:
2591 WebGLGLSLTest() { setWebGLCompatibilityEnabled(true); }
2592};
2593
2594TEST_P(WebGLGLSLTest, MaxVaryingVec4PlusFragCoord)
2595{
2596 GLint maxVaryings = 0;
2597 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2598
2599 // Generate shader code that uses gl_FragCoord, a special fragment shader variables.
2600 // This test should fail, since we are really using (maxVaryings + 1) varyings.
2601 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, true, false, false, false);
2602}
2603
2604TEST_P(WebGLGLSLTest, MaxVaryingVec4PlusPointCoord)
2605{
2606 GLint maxVaryings = 0;
2607 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2608
2609 // Generate shader code that uses gl_FragCoord, a special fragment shader variables.
2610 // This test should fail, since we are really using (maxVaryings + 1) varyings.
2611 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, false, true, false, false);
2612}
2613
2614TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec3)
2615{
2616 GLint maxVaryings = 0;
2617 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2618
2619 VaryingTestBase(0, 0, 0, 0, maxVaryings + 1, 0, 0, 0, false, false, false, false);
2620}
2621
2622TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec3Array)
2623{
2624 GLint maxVaryings = 0;
2625 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2626
2627 VaryingTestBase(0, 0, 0, 0, 0, maxVaryings / 2 + 1, 0, 0, false, false, false, false);
2628}
2629
2630TEST_P(WebGLGLSLTest, MaxVaryingVec3AndOneVec2)
2631{
2632 GLint maxVaryings = 0;
2633 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2634
2635 VaryingTestBase(0, 0, 1, 0, maxVaryings, 0, 0, 0, false, false, false, false);
2636}
2637
2638TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec2)
2639{
2640 GLint maxVaryings = 0;
2641 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2642
2643 VaryingTestBase(0, 0, 2 * maxVaryings + 1, 0, 0, 0, 0, 0, false, false, false, false);
2644}
2645
2646TEST_P(WebGLGLSLTest, MaxVaryingVec3ArrayAndMaxPlusOneFloatArray)
2647{
2648 GLint maxVaryings = 0;
2649 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2650
2651 VaryingTestBase(0, maxVaryings / 2 + 1, 0, 0, 0, 0, 0, maxVaryings / 2, false, false, false,
2652 false);
2653}
2654
Jamie Madill6c9503e2016-08-16 14:06:32 -04002655} // anonymous namespace
2656
Olli Etuaho9250cb22017-01-21 10:51:27 +00002657// Test that FindLSB and FindMSB return correct values in their corner cases.
2658TEST_P(GLSLTest_ES31, FindMSBAndFindLSBCornerCases)
2659{
Olli Etuaho61bd9fe2017-01-27 14:20:34 -08002660 // Suspecting AMD driver bug - failure seen on bots running on AMD R5 230.
2661 if (IsAMD() && IsOpenGL() && IsLinux())
2662 {
2663 std::cout << "Test skipped on AMD OpenGL Linux" << std::endl;
2664 return;
2665 }
2666
Olli Etuaho9250cb22017-01-21 10:51:27 +00002667 const std::string &fragmentShader =
2668 "#version 310 es\n"
2669 "precision mediump float;\n"
2670 "out vec4 my_FragColor;\n"
2671 "uniform int u_zero;\n"
2672 "void main() {\n"
2673 " if (findLSB(u_zero) == -1 && findMSB(u_zero) == -1 && findMSB(u_zero - 1) == -1)\n"
2674 " {\n"
2675 " my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
2676 " }\n"
2677 " else\n"
2678 " {\n"
2679 " my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
2680 " }\n"
2681 "}\n";
2682
2683 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2684 drawQuad(program.get(), "inputAttribute", 0.5f);
2685 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2686}
2687
Olli Etuahoc9da71f2017-03-06 16:28:54 +00002688// Test that writing into a swizzled vector that is dynamically indexed succeeds.
2689TEST_P(GLSLTest_ES3, WriteIntoDynamicIndexingOfSwizzledVector)
2690{
Corentin Wallez6445ddf2017-03-08 19:00:32 -05002691 if (IsOpenGL())
Olli Etuahoc9da71f2017-03-06 16:28:54 +00002692 {
2693 // http://anglebug.com/1924
Corentin Wallez6445ddf2017-03-08 19:00:32 -05002694 std::cout << "Test skipped on all OpenGL configurations because it has incorrect results"
2695 << std::endl;
Olli Etuahoc9da71f2017-03-06 16:28:54 +00002696 return;
2697 }
2698
2699 // The shader first assigns v.x to v.z (1.0)
2700 // Then v.y to v.y (2.0)
2701 // Then v.z to v.x (1.0)
2702 const std::string &fragmentShader =
2703 "#version 300 es\n"
2704 "precision highp float;\n"
2705 "out vec4 my_FragColor;\n"
2706 "void main() {\n"
2707 " vec3 v = vec3(1.0, 2.0, 3.0);\n"
2708 " for (int i = 0; i < 3; i++) {\n"
2709 " v.zyx[i] = v[i];\n"
2710 " }\n"
2711 " my_FragColor = distance(v, vec3(1.0, 2.0, 1.0)) < 0.01 ? vec4(0, 1, 0, 1) : vec4(1, "
2712 "0, 0, 1);\n"
2713 "}\n";
2714
2715 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2716 drawQuad(program.get(), "inputAttribute", 0.5f);
2717 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2718}
2719
Jamie Madill8aeeed62017-03-15 18:09:26 -04002720// This test covers a bug (and associated workaround) with nested sampling operations in the HLSL
2721// compiler DLL.
2722TEST_P(GLSLTest_ES3, NestedSamplingOperation)
2723{
2724 // This seems to be bugged on some version of Android. Might not affect the newest versions.
2725 // TODO(jmadill): Lift suppression when Chromium bots are upgraded.
2726 if (IsAndroid() && IsOpenGLES())
2727 {
2728 std::cout << "Test skipped on Android because of bug with Nexus 5X." << std::endl;
2729 return;
2730 }
2731
2732 const std::string &vertexShader =
2733 "#version 300 es\n"
2734 "out vec2 texCoord;\n"
2735 "in vec2 position;\n"
2736 "void main()\n"
2737 "{\n"
2738 " gl_Position = vec4(position, 0, 1);\n"
2739 " texCoord = position * 0.5 + vec2(0.5);\n"
2740 "}\n";
2741
2742 const std::string &simpleFragmentShader =
2743 "#version 300 es\n"
2744 "in mediump vec2 texCoord;\n"
2745 "out mediump vec4 fragColor;\n"
2746 "void main()\n"
2747 "{\n"
2748 " fragColor = vec4(texCoord, 0, 1);\n"
2749 "}\n";
2750
2751 const std::string &nestedFragmentShader =
2752 "#version 300 es\n"
2753 "uniform mediump sampler2D samplerA;\n"
2754 "uniform mediump sampler2D samplerB;\n"
2755 "in mediump vec2 texCoord;\n"
2756 "out mediump vec4 fragColor;\n"
2757 "void main ()\n"
2758 "{\n"
2759 " fragColor = texture(samplerB, texture(samplerA, texCoord).xy);\n"
2760 "}\n";
2761
2762 ANGLE_GL_PROGRAM(initProg, vertexShader, simpleFragmentShader);
2763 ANGLE_GL_PROGRAM(nestedProg, vertexShader, nestedFragmentShader);
2764
2765 // Initialize a first texture with default texCoord data.
2766 GLTexture texA;
2767 glActiveTexture(GL_TEXTURE0);
2768 glBindTexture(GL_TEXTURE_2D, texA);
2769 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
2770 GL_UNSIGNED_BYTE, nullptr);
2771 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2772 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2773
2774 GLFramebuffer fbo;
2775 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2776 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texA, 0);
2777
2778 drawQuad(initProg, "position", 0.5f);
2779 ASSERT_GL_NO_ERROR();
2780
2781 // Initialize a second texture with a simple color pattern.
2782 GLTexture texB;
2783 glActiveTexture(GL_TEXTURE1);
2784 glBindTexture(GL_TEXTURE_2D, texB);
2785
2786 std::array<GLColor, 4> simpleColors = {
2787 {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
2788 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2789 simpleColors.data());
2790 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2791 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2792
2793 // Draw with the nested program, using the first texture to index the second.
2794 glBindFramebuffer(GL_FRAMEBUFFER, 0);
2795 glUseProgram(nestedProg);
2796 GLint samplerALoc = glGetUniformLocation(nestedProg, "samplerA");
2797 ASSERT_NE(-1, samplerALoc);
2798 glUniform1i(samplerALoc, 0);
2799 GLint samplerBLoc = glGetUniformLocation(nestedProg, "samplerB");
2800 ASSERT_NE(-1, samplerBLoc);
2801 glUniform1i(samplerBLoc, 1);
2802
2803 drawQuad(nestedProg, "position", 0.5f);
2804 ASSERT_GL_NO_ERROR();
2805
2806 // Compute four texel centers.
2807 Vector2 windowSize(getWindowWidth(), getWindowHeight());
2808 Vector2 quarterWindowSize = windowSize / 4;
2809 Vector2 ul = quarterWindowSize;
2810 Vector2 ur(windowSize.x() - quarterWindowSize.x(), quarterWindowSize.y());
2811 Vector2 ll(quarterWindowSize.x(), windowSize.y() - quarterWindowSize.y());
2812 Vector2 lr = windowSize - quarterWindowSize;
2813
2814 EXPECT_PIXEL_COLOR_EQ_VEC2(ul, simpleColors[0]);
2815 EXPECT_PIXEL_COLOR_EQ_VEC2(ur, simpleColors[1]);
2816 EXPECT_PIXEL_COLOR_EQ_VEC2(ll, simpleColors[2]);
2817 EXPECT_PIXEL_COLOR_EQ_VEC2(lr, simpleColors[3]);
2818}
2819
Olli Etuaho81629262017-04-19 11:56:01 +03002820// Tests that using a constant declaration as the only statement in a for loop without curly braces
2821// doesn't crash.
2822TEST_P(GLSLTest, ConstantStatementInForLoop)
2823{
2824 const std::string &vertexShader =
2825 "void main()\n"
2826 "{\n"
2827 " for (int i = 0; i < 10; ++i)\n"
2828 " const int b = 0;\n"
2829 "}\n";
2830
2831 GLuint shader = CompileShader(GL_VERTEX_SHADER, vertexShader);
2832 EXPECT_NE(0u, shader);
2833 glDeleteShader(shader);
2834}
2835
2836// Tests that using a constant declaration as a loop init expression doesn't crash. Note that this
2837// test doesn't work on D3D9 due to looping limitations, so it is only run on ES3.
2838TEST_P(GLSLTest_ES3, ConstantStatementAsLoopInit)
2839{
2840 const std::string &vertexShader =
2841 "void main()\n"
2842 "{\n"
2843 " for (const int i = 0; i < 0;) {}\n"
2844 "}\n";
2845
2846 GLuint shader = CompileShader(GL_VERTEX_SHADER, vertexShader);
2847 EXPECT_NE(0u, shader);
2848 glDeleteShader(shader);
2849}
2850
Olli Etuaho9733cee2017-05-11 19:14:35 +03002851// Test that uninitialized local variables are initialized to 0.
2852TEST_P(GLSLTest_ES3, InitUninitializedLocals)
2853{
2854 if (IsAndroid() && IsOpenGLES())
2855 {
2856 // http://anglebug.com/2046
2857 std::cout
2858 << "Test skipped on Android GLES because local variable initialization is disabled."
2859 << std::endl;
2860 return;
2861 }
2862
Olli Etuaho9733cee2017-05-11 19:14:35 +03002863 const std::string &fragmentShader =
2864 "#version 300 es\n"
2865 "precision mediump float;\n"
2866 "out vec4 my_FragColor;\n"
2867 "int result = 0;\n"
2868 "void main()\n"
2869 "{\n"
2870 " int u;\n"
2871 " result += u;\n"
2872 " int k = 0;\n"
2873 " for (int i[2], j = i[0] + 1; k < 2; ++k)\n"
2874 " {\n"
2875 " result += j;\n"
2876 " }\n"
2877 " if (result == 2)\n"
2878 " {\n"
2879 " my_FragColor = vec4(0, 1, 0, 1);\n"
2880 " }\n"
2881 " else\n"
2882 " {\n"
2883 " my_FragColor = vec4(1, 0, 0, 1);\n"
2884 " }\n"
2885 "}\n";
2886
2887 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2888 drawQuad(program.get(), "inputAttribute", 0.5f);
2889 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2890}
2891
2892// Test that uninitialized structs containing arrays of structs are initialized to 0. This
2893// specifically tests with two different struct variables declared in the same block.
2894TEST_P(GLSLTest, InitUninitializedStructContainingArrays)
2895{
2896 if (IsAndroid() && IsOpenGLES())
2897 {
2898 // http://anglebug.com/2046
2899 std::cout
2900 << "Test skipped on Android GLES because local variable initialization is disabled."
2901 << std::endl;
2902 return;
2903 }
2904
2905 if (IsOSX() && IsOpenGL())
2906 {
2907 // http://anglebug.com/2041
2908 std::cout << "Test skipped on Mac OpenGL because local variable initialization is disabled."
2909 << std::endl;
2910 return;
2911 }
2912
2913 const std::string &fragmentShader =
2914 "precision mediump float;\n"
2915 "struct T\n"
2916 "{\n"
2917 " int a[2];\n"
2918 "};\n"
2919 "struct S\n"
2920 "{\n"
2921 " T t[2];\n"
2922 "};\n"
2923 "void main()\n"
2924 "{\n"
2925 " S s;\n"
2926 " S s2;\n"
2927 " if (s.t[1].a[1] == 0 && s2.t[1].a[1] == 0)\n"
2928 " {\n"
2929 " gl_FragColor = vec4(0, 1, 0, 1);\n"
2930 " }\n"
2931 " else\n"
2932 " {\n"
2933 " gl_FragColor = vec4(1, 0, 0, 1);\n"
2934 " }\n"
2935 "}\n";
2936
2937 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2938 drawQuad(program.get(), "inputAttribute", 0.5f);
2939 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2940}
2941
Geoff Langbb1e7502017-06-05 16:40:09 -04002942// Verify that two shaders with the same uniform name and members but different structure names will
2943// not link.
2944TEST_P(GLSLTest, StructureNameMatchingTest)
2945{
2946 const char *vsSource =
2947 "// Structures must have the same name, sequence of type names, and\n"
2948 "// type definitions, and field names to be considered the same type.\n"
2949 "// GLSL 1.017 4.2.4\n"
2950 "precision mediump float;\n"
2951 "struct info {\n"
2952 " vec4 pos;\n"
2953 " vec4 color;\n"
2954 "};\n"
2955 "\n"
2956 "uniform info uni;\n"
2957 "void main()\n"
2958 "{\n"
2959 " gl_Position = uni.pos;\n"
2960 "}\n";
2961
2962 GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
2963 ASSERT_NE(0u, vs);
2964 glDeleteShader(vs);
2965
2966 const char *fsSource =
2967 "// Structures must have the same name, sequence of type names, and\n"
2968 "// type definitions, and field names to be considered the same type.\n"
2969 "// GLSL 1.017 4.2.4\n"
2970 "precision mediump float;\n"
2971 "struct info1 {\n"
2972 " vec4 pos;\n"
2973 " vec4 color;\n"
2974 "};\n"
2975 "\n"
2976 "uniform info1 uni;\n"
2977 "void main()\n"
2978 "{\n"
2979 " gl_FragColor = uni.color;\n"
2980 "}\n";
2981
2982 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
2983 ASSERT_NE(0u, fs);
2984 glDeleteShader(fs);
2985
2986 GLuint program = CompileProgram(vsSource, fsSource);
2987 EXPECT_EQ(0u, program);
2988}
2989
Olli Etuaho9733cee2017-05-11 19:14:35 +03002990// Test that an uninitialized nameless struct inside a for loop init statement works.
2991TEST_P(GLSLTest_ES3, UninitializedNamelessStructInForInitStatement)
2992{
2993 if (IsAndroid() && IsOpenGLES())
2994 {
2995 // http://anglebug.com/2046
2996 std::cout
2997 << "Test skipped on Android GLES because local variable initialization is disabled."
2998 << std::endl;
2999 return;
3000 }
3001
3002 if (IsOSX() && IsOpenGL())
3003 {
3004 // http://anglebug.com/2041
3005 std::cout << "Test skipped on Mac OpenGL because local variable initialization is disabled."
3006 << std::endl;
3007 return;
3008 }
3009
3010 const std::string &fragmentShader =
3011 "#version 300 es\n"
3012 "precision highp float;\n"
3013 "out vec4 my_FragColor;\n"
3014 "void main()\n"
3015 "{\n"
3016 " my_FragColor = vec4(1, 0, 0, 1);\n"
3017 " for (struct { float q; } b; b.q < 2.0; b.q++) {\n"
3018 " my_FragColor = vec4(0, 1, 0, 1);\n"
3019 " }\n"
3020 "}\n";
3021
3022 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3023 drawQuad(program.get(), "inputAttribute", 0.5f);
3024 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3025}
3026
Olli Etuaho0ffc4412017-05-19 14:18:55 +03003027// Test that uninitialized global variables are initialized to 0.
3028TEST_P(WebGLGLSLTest, InitUninitializedGlobals)
3029{
3030 const std::string &fragmentShader =
3031 "precision mediump float;\n"
3032 "int result;\n"
3033 "int i[2], j = i[0] + 1;\n"
3034 "void main()\n"
3035 "{\n"
3036 " result += j;\n"
3037 " if (result == 1)\n"
3038 " {\n"
3039 " gl_FragColor = vec4(0, 1, 0, 1);\n"
3040 " }\n"
3041 " else\n"
3042 " {\n"
3043 " gl_FragColor = vec4(1, 0, 0, 1);\n"
3044 " }\n"
3045 "}\n";
3046
3047 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3048 drawQuad(program.get(), "inputAttribute", 0.5f, 1.0f, true);
3049 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3050}
3051
3052// Test that an uninitialized nameless struct in the global scope works.
3053TEST_P(WebGLGLSLTest, UninitializedNamelessStructInGlobalScope)
3054{
3055 const std::string &fragmentShader =
3056 "precision mediump float;\n"
3057 "struct { float q; } b;\n"
3058 "void main()\n"
3059 "{\n"
3060 " gl_FragColor = vec4(1, 0, 0, 1);\n"
3061 " if (b.q == 0.0)\n"
3062 " {\n"
3063 " gl_FragColor = vec4(0, 1, 0, 1);\n"
3064 " }\n"
3065 "}\n";
3066
3067 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3068 drawQuad(program.get(), "inputAttribute", 0.5f, 1.0f, true);
3069 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3070}
3071
Olli Etuaho914b79a2017-06-19 16:03:19 +03003072// Test that a loop condition that has an initializer declares a variable.
3073TEST_P(GLSLTest_ES3, ConditionInitializerDeclaresVariable)
3074{
3075 const std::string &fragmentShader =
3076 "#version 300 es\n"
3077 "precision highp float;\n"
3078 "out vec4 my_FragColor;\n"
3079 "void main()\n"
3080 "{\n"
3081 " float i = 0.0;\n"
3082 " while (bool foo = (i < 1.5))\n"
3083 " {\n"
3084 " if (!foo)\n"
3085 " {\n"
3086 " ++i;\n"
3087 " }\n"
3088 " if (i > 3.5)\n"
3089 " {\n"
3090 " break;\n"
3091 " }\n"
3092 " ++i;\n"
3093 " }\n"
3094 " my_FragColor = vec4(i * 0.5 - 1.0, i * 0.5, 0.0, 1.0);\n"
3095 "}\n";
3096
3097 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3098 drawQuad(program.get(), "inputAttribute", 0.5f);
3099 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3100}
3101
Olli Etuahoff526f12017-06-30 12:26:54 +03003102// Test that a variable hides a user-defined function with the same name after its initializer.
3103// GLSL ES 1.00.17 section 4.2.2: "A variable declaration is visible immediately following the
3104// initializer if present, otherwise immediately following the identifier"
3105TEST_P(GLSLTest, VariableHidesUserDefinedFunctionAfterInitializer)
3106{
3107 const std::string &fragmentShader =
3108 "precision mediump float;\n"
3109 "uniform vec4 u;\n"
3110 "vec4 foo()\n"
3111 "{\n"
3112 " return u;\n"
3113 "}\n"
3114 "void main()\n"
3115 "{\n"
3116 " vec4 foo = foo();\n"
3117 " gl_FragColor = foo + vec4(0, 1, 0, 1);\n"
3118 "}\n";
3119
3120 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3121 drawQuad(program.get(), "inputAttribute", 0.5f);
3122 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3123}
3124
Olli Etuaho088031e2017-07-03 15:59:33 +03003125// Test that structs with identical members are not ambiguous as function arguments.
3126TEST_P(GLSLTest, StructsWithSameMembersDisambiguatedByName)
3127{
3128 const std::string &fragmentShader =
3129 "precision mediump float;\n"
3130 "uniform float u_zero;\n"
3131 "struct S { float foo; };\n"
3132 "struct S2 { float foo; };\n"
3133 "float get(S s) { return s.foo + u_zero; }\n"
3134 "float get(S2 s2) { return 0.25 + s2.foo + u_zero; }\n"
3135 "void main()\n"
3136 "{\n"
3137 " S s;\n"
3138 " s.foo = 0.5;\n"
3139 " S2 s2;\n"
3140 " s2.foo = 0.25;\n"
3141 " gl_FragColor = vec4(0.0, get(s) + get(s2), 0.0, 1.0);\n"
3142 "}\n";
3143
3144 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3145 drawQuad(program.get(), "inputAttribute", 0.5f);
3146 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3147}
3148
Olli Etuaho06a06f52017-07-12 12:22:15 +03003149// Test that a varying struct that's not statically used in the fragment shader works.
3150// GLSL ES 3.00.6 section 4.3.10.
3151TEST_P(GLSLTest_ES3, VaryingStructNotStaticallyUsedInFragmentShader)
3152{
3153 const std::string &vertexShader =
3154 "#version 300 es\n"
3155 "struct S {\n"
3156 " vec4 field;\n"
3157 "};\n"
3158 "out S varStruct;\n"
3159 "void main()\n"
3160 "{\n"
3161 " gl_Position = vec4(1.0);\n"
3162 " varStruct.field = vec4(0.0, 0.5, 0.0, 0.0);\n"
3163 "}\n";
3164
3165 const std::string &fragmentShader =
3166 "#version 300 es\n"
3167 "precision mediump float;\n"
3168 "struct S {\n"
3169 " vec4 field;\n"
3170 "};\n"
3171 "in S varStruct;\n"
3172 "out vec4 col;\n"
3173 "void main()\n"
3174 "{\n"
3175 " col = vec4(1.0);\n"
3176 "}\n";
3177
3178 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3179}
3180
3181// Test that a varying struct that's not declared in the fragment shader links successfully.
3182// GLSL ES 3.00.6 section 4.3.10.
3183TEST_P(GLSLTest_ES3, VaryingStructNotDeclaredInFragmentShader)
3184{
3185 const std::string &vertexShader =
3186 "#version 300 es\n"
3187 "struct S {\n"
3188 " vec4 field;\n"
3189 "};\n"
3190 "out S varStruct;\n"
3191 "void main()\n"
3192 "{\n"
3193 " gl_Position = vec4(1.0);\n"
3194 " varStruct.field = vec4(0.0, 0.5, 0.0, 0.0);\n"
3195 "}\n";
3196
3197 const std::string &fragmentShader =
3198 "#version 300 es\n"
3199 "precision mediump float;\n"
3200 "out vec4 col;\n"
3201 "void main()\n"
3202 "{\n"
3203 " col = vec4(1.0);\n"
3204 "}\n";
3205
3206 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3207}
3208
3209// Test that a varying struct that gets used in the fragment shader works.
3210TEST_P(GLSLTest_ES3, VaryingStructUsedInFragmentShader)
3211{
3212 const std::string &vertexShader =
3213 "#version 300 es\n"
3214 "in vec4 inputAttribute;\n"
3215 "struct S {\n"
3216 " vec4 field;\n"
3217 "};\n"
3218 "out S varStruct;\n"
3219 "void main()\n"
3220 "{\n"
3221 " gl_Position = inputAttribute;\n"
3222 " varStruct.field = vec4(0.0, 1.0, 0.0, 1.0);\n"
3223 "}\n";
3224
3225 const std::string &fragmentShader =
3226 "#version 300 es\n"
3227 "precision mediump float;\n"
3228 "out vec4 col;\n"
3229 "struct S {\n"
3230 " vec4 field;\n"
3231 "};\n"
3232 "in S varStruct;\n"
3233 "void main()\n"
3234 "{\n"
3235 " col = varStruct.field;\n"
3236 "}\n";
3237
3238 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3239 drawQuad(program.get(), "inputAttribute", 0.5f);
3240 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3241}
3242
Olli Etuaho3860b6c2017-07-19 16:17:24 +03003243// This test covers passing an array of structs containing samplers as a function argument.
3244TEST_P(GLSLTest, ArrayOfStructsWithSamplersAsFunctionArg)
3245{
3246 if (IsAndroid() && IsAdreno() && IsOpenGLES())
3247 {
3248 // Shader failed to compile on Android. http://anglebug.com/2114
3249 std::cout << "Test skipped on Adreno OpenGLES on Android." << std::endl;
3250 return;
3251 }
3252
3253 const std::string &vertexShader =
3254 "attribute vec2 position;\n"
3255 "void main()\n"
3256 "{\n"
3257 " gl_Position = vec4(position, 0, 1);\n"
3258 "}\n";
3259
3260 const std::string &fragmentShader =
3261 "precision mediump float;\n"
3262 "struct S\n"
3263 "{\n"
3264 " sampler2D samplerMember; \n"
3265 "};\n"
3266 "uniform S uStructs[2];\n"
3267 "uniform vec2 uTexCoord;\n"
3268 "\n"
3269 "vec4 foo(S[2] structs)\n"
3270 "{\n"
3271 " return texture2D(structs[0].samplerMember, uTexCoord);\n"
3272 "}\n"
3273 "void main()\n"
3274 "{\n"
3275 " gl_FragColor = foo(uStructs);\n"
3276 "}\n";
3277
3278 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3279
3280 // Initialize the texture with green.
3281 GLTexture tex;
3282 glActiveTexture(GL_TEXTURE0);
3283 glBindTexture(GL_TEXTURE_2D, tex);
3284 GLubyte texData[] = {0u, 255u, 0u, 255u};
3285 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
3286 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3287 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3288 ASSERT_GL_NO_ERROR();
3289
3290 // Draw
3291 glUseProgram(program);
3292 GLint samplerMemberLoc = glGetUniformLocation(program, "uStructs[0].samplerMember");
3293 ASSERT_NE(-1, samplerMemberLoc);
3294 glUniform1i(samplerMemberLoc, 0);
3295 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
3296 ASSERT_NE(-1, texCoordLoc);
3297 glUniform2f(texCoordLoc, 0.5f, 0.5f);
3298
3299 drawQuad(program, "position", 0.5f);
3300 ASSERT_GL_NO_ERROR();
3301
3302 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
3303}
3304
Olli Etuaho28839f02017-08-15 11:38:16 +03003305// This test covers passing a struct containing an array of samplers as a function argument.
3306TEST_P(GLSLTest, StructWithSamplerArrayAsFunctionArg)
3307{
3308 if (IsAndroid() && IsAdreno() && IsOpenGLES())
3309 {
3310 // Shader failed to compile on Android. http://anglebug.com/2114
3311 std::cout << "Test skipped on Adreno OpenGLES on Android." << std::endl;
3312 return;
3313 }
3314
3315 const std::string &vertexShader =
3316 "attribute vec2 position;\n"
3317 "void main()\n"
3318 "{\n"
3319 " gl_Position = vec4(position, 0, 1);\n"
3320 "}\n";
3321
3322 const std::string &fragmentShader =
3323 "precision mediump float;\n"
3324 "struct S\n"
3325 "{\n"
3326 " sampler2D samplerMembers[2];\n"
3327 "};\n"
3328 "uniform S uStruct;\n"
3329 "uniform vec2 uTexCoord;\n"
3330 "\n"
3331 "vec4 foo(S str)\n"
3332 "{\n"
3333 " return texture2D(str.samplerMembers[0], uTexCoord);\n"
3334 "}\n"
3335 "void main()\n"
3336 "{\n"
3337 " gl_FragColor = foo(uStruct);\n"
3338 "}\n";
3339
3340 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3341
3342 // Initialize the texture with green.
3343 GLTexture tex;
3344 glActiveTexture(GL_TEXTURE0);
3345 glBindTexture(GL_TEXTURE_2D, tex);
3346 GLubyte texData[] = {0u, 255u, 0u, 255u};
3347 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
3348 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3349 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3350 ASSERT_GL_NO_ERROR();
3351
3352 // Draw
3353 glUseProgram(program);
3354 GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMembers[0]");
3355 ASSERT_NE(-1, samplerMemberLoc);
3356 glUniform1i(samplerMemberLoc, 0);
3357 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
3358 ASSERT_NE(-1, texCoordLoc);
3359 glUniform2f(texCoordLoc, 0.5f, 0.5f);
3360
3361 drawQuad(program, "position", 0.5f);
3362 ASSERT_GL_NO_ERROR();
3363
3364 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
3365}
3366
Olli Etuahoa16a84f2017-09-12 13:49:18 +03003367// Test that a global variable declared after main() works. This is a regression test for an issue
3368// in global variable initialization.
3369TEST_P(WebGLGLSLTest, GlobalVariableDeclaredAfterMain)
3370{
3371 const std::string &fragmentShader =
3372 "precision mediump float;\n"
3373 "int getFoo();\n"
3374 "uniform int u_zero;\n"
3375 "void main()\n"
3376 "{\n"
3377 " gl_FragColor = vec4(1, 0, 0, 1);\n"
3378 " if (getFoo() == 0)\n"
3379 " {\n"
3380 " gl_FragColor = vec4(0, 1, 0, 1);\n"
3381 " }\n"
3382 "}\n"
3383 "int foo;\n"
3384 "int getFoo()\n"
3385 "{\n"
3386 " foo = u_zero;\n"
3387 " return foo;\n"
3388 "}\n";
3389
3390 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3391 drawQuad(program.get(), "inputAttribute", 0.5f, 1.0f, true);
3392 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3393}
3394
Olli Etuahobb5a7e22017-08-30 13:03:12 +03003395// Test calling array length() with a "this" expression having side effects inside a loop condition.
3396// The spec says that sequence operator operands need to run in sequence.
3397TEST_P(GLSLTest_ES3, ArrayLengthOnExpressionWithSideEffectsInLoopCondition)
3398{
3399 // "a" gets doubled three times in the below program.
3400 const std::string &fragmentShader =
3401 R"(#version 300 es
3402 precision highp float;
3403 out vec4 my_FragColor;
3404 uniform int u_zero;
3405 int a;
3406 int[2] doubleA()
3407 {
3408 a *= 2;
3409 return int[2](a, a);
3410 }
3411 void main()
3412 {
3413 a = u_zero + 1;
3414 for (int i = 0; i < doubleA().length(); ++i)
3415 {}
3416 if (a == 8)
3417 {
3418 my_FragColor = vec4(0, 1, 0, 1);
3419 }
3420 else
3421 {
3422 my_FragColor = vec4(1, 0, 0, 1);
3423 }
3424 })";
3425
3426 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3427 drawQuad(program.get(), "inputAttribute", 0.5f);
3428 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3429}
3430
3431// Test calling array length() with a "this" expression having side effects that interact with side
3432// effects of another operand of the same sequence operator. The spec says that sequence operator
3433// operands need to run in order from left to right (ESSL 3.00.6 section 5.9).
3434TEST_P(GLSLTest_ES3, ArrayLengthOnExpressionWithSideEffectsInSequence)
3435{
3436 const std::string &fragmentShader =
3437 R"(#version 300 es
3438 precision highp float;
3439 out vec4 my_FragColor;
3440 uniform int u_zero;
3441 int a;
3442 int[3] doubleA()
3443 {
3444 a *= 2;
3445 return int[3](a, a, a);
3446 }
3447 void main()
3448 {
3449 a = u_zero;
3450 int b = (a++, doubleA().length());
3451 if (b == 3 && a == 2)
3452 {
3453 my_FragColor = vec4(0, 1, 0, 1);
3454 }
3455 else
3456 {
3457 my_FragColor = vec4(1, 0, 0, 1);
3458 }
3459 })";
3460
3461 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3462 drawQuad(program.get(), "inputAttribute", 0.5f);
3463 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3464}
3465
3466// Test calling array length() with a "this" expression that also contains a call of array length().
3467// Both "this" expressions also have side effects.
3468TEST_P(GLSLTest_ES3, NestedArrayLengthMethodsWithSideEffects)
3469{
3470 const std::string &fragmentShader =
3471 R"(#version 300 es
3472 precision highp float;
3473 out vec4 my_FragColor;
3474 uniform int u_zero;
3475 int a;
3476 int[3] multiplyA(int multiplier)
3477 {
3478 a *= multiplier;
3479 return int[3](a, a, a);
3480 }
3481 void main()
3482 {
3483 a = u_zero + 1;
3484 int b = multiplyA(multiplyA(2).length()).length();
3485 if (b == 3 && a == 6)
3486 {
3487 my_FragColor = vec4(0, 1, 0, 1);
3488 }
3489 else
3490 {
3491 my_FragColor = vec4(1, 0, 0, 1);
3492 }
3493 })";
3494
3495 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3496 drawQuad(program.get(), "inputAttribute", 0.5f);
3497 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3498}
3499
Olli Etuaho78507c62017-10-10 15:06:45 +03003500// Test that statements inside switch() get translated to correct HLSL.
3501TEST_P(GLSLTest_ES3, DifferentStatementsInsideSwitch)
3502{
3503 const std::string &fragmentShader =
3504 R"(#version 300 es
3505
3506 precision highp float;
3507
3508 uniform int u;
3509
3510 void main()
3511 {
3512 switch (u)
3513 {
3514 case 0:
3515 ivec2 i;
3516 i.yx;
3517 }
3518 })";
3519 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3520}
3521
Olli Etuaho852fe872017-10-10 15:13:59 +03003522// Test that switch fall-through works correctly.
3523// This is a regression test for http://anglebug.com/2178
3524TEST_P(GLSLTest_ES3, SwitchFallThroughCodeDuplication)
3525{
3526 const std::string &fragmentShader =
3527 R"(#version 300 es
3528
3529 precision highp float;
3530
3531 out vec4 my_FragColor;
3532
3533 uniform int u_zero;
3534
3535 void main()
3536 {
3537 int i = 0;
3538 // switch should fall through both cases.
3539 switch(u_zero)
3540 {
3541 case 0:
3542 i += 1;
3543 case 1:
3544 i += 2;
3545 }
3546 if (i == 3)
3547 {
3548 my_FragColor = vec4(0, 1, 0, 1);
3549 }
3550 else
3551 {
3552 my_FragColor = vec4(1, 0, 0, 1);
3553 }
3554 })";
3555
3556 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3557 drawQuad(program.get(), "inputAttribute", 0.5f);
3558 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3559}
3560
Olli Etuaho923ecef2017-10-11 12:01:38 +03003561// Test that a switch statement with an empty block inside as a final statement compiles.
3562TEST_P(GLSLTest_ES3, SwitchFinalCaseHasEmptyBlock)
3563{
3564 const std::string &fragmentShader =
3565 R"(#version 300 es
3566
3567 precision mediump float;
3568 uniform int i;
3569 void main()
3570 {
3571 switch (i)
3572 {
3573 case 0:
3574 break;
3575 default:
3576 {}
3577 }
3578 })";
3579 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3580}
3581
3582// Test that a switch statement with an empty declaration inside as a final statement compiles.
3583TEST_P(GLSLTest_ES3, SwitchFinalCaseHasEmptyDeclaration)
3584{
3585 const std::string &fragmentShader =
3586 R"(#version 300 es
3587
3588 precision mediump float;
3589 uniform int i;
3590 void main()
3591 {
3592 switch (i)
3593 {
3594 case 0:
3595 break;
3596 default:
3597 float;
3598 }
3599 })";
3600 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3601}
3602
Olli Etuaho4bd730c2017-10-10 14:14:19 +03003603// Test switch/case where break/return statements are within blocks.
3604TEST_P(GLSLTest_ES3, SwitchBreakOrReturnInsideBlocks)
3605{
3606 const std::string &fragmentShader =
3607 R"(#version 300 es
3608
3609 precision highp float;
3610
3611 uniform int u_zero;
3612 out vec4 my_FragColor;
3613
3614 bool test(int n)
3615 {
3616 switch(n) {
3617 case 0:
3618 {
3619 {
3620 break;
3621 }
3622 }
3623 case 1:
3624 {
3625 return true;
3626 }
3627 case 2:
3628 {
3629 n++;
3630 }
3631 }
3632 return false;
3633 }
3634
3635 void main()
3636 {
3637 my_FragColor = test(u_zero + 1) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
3638 })";
3639
3640 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3641 drawQuad(program.get(), "inputAttribute", 0.5f);
3642 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3643}
3644
Olli Etuahof6d242e2017-10-12 17:21:06 +03003645// Test switch/case where a variable is declared inside one of the cases and is accessed by a
3646// subsequent case.
3647TEST_P(GLSLTest_ES3, SwitchWithVariableDeclarationInside)
3648{
3649 const std::string &fragmentShader =
3650 R"(#version 300 es
3651
3652 precision highp float;
3653 out vec4 my_FragColor;
3654
3655 uniform int u_zero;
3656
3657 void main()
3658 {
3659 my_FragColor = vec4(1, 0, 0, 1);
3660 switch (u_zero)
3661 {
3662 case 0:
3663 ivec2 i;
3664 i = ivec2(1, 0);
3665 default:
3666 my_FragColor = vec4(0, i[0], 0, 1);
3667 }
3668 })";
3669
3670 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3671 drawQuad(program.get(), "inputAttribute", 0.5f);
3672 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3673}
3674
3675// Test nested switch/case where a variable is declared inside one of the cases and is accessed by a
3676// subsequent case.
3677TEST_P(GLSLTest_ES3, NestedSwitchWithVariableDeclarationInside)
3678{
3679 const std::string &fragmentShader =
3680 R"(#version 300 es
3681
3682 precision highp float;
3683 out vec4 my_FragColor;
3684
3685 uniform int u_zero;
3686 uniform int u_zero2;
3687
3688 void main()
3689 {
3690 my_FragColor = vec4(1, 0, 0, 1);
3691 switch (u_zero)
3692 {
3693 case 0:
3694 ivec2 i;
3695 i = ivec2(1, 0);
3696 switch (u_zero2)
3697 {
3698 case 0:
3699 int j;
3700 default:
3701 j = 1;
3702 i *= j;
3703 }
3704 default:
3705 my_FragColor = vec4(0, i[0], 0, 1);
3706 }
3707 })";
3708
3709 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3710 drawQuad(program.get(), "inputAttribute", 0.5f);
3711 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3712}
3713
Olli Etuahoc1f14fb2017-10-28 19:17:23 +03003714// Test that an empty switch/case statement is translated in a way that compiles and executes the
3715// init-statement.
3716TEST_P(GLSLTest_ES3, EmptySwitch)
3717{
3718 const std::string &fragmentShader =
3719 R"(#version 300 es
3720
3721 precision highp float;
3722
3723 uniform int u_zero;
3724 out vec4 my_FragColor;
3725
3726 void main()
3727 {
3728 int i = u_zero;
3729 switch(++i) {}
3730 my_FragColor = (i == 1) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
3731 })";
3732
3733 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3734 drawQuad(program.get(), "inputAttribute", 0.5f);
3735 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3736}
3737
Olli Etuahobd3cd502017-11-03 15:48:52 +02003738// Test that a constant struct inside an expression is handled correctly.
3739TEST_P(GLSLTest_ES3, ConstStructInsideExpression)
3740{
3741 // Incorrect output color was seen on Android. http://anglebug.com/2226
3742 ANGLE_SKIP_TEST_IF(IsAndroid() && !IsNVIDIA() && IsOpenGLES());
3743
3744 const std::string &fragmentShader =
3745 R"(#version 300 es
3746
3747 precision highp float;
3748 out vec4 my_FragColor;
3749
3750 uniform float u_zero;
3751
3752 struct S
3753 {
3754 float field;
3755 };
3756
3757 void main()
3758 {
3759 const S constS = S(1.0);
3760 S nonConstS = constS;
3761 nonConstS.field = u_zero;
3762 bool fail = (constS == nonConstS);
3763 my_FragColor = vec4(0, 1, 0, 1);
3764 if (fail)
3765 {
3766 my_FragColor = vec4(1, 0, 0, 1);
3767 }
3768 })";
3769
3770 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3771 drawQuad(program.get(), "inputAttribute", 0.5f);
3772 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3773}
3774
3775// Test that a varying struct that's defined as a part of the declaration is handled correctly.
3776TEST_P(GLSLTest_ES3, VaryingStructWithInlineDefinition)
3777{
3778 const std::string &vertexShader =
3779 R"(#version 300 es
3780 in vec4 inputAttribute;
3781
3782 flat out struct S
3783 {
3784 int field;
3785 } v_s;
3786
3787 void main()
3788 {
3789 v_s.field = 1;
3790 gl_Position = inputAttribute;
3791 })";
3792
3793 const std::string &fragmentShader =
3794 R"(#version 300 es
3795
3796 precision highp float;
3797 out vec4 my_FragColor;
3798
3799 flat in struct S
3800 {
3801 int field;
3802 } v_s;
3803
3804 void main()
3805 {
3806 bool success = (v_s.field == 1);
3807 my_FragColor = vec4(1, 0, 0, 1);
3808 if (success)
3809 {
3810 my_FragColor = vec4(0, 1, 0, 1);
3811 }
3812 })";
3813
3814 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3815 drawQuad(program.get(), "inputAttribute", 0.5f);
3816 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3817}
3818
Olli Etuaho661fc482017-10-16 12:17:05 +03003819// Test vector/scalar arithmetic (in this case multiplication and addition). Meant to reproduce a
3820// bug that appeared in NVIDIA OpenGL drivers and that is worked around by
3821// VectorizeVectorScalarArithmetic AST transform.
3822TEST_P(GLSLTest, VectorScalarMultiplyAndAddInLoop)
3823{
3824 const std::string &fragmentShader =
3825 R"(
3826
3827 precision mediump float;
3828
3829 void main() {
3830 gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
3831 for (int i = 0; i < 2; i++)
3832 {
3833 gl_FragColor += (2.0 * gl_FragCoord.x);
3834 }
3835 if (gl_FragColor.g == gl_FragColor.r &&
3836 gl_FragColor.b == gl_FragColor.r &&
3837 gl_FragColor.a == gl_FragColor.r)
3838 {
3839 gl_FragColor = vec4(0, 1, 0, 1);
3840 }
3841 })";
3842
3843 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3844 drawQuad(program.get(), "inputAttribute", 0.5f);
3845 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3846}
3847
3848// Test vector/scalar arithmetic (in this case compound division and addition). Meant to reproduce a
3849// bug that appeared in NVIDIA OpenGL drivers and that is worked around by
3850// VectorizeVectorScalarArithmetic AST transform.
3851TEST_P(GLSLTest, VectorScalarDivideAndAddInLoop)
3852{
3853 const std::string &fragmentShader =
3854 R"(
3855
3856 precision mediump float;
3857
3858 void main() {
3859 gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
3860 for (int i = 0; i < 2; i++)
3861 {
3862 float x = gl_FragCoord.x;
3863 gl_FragColor = gl_FragColor + (x /= 2.0);
3864 }
3865 if (gl_FragColor.g == gl_FragColor.r &&
3866 gl_FragColor.b == gl_FragColor.r &&
3867 gl_FragColor.a == gl_FragColor.r)
3868 {
3869 gl_FragColor = vec4(0, 1, 0, 1);
3870 }
3871 })";
3872
3873 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3874 drawQuad(program.get(), "inputAttribute", 0.5f);
3875 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3876}
3877
Jamie Madillfa05f602015-05-07 13:47:11 -04003878// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
Geoff Lange0cc2a42016-01-20 10:58:17 -05003879ANGLE_INSTANTIATE_TEST(GLSLTest,
3880 ES2_D3D9(),
3881 ES2_D3D11(),
3882 ES2_D3D11_FL9_3(),
3883 ES2_OPENGL(),
3884 ES3_OPENGL(),
3885 ES2_OPENGLES(),
3886 ES3_OPENGLES());
Jamie Madillfa05f602015-05-07 13:47:11 -04003887
3888// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
Geoff Lange0cc2a42016-01-20 10:58:17 -05003889ANGLE_INSTANTIATE_TEST(GLSLTest_ES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
Jamie Madill192745a2016-12-22 15:58:21 -05003890
3891ANGLE_INSTANTIATE_TEST(WebGLGLSLTest, ES2_D3D11(), ES2_OPENGL(), ES2_OPENGLES());
Olli Etuaho9250cb22017-01-21 10:51:27 +00003892
3893ANGLE_INSTANTIATE_TEST(GLSLTest_ES31, ES31_D3D11(), ES31_OPENGL(), ES31_OPENGLES());