blob: c736579f08253a61b9e1af7944b6a0bc6f76b005 [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
Jiawei Shao02f15232017-12-27 10:10:28 +0800434 std::string QueryErrorMessage(GLuint program)
435 {
436 GLint infoLogLength;
437 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);
438 EXPECT_GL_NO_ERROR();
439
440 if (infoLogLength >= 1)
441 {
442 std::vector<GLchar> infoLog(infoLogLength);
443 glGetProgramInfoLog(program, static_cast<GLsizei>(infoLog.size()), nullptr,
444 infoLog.data());
445 EXPECT_GL_NO_ERROR();
446 return infoLog.data();
447 }
448
449 return "";
450 }
451
Jiawei Shao881b7bf2017-12-25 11:18:37 +0800452 void validateComponentsInErrorMessage(const std::string &vertexShader,
453 const std::string &fragmentShader,
454 const std::string &expectedErrorType,
455 const std::string &expectedVariableFullName)
456 {
457 GLuint vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
458 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);
459
460 GLuint program = glCreateProgram();
461 glAttachShader(program, vs);
462 glAttachShader(program, fs);
463 glLinkProgram(program);
464
465 glDetachShader(program, vs);
466 glDetachShader(program, fs);
467 glDeleteShader(vs);
468 glDeleteShader(fs);
469
470 const std::string &errorMessage = QueryErrorMessage(program);
471
472 EXPECT_NE(std::string::npos, errorMessage.find(expectedErrorType));
473 EXPECT_NE(std::string::npos, errorMessage.find(expectedVariableFullName));
474
475 glDeleteProgram(program);
476 ASSERT_GL_NO_ERROR();
477 }
478
Jamie Madill2bf8b372014-06-16 17:18:51 -0400479 std::string mSimpleVSSource;
Jamie Madill96509e42014-05-29 14:33:27 -0400480};
481
Jamie Madille1faacb2016-12-13 12:42:14 -0500482class GLSLTestNoValidation : public GLSLTest
483{
484 public:
485 GLSLTestNoValidation() { setNoErrorEnabled(true); }
486};
487
Jamie Madillfa05f602015-05-07 13:47:11 -0400488class GLSLTest_ES3 : public GLSLTest
Gregoire Payen de La Garanderieb3dced22015-01-12 14:54:55 +0000489{
Olli Etuahoe1d199b2016-07-19 17:14:27 +0300490 void SetUp() override
491 {
492 ANGLETest::SetUp();
493
494 mSimpleVSSource =
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300495 R"(#version 300 es
496 in vec4 inputAttribute;
497 void main()
498 {
499 gl_Position = inputAttribute;
500 })";
Olli Etuahoe1d199b2016-07-19 17:14:27 +0300501 }
Gregoire Payen de La Garanderieb3dced22015-01-12 14:54:55 +0000502};
503
Olli Etuaho9250cb22017-01-21 10:51:27 +0000504class GLSLTest_ES31 : public GLSLTest
505{
506 void SetUp() override
507 {
508 ANGLETest::SetUp();
509
510 mSimpleVSSource =
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300511 R"(#version 310 es
512 in vec4 inputAttribute;
513 void main()
514 {
515 gl_Position = inputAttribute;
516 })";
Olli Etuaho9250cb22017-01-21 10:51:27 +0000517 }
518};
519
Jamie Madillfa05f602015-05-07 13:47:11 -0400520TEST_P(GLSLTest, NamelessScopedStructs)
Jamie Madill96509e42014-05-29 14:33:27 -0400521{
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300522 const std::string fragmentShaderSource =
523 R"(precision mediump float;
Jamie Madill96509e42014-05-29 14:33:27 -0400524 void main()
525 {
Jamie Madillbfa91f42014-06-05 15:45:18 -0400526 struct
527 {
528 float q;
529 } b;
530
531 gl_FragColor = vec4(1, 0, 0, 1);
532 gl_FragColor.a += b.q;
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300533 })";
Jamie Madill96509e42014-05-29 14:33:27 -0400534
Jamie Madill5599c8f2014-08-26 13:16:39 -0400535 GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
Jamie Madillbfa91f42014-06-05 15:45:18 -0400536 EXPECT_NE(0u, program);
537}
Austin Kinross18b931d2014-09-29 12:58:31 -0700538
Jamie Madillfa05f602015-05-07 13:47:11 -0400539TEST_P(GLSLTest, ScopedStructsOrderBug)
Jamie Madillbfa91f42014-06-05 15:45:18 -0400540{
Geoff Lange0cc2a42016-01-20 10:58:17 -0500541 // TODO(geofflang): Find out why this doesn't compile on Apple OpenGL drivers
542 // (http://anglebug.com/1292)
Geoff Lang5103f4c2016-01-26 11:40:18 -0500543 // TODO(geofflang): Find out why this doesn't compile on AMD OpenGL drivers
Geoff Lange0cc2a42016-01-20 10:58:17 -0500544 // (http://anglebug.com/1291)
Corentin Wallezc7f59d02016-06-20 10:12:08 -0400545 if (IsDesktopOpenGL() && (IsOSX() || !IsNVIDIA()))
Geoff Lange0cc2a42016-01-20 10:58:17 -0500546 {
Jamie Madill518b9fa2016-03-02 11:26:02 -0500547 std::cout << "Test disabled on this OpenGL configuration." << std::endl;
Geoff Lange0cc2a42016-01-20 10:58:17 -0500548 return;
549 }
Geoff Lange0cc2a42016-01-20 10:58:17 -0500550
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300551 const std::string fragmentShaderSource =
552 R"(precision mediump float;
Jamie Madillbfa91f42014-06-05 15:45:18 -0400553
554 struct T
555 {
556 float f;
557 };
558
559 void main()
560 {
561 T a;
562
563 struct T
564 {
565 float q;
566 };
567
568 T b;
569
570 gl_FragColor = vec4(1, 0, 0, 1);
571 gl_FragColor.a += a.f;
572 gl_FragColor.a += b.q;
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300573 })";
Jamie Madillbfa91f42014-06-05 15:45:18 -0400574
Jamie Madill5599c8f2014-08-26 13:16:39 -0400575 GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
Jamie Madillbfa91f42014-06-05 15:45:18 -0400576 EXPECT_NE(0u, program);
577}
578
Jamie Madillfa05f602015-05-07 13:47:11 -0400579TEST_P(GLSLTest, ScopedStructsBug)
Jamie Madillbfa91f42014-06-05 15:45:18 -0400580{
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300581 const std::string fragmentShaderSource =
582 R"(precision mediump float;
Jamie Madill96509e42014-05-29 14:33:27 -0400583
584 struct T_0
585 {
586 float f;
587 };
588
589 void main()
590 {
591 gl_FragColor = vec4(1, 0, 0, 1);
592
593 struct T
594 {
595 vec2 v;
596 };
597
598 T_0 a;
599 T b;
600
601 gl_FragColor.a += a.f;
602 gl_FragColor.a += b.v.x;
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300603 })";
Jamie Madill96509e42014-05-29 14:33:27 -0400604
Jamie Madill5599c8f2014-08-26 13:16:39 -0400605 GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
Jamie Madill2bf8b372014-06-16 17:18:51 -0400606 EXPECT_NE(0u, program);
607}
608
Jamie Madillfa05f602015-05-07 13:47:11 -0400609TEST_P(GLSLTest, DxPositionBug)
Jamie Madill2bf8b372014-06-16 17:18:51 -0400610{
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300611 const std::string &vertexShaderSource =
612 R"(attribute vec4 inputAttribute;
Jamie Madill2bf8b372014-06-16 17:18:51 -0400613 varying float dx_Position;
614 void main()
615 {
616 gl_Position = vec4(inputAttribute);
617 dx_Position = 0.0;
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300618 })";
Jamie Madill2bf8b372014-06-16 17:18:51 -0400619
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300620 const std::string &fragmentShaderSource =
621 R"(precision mediump float;
Jamie Madill2bf8b372014-06-16 17:18:51 -0400622
623 varying float dx_Position;
624
625 void main()
626 {
627 gl_FragColor = vec4(dx_Position, 0, 0, 1);
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300628 })";
Jamie Madill2bf8b372014-06-16 17:18:51 -0400629
Jamie Madill5599c8f2014-08-26 13:16:39 -0400630 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
Jamie Madill96509e42014-05-29 14:33:27 -0400631 EXPECT_NE(0u, program);
632}
Jamie Madill4836d222014-07-24 06:55:51 -0400633
Jamie Madillfa05f602015-05-07 13:47:11 -0400634TEST_P(GLSLTest, ElseIfRewriting)
Jamie Madill4836d222014-07-24 06:55:51 -0400635{
636 const std::string &vertexShaderSource =
637 "attribute vec4 a_position;\n"
638 "varying float v;\n"
639 "void main() {\n"
640 " gl_Position = a_position;\n"
641 " v = 1.0;\n"
642 " if (a_position.x <= 0.5) {\n"
643 " v = 0.0;\n"
644 " } else if (a_position.x >= 0.5) {\n"
645 " v = 2.0;\n"
646 " }\n"
647 "}\n";
648
649 const std::string &fragmentShaderSource =
650 "precision highp float;\n"
651 "varying float v;\n"
652 "void main() {\n"
653 " vec4 color = vec4(1.0, 0.0, 0.0, 1.0);\n"
654 " if (v >= 1.0) color = vec4(0.0, 1.0, 0.0, 1.0);\n"
655 " if (v >= 2.0) color = vec4(0.0, 0.0, 1.0, 1.0);\n"
656 " gl_FragColor = color;\n"
657 "}\n";
658
Jamie Madill5599c8f2014-08-26 13:16:39 -0400659 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
Jamie Madill4836d222014-07-24 06:55:51 -0400660 ASSERT_NE(0u, program);
661
662 drawQuad(program, "a_position", 0.5f);
Jamie Madill4836d222014-07-24 06:55:51 -0400663
664 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
665 EXPECT_PIXEL_EQ(getWindowWidth()-1, 0, 0, 255, 0, 255);
666}
667
Jamie Madillfa05f602015-05-07 13:47:11 -0400668TEST_P(GLSLTest, TwoElseIfRewriting)
Jamie Madill4836d222014-07-24 06:55:51 -0400669{
670 const std::string &vertexShaderSource =
671 "attribute vec4 a_position;\n"
672 "varying float v;\n"
673 "void main() {\n"
674 " gl_Position = a_position;\n"
Jamie Madill778d5272014-08-04 13:13:25 -0400675 " if (a_position.x == 0.0) {\n"
Jamie Madill4836d222014-07-24 06:55:51 -0400676 " v = 1.0;\n"
677 " } else if (a_position.x > 0.5) {\n"
678 " v = 0.0;\n"
679 " } else if (a_position.x > 0.75) {\n"
680 " v = 0.5;\n"
681 " }\n"
682 "}\n";
683
684 const std::string &fragmentShaderSource =
685 "precision highp float;\n"
686 "varying float v;\n"
687 "void main() {\n"
688 " gl_FragColor = vec4(v, 0.0, 0.0, 1.0);\n"
689 "}\n";
690
Jamie Madill5599c8f2014-08-26 13:16:39 -0400691 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
Jamie Madill4836d222014-07-24 06:55:51 -0400692 EXPECT_NE(0u, program);
693}
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400694
Jamie Madillfa05f602015-05-07 13:47:11 -0400695TEST_P(GLSLTest, FrontFacingAndVarying)
Jamie Madille6256f82014-09-17 10:31:15 -0400696{
Geoff Langdd323e92015-06-09 15:16:31 -0400697 EGLPlatformParameters platform = GetParam().eglParameters;
Austin Kinross8b695ee2015-03-12 13:12:20 -0700698
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300699 const std::string vertexShaderSource =
700 R"(attribute vec4 a_position;
Jamie Madille6256f82014-09-17 10:31:15 -0400701 varying float v_varying;
702 void main()
703 {
704 v_varying = a_position.x;
705 gl_Position = a_position;
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300706 })";
Jamie Madille6256f82014-09-17 10:31:15 -0400707
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300708 const std::string fragmentShaderSource =
709 R"(precision mediump float;
Jamie Madille6256f82014-09-17 10:31:15 -0400710 varying float v_varying;
711 void main()
712 {
713 vec4 c;
714
715 if (gl_FrontFacing)
716 {
717 c = vec4(v_varying, 0, 0, 1.0);
718 }
719 else
720 {
721 c = vec4(0, v_varying, 0, 1.0);
722 }
723 gl_FragColor = c;
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300724 })";
Jamie Madille6256f82014-09-17 10:31:15 -0400725
726 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
Austin Kinross02df7962015-07-01 10:03:42 -0700727
728 // Compilation should fail on D3D11 feature level 9_3, since gl_FrontFacing isn't supported.
729 if (platform.renderer == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
730 {
731 if (platform.majorVersion == 9 && platform.minorVersion == 3)
732 {
733 EXPECT_EQ(0u, program);
734 return;
735 }
736 }
737
738 // Otherwise, compilation should succeed
Jamie Madille6256f82014-09-17 10:31:15 -0400739 EXPECT_NE(0u, program);
740}
741
Jamie Madill2f348d22017-06-05 10:50:59 -0400742// Test that we can release the shader compiler and still compile things properly.
743TEST_P(GLSLTest, ReleaseCompilerThenCompile)
744{
745 const std::string &simpleVS =
746 "attribute vec4 position; void main() { gl_Position = position; }";
747 const std::string &simpleFS = "void main() { gl_FragColor = vec4(1, 0, 0, 1); }";
748
749 // Draw with the first program.
750 ANGLE_GL_PROGRAM(program1, simpleVS, simpleFS);
751 drawQuad(program1, "position", 0.5f);
752 ASSERT_GL_NO_ERROR();
753 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
754
755 // Clear and release shader compiler.
756 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
757 glClear(GL_COLOR_BUFFER_BIT);
758 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
759 glReleaseShaderCompiler();
760 ASSERT_GL_NO_ERROR();
761
762 // Draw with a second program.
763 ANGLE_GL_PROGRAM(program2, simpleVS, simpleFS);
764 drawQuad(program2, "position", 0.5f);
765 ASSERT_GL_NO_ERROR();
766 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
767}
768
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400769// Verify that linking shaders declaring different shading language versions fails.
770TEST_P(GLSLTest_ES3, VersionMismatch)
771{
772 const std::string fragmentShaderSource100 =
773 "precision mediump float;\n"
774 "varying float v_varying;\n"
775 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
776
777 const std::string vertexShaderSource100 =
778 "attribute vec4 a_position;\n"
779 "varying float v_varying;\n"
780 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
781
782 const std::string fragmentShaderSource300 =
783 "#version 300 es\n"
784 "precision mediump float;\n"
785 "in float v_varying;\n"
786 "out vec4 my_FragColor;\n"
787 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
788
789 const std::string vertexShaderSource300 =
790 "#version 300 es\n"
791 "in vec4 a_position;\n"
792 "out float v_varying;\n"
793 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
794
795 GLuint program = CompileProgram(vertexShaderSource300, fragmentShaderSource100);
796 EXPECT_EQ(0u, program);
797
798 program = CompileProgram(vertexShaderSource100, fragmentShaderSource300);
799 EXPECT_EQ(0u, program);
800}
801
802// Verify that declaring varying as invariant only in vertex shader fails in ESSL 1.00.
803TEST_P(GLSLTest, InvariantVaryingOut)
804{
805 const std::string fragmentShaderSource =
806 "precision mediump float;\n"
807 "varying float v_varying;\n"
808 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
809
810 const std::string vertexShaderSource =
811 "attribute vec4 a_position;\n"
812 "invariant varying float v_varying;\n"
813 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
814
815 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
816 EXPECT_EQ(0u, program);
817}
818
819// Verify that declaring varying as invariant only in vertex shader succeeds in ESSL 3.00.
820TEST_P(GLSLTest_ES3, InvariantVaryingOut)
821{
822 // TODO: ESSL 3.00 -> GLSL 1.20 translation should add "invariant" in fragment shader
823 // for varyings which are invariant in vertex shader (http://anglebug.com/1293)
Corentin Wallezc7f59d02016-06-20 10:12:08 -0400824 if (IsDesktopOpenGL())
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400825 {
826 std::cout << "Test disabled on OpenGL." << std::endl;
827 return;
828 }
829
830 const std::string fragmentShaderSource =
831 "#version 300 es\n"
832 "precision mediump float;\n"
833 "in float v_varying;\n"
834 "out vec4 my_FragColor;\n"
835 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
836
837 const std::string vertexShaderSource =
838 "#version 300 es\n"
839 "in vec4 a_position;\n"
840 "invariant out float v_varying;\n"
841 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
842
843 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
844 EXPECT_NE(0u, program);
845}
846
847// Verify that declaring varying as invariant only in fragment shader fails in ESSL 1.00.
Jamie Madillfa05f602015-05-07 13:47:11 -0400848TEST_P(GLSLTest, InvariantVaryingIn)
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400849{
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400850 const std::string fragmentShaderSource =
851 "precision mediump float;\n"
852 "invariant varying float v_varying;\n"
853 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
Geoff Lange0cc2a42016-01-20 10:58:17 -0500854
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400855 const std::string vertexShaderSource =
856 "attribute vec4 a_position;\n"
857 "varying float v_varying;\n"
858 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400859
Jamie Madill5599c8f2014-08-26 13:16:39 -0400860 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400861 EXPECT_EQ(0u, program);
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400862}
863
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400864// Verify that declaring varying as invariant only in fragment shader fails in ESSL 3.00.
865TEST_P(GLSLTest_ES3, InvariantVaryingIn)
866{
867 const std::string fragmentShaderSource =
868 "#version 300 es\n"
869 "precision mediump float;\n"
870 "invariant in float v_varying;\n"
871 "out vec4 my_FragColor;\n"
872 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
873
874 const std::string vertexShaderSource =
875 "#version 300 es\n"
876 "in vec4 a_position;\n"
877 "out float v_varying;\n"
878 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
879
880 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
881 EXPECT_EQ(0u, program);
882}
883
884// Verify that declaring varying as invariant in both shaders succeeds in ESSL 1.00.
Jamie Madillfa05f602015-05-07 13:47:11 -0400885TEST_P(GLSLTest, InvariantVaryingBoth)
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400886{
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400887 const std::string fragmentShaderSource =
888 "precision mediump float;\n"
889 "invariant varying float v_varying;\n"
890 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400891
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400892 const std::string vertexShaderSource =
893 "attribute vec4 a_position;\n"
894 "invariant varying float v_varying;\n"
895 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400896
Jamie Madill5599c8f2014-08-26 13:16:39 -0400897 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400898 EXPECT_NE(0u, program);
899}
900
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400901// Verify that declaring varying as invariant in both shaders fails in ESSL 3.00.
902TEST_P(GLSLTest_ES3, InvariantVaryingBoth)
903{
904 const std::string fragmentShaderSource =
905 "#version 300 es\n"
906 "precision mediump float;\n"
907 "invariant in float v_varying;\n"
908 "out vec4 my_FragColor;\n"
909 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
910
911 const std::string vertexShaderSource =
912 "#version 300 es\n"
913 "in vec4 a_position;\n"
914 "invariant out float v_varying;\n"
915 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
916
917 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
918 EXPECT_EQ(0u, program);
919}
920
921// Verify that declaring gl_Position as invariant succeeds in ESSL 1.00.
Jamie Madillfa05f602015-05-07 13:47:11 -0400922TEST_P(GLSLTest, InvariantGLPosition)
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400923{
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400924 const std::string fragmentShaderSource =
925 "precision mediump float;\n"
926 "varying float v_varying;\n"
927 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400928
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400929 const std::string vertexShaderSource =
930 "attribute vec4 a_position;\n"
931 "invariant gl_Position;\n"
932 "varying float v_varying;\n"
933 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400934
Jamie Madill5599c8f2014-08-26 13:16:39 -0400935 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400936 EXPECT_NE(0u, program);
937}
938
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400939// Verify that declaring gl_Position as invariant succeeds in ESSL 3.00.
940TEST_P(GLSLTest_ES3, InvariantGLPosition)
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400941{
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400942 const std::string fragmentShaderSource =
943 "#version 300 es\n"
944 "precision mediump float;\n"
945 "in float v_varying;\n"
946 "out vec4 my_FragColor;\n"
947 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
948
949 const std::string vertexShaderSource =
950 "#version 300 es\n"
951 "in vec4 a_position;\n"
952 "invariant gl_Position;\n"
953 "out float v_varying;\n"
954 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
955
956 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
957 EXPECT_NE(0u, program);
958}
959
960// Verify that using invariant(all) in both shaders succeeds in ESSL 1.00.
961TEST_P(GLSLTest, InvariantAllBoth)
962{
963 // TODO: ESSL 1.00 -> GLSL 1.20 translation should add "invariant" in fragment shader
964 // for varyings which are invariant in vertex shader individually,
965 // and remove invariant(all) from fragment shader (http://anglebug.com/1293)
Corentin Wallezc7f59d02016-06-20 10:12:08 -0400966 if (IsDesktopOpenGL())
Geoff Lange0cc2a42016-01-20 10:58:17 -0500967 {
968 std::cout << "Test disabled on OpenGL." << std::endl;
969 return;
970 }
971
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400972 const std::string fragmentShaderSource =
973 "#pragma STDGL invariant(all)\n"
974 "precision mediump float;\n"
975 "varying float v_varying;\n"
976 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400977
978 const std::string vertexShaderSource =
979 "#pragma STDGL invariant(all)\n"
980 "attribute vec4 a_position;\n"
981 "varying float v_varying;\n"
982 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
983
Jamie Madill5599c8f2014-08-26 13:16:39 -0400984 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400985 EXPECT_NE(0u, program);
986}
Austin Kinrossaf875522014-08-25 21:06:07 -0700987
Geoff Lang156d7192016-07-21 16:11:00 -0400988// Verify that functions without return statements still compile
989TEST_P(GLSLTest, MissingReturnFloat)
990{
991 const std::string vertexShaderSource =
992 "varying float v_varying;\n"
993 "float f() { if (v_varying > 0.0) return 1.0; }\n"
994 "void main() { gl_Position = vec4(f(), 0, 0, 1); }\n";
995
996 const std::string fragmentShaderSource =
997 "precision mediump float;\n"
998 "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
999
1000 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1001 EXPECT_NE(0u, program);
1002}
1003
1004// Verify that functions without return statements still compile
1005TEST_P(GLSLTest, MissingReturnVec2)
1006{
1007 const std::string vertexShaderSource =
1008 "varying float v_varying;\n"
1009 "vec2 f() { if (v_varying > 0.0) return vec2(1.0, 1.0); }\n"
1010 "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
1011
1012 const std::string fragmentShaderSource =
1013 "precision mediump float;\n"
1014 "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
1015
1016 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1017 EXPECT_NE(0u, program);
1018}
1019
1020// Verify that functions without return statements still compile
1021TEST_P(GLSLTest, MissingReturnVec3)
1022{
1023 const std::string vertexShaderSource =
1024 "varying float v_varying;\n"
1025 "vec3 f() { if (v_varying > 0.0) return vec3(1.0, 1.0, 1.0); }\n"
1026 "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
1027
1028 const std::string fragmentShaderSource =
1029 "precision mediump float;\n"
1030 "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
1031
1032 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1033 EXPECT_NE(0u, program);
1034}
1035
1036// Verify that functions without return statements still compile
1037TEST_P(GLSLTest, MissingReturnVec4)
1038{
1039 const std::string vertexShaderSource =
1040 "varying float v_varying;\n"
1041 "vec4 f() { if (v_varying > 0.0) return vec4(1.0, 1.0, 1.0, 1.0); }\n"
1042 "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
1043
1044 const std::string fragmentShaderSource =
1045 "precision mediump float;\n"
1046 "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
1047
1048 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1049 EXPECT_NE(0u, program);
1050}
1051
1052// Verify that functions without return statements still compile
1053TEST_P(GLSLTest, MissingReturnIVec4)
1054{
1055 const std::string vertexShaderSource =
1056 "varying float v_varying;\n"
1057 "ivec4 f() { if (v_varying > 0.0) return ivec4(1, 1, 1, 1); }\n"
1058 "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
1059
1060 const std::string fragmentShaderSource =
1061 "precision mediump float;\n"
1062 "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
1063
1064 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1065 EXPECT_NE(0u, program);
1066}
1067
1068// Verify that functions without return statements still compile
1069TEST_P(GLSLTest, MissingReturnMat4)
1070{
1071 const std::string vertexShaderSource =
1072 "varying float v_varying;\n"
1073 "mat4 f() { if (v_varying > 0.0) return mat4(1.0); }\n"
1074 "void main() { gl_Position = vec4(f()[0][0], 0, 0, 1); }\n";
1075
1076 const std::string fragmentShaderSource =
1077 "precision mediump float;\n"
1078 "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
1079
1080 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1081 EXPECT_NE(0u, program);
1082}
1083
1084// Verify that functions without return statements still compile
1085TEST_P(GLSLTest, MissingReturnStruct)
1086{
1087 const std::string vertexShaderSource =
1088 "varying float v_varying;\n"
1089 "struct s { float a; int b; vec2 c; };\n"
1090 "s f() { if (v_varying > 0.0) return s(1.0, 1, vec2(1.0, 1.0)); }\n"
1091 "void main() { gl_Position = vec4(f().a, 0, 0, 1); }\n";
1092
1093 const std::string fragmentShaderSource =
1094 "precision mediump float;\n"
1095 "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
1096
1097 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1098 EXPECT_NE(0u, program);
1099}
1100
1101// Verify that functions without return statements still compile
1102TEST_P(GLSLTest_ES3, MissingReturnArray)
1103{
1104 const std::string vertexShaderSource =
1105 "#version 300 es\n"
1106 "in float v_varying;\n"
1107 "vec2[2] f() { if (v_varying > 0.0) { return vec2[2](vec2(1.0, 1.0), vec2(1.0, 1.0)); } }\n"
1108 "void main() { gl_Position = vec4(f()[0].x, 0, 0, 1); }\n";
1109
1110 const std::string fragmentShaderSource =
1111 "#version 300 es\n"
1112 "precision mediump float;\n"
1113 "out vec4 my_FragColor;\n"
1114 "void main() { my_FragColor = vec4(0, 0, 0, 1); }\n";
1115
1116 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1117 EXPECT_NE(0u, program);
1118}
1119
1120// Verify that functions without return statements still compile
1121TEST_P(GLSLTest_ES3, MissingReturnArrayOfStructs)
1122{
1123 const std::string vertexShaderSource =
1124 "#version 300 es\n"
1125 "in float v_varying;\n"
1126 "struct s { float a; int b; vec2 c; };\n"
1127 "s[2] f() { if (v_varying > 0.0) { return s[2](s(1.0, 1, vec2(1.0, 1.0)), s(1.0, 1, "
1128 "vec2(1.0, 1.0))); } }\n"
1129 "void main() { gl_Position = vec4(f()[0].a, 0, 0, 1); }\n";
1130
1131 const std::string fragmentShaderSource =
1132 "#version 300 es\n"
1133 "precision mediump float;\n"
1134 "out vec4 my_FragColor;\n"
1135 "void main() { my_FragColor = vec4(0, 0, 0, 1); }\n";
1136
1137 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1138 EXPECT_NE(0u, program);
1139}
1140
Corentin Wallez509e4562016-08-25 14:55:44 -04001141// Verify that functions without return statements still compile
1142TEST_P(GLSLTest_ES3, MissingReturnStructOfArrays)
1143{
Olli Etuahodf7d13e2017-05-30 13:53:45 +03001144 // TODO(cwallez) remove the suppression once NVIDIA drivers are updated across trybots, drivers
1145 // since late 2016 should have the fix. Last check on 2017-05-30 revealed that the Windows
1146 // Server 2008 bots still had the old, failing drivers.
Corentin Wallez509e4562016-08-25 14:55:44 -04001147 if (IsNVIDIA() && IsOpenGLES())
1148 {
1149 std::cout << "Test skipped on NVIDIA OpenGL ES because it disallows returning "
1150 "structure of arrays"
1151 << std::endl;
1152 return;
1153 }
1154
1155 const std::string vertexShaderSource =
1156 "#version 300 es\n"
1157 "in float v_varying;\n"
1158 "struct s { float a[2]; int b[2]; vec2 c[2]; };\n"
1159 "s f() { if (v_varying > 0.0) { return s(float[2](1.0, 1.0), int[2](1, 1),"
1160 "vec2[2](vec2(1.0, 1.0), vec2(1.0, 1.0))); } }\n"
1161 "void main() { gl_Position = vec4(f().a[0], 0, 0, 1); }\n";
1162
1163 const std::string fragmentShaderSource =
1164 "#version 300 es\n"
1165 "precision mediump float;\n"
1166 "out vec4 my_FragColor;\n"
1167 "void main() { my_FragColor = vec4(0, 0, 0, 1); }\n";
1168
1169 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1170 EXPECT_NE(0u, program);
1171}
1172
Yuly Novikova1f6dc92016-06-15 23:27:04 -04001173// Verify that using invariant(all) in both shaders fails in ESSL 3.00.
1174TEST_P(GLSLTest_ES3, InvariantAllBoth)
1175{
1176 const std::string fragmentShaderSource =
1177 "#version 300 es\n"
1178 "#pragma STDGL invariant(all)\n"
1179 "precision mediump float;\n"
1180 "in float v_varying;\n"
1181 "out vec4 my_FragColor;\n"
1182 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1183
1184 const std::string vertexShaderSource =
1185 "#version 300 es\n"
1186 "#pragma STDGL invariant(all)\n"
1187 "in vec4 a_position;\n"
1188 "out float v_varying;\n"
1189 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1190
1191 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1192 EXPECT_EQ(0u, program);
1193}
1194
1195// Verify that using invariant(all) only in fragment shader fails in ESSL 1.00.
1196TEST_P(GLSLTest, InvariantAllIn)
1197{
1198 const std::string fragmentShaderSource =
1199 "#pragma STDGL invariant(all)\n"
1200 "precision mediump float;\n"
1201 "varying float v_varying;\n"
1202 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1203
1204 const std::string vertexShaderSource =
1205 "attribute vec4 a_position;\n"
1206 "varying float v_varying;\n"
1207 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1208
1209 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1210 EXPECT_EQ(0u, program);
1211}
1212
1213// Verify that using invariant(all) only in fragment shader fails in ESSL 3.00.
1214TEST_P(GLSLTest_ES3, InvariantAllIn)
1215{
1216 const std::string fragmentShaderSource =
1217 "#version 300 es\n"
1218 "#pragma STDGL invariant(all)\n"
1219 "precision mediump float;\n"
1220 "in float v_varying;\n"
1221 "out vec4 my_FragColor;\n"
1222 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1223
1224 const std::string vertexShaderSource =
1225 "#version 300 es\n"
1226 "in vec4 a_position;\n"
1227 "out float v_varying;\n"
1228 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1229
1230 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1231 EXPECT_EQ(0u, program);
1232}
1233
1234// Verify that using invariant(all) only in vertex shader fails in ESSL 1.00.
1235TEST_P(GLSLTest, InvariantAllOut)
1236{
1237 const std::string fragmentShaderSource =
1238 "precision mediump float;\n"
1239 "varying float v_varying;\n"
1240 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1241
1242 const std::string vertexShaderSource =
1243 "#pragma STDGL invariant(all)\n"
1244 "attribute vec4 a_position;\n"
1245 "varying float v_varying;\n"
1246 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1247
1248 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1249 EXPECT_EQ(0u, program);
1250}
1251
1252// Verify that using invariant(all) only in vertex shader succeeds in ESSL 3.00.
1253TEST_P(GLSLTest_ES3, InvariantAllOut)
1254{
1255 // TODO: ESSL 3.00 -> GLSL 1.20 translation should add "invariant" in fragment shader
1256 // for varyings which are invariant in vertex shader,
1257 // because of invariant(all) being used in vertex shader (http://anglebug.com/1293)
Corentin Wallezc7f59d02016-06-20 10:12:08 -04001258 if (IsDesktopOpenGL())
Yuly Novikova1f6dc92016-06-15 23:27:04 -04001259 {
1260 std::cout << "Test disabled on OpenGL." << std::endl;
1261 return;
1262 }
1263
1264 const std::string fragmentShaderSource =
1265 "#version 300 es\n"
1266 "precision mediump float;\n"
1267 "in float v_varying;\n"
1268 "out vec4 my_FragColor;\n"
1269 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1270
1271 const std::string vertexShaderSource =
1272 "#version 300 es\n"
1273 "#pragma STDGL invariant(all)\n"
1274 "in vec4 a_position;\n"
1275 "out float v_varying;\n"
1276 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1277
1278 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1279 EXPECT_NE(0u, program);
1280}
1281
Jamie Madillfa05f602015-05-07 13:47:11 -04001282TEST_P(GLSLTest, MaxVaryingVec4)
Austin Kinross8b695ee2015-03-12 13:12:20 -07001283{
Geoff Lang69accbd2016-01-25 16:22:32 -05001284#if defined(__APPLE__)
1285 // TODO(geofflang): Find out why this doesn't compile on Apple AND OpenGL drivers
1286 // (http://anglebug.com/1291)
Jamie Madill518b9fa2016-03-02 11:26:02 -05001287 if (IsAMD() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
Geoff Lang69accbd2016-01-25 16:22:32 -05001288 {
1289 std::cout << "Test disabled on Apple AMD OpenGL." << std::endl;
1290 return;
1291 }
1292#endif
1293
Austin Kinross8b695ee2015-03-12 13:12:20 -07001294 GLint maxVaryings = 0;
1295 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1296
1297 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, false, false, false, true);
1298}
1299
Jamie Madill61d53252018-01-31 14:49:24 -05001300// Verify we can pack registers with one builtin varying.
1301TEST_P(GLSLTest, MaxVaryingVec4_OneBuiltin)
Austin Kinross8b695ee2015-03-12 13:12:20 -07001302{
1303 GLint maxVaryings = 0;
1304 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1305
Jamie Madill61d53252018-01-31 14:49:24 -05001306 // Generate shader code that uses gl_FragCoord.
1307 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 1, 0, true, false, false, true);
1308}
1309
1310// Verify we can pack registers with two builtin varyings.
1311TEST_P(GLSLTest, MaxVaryingVec4_TwoBuiltins)
1312{
1313 GLint maxVaryings = 0;
1314 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1315
1316 // Generate shader code that uses gl_FragCoord and gl_PointCoord.
Austin Kinross8b695ee2015-03-12 13:12:20 -07001317 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 2, 0, true, true, false, true);
1318}
1319
Jamie Madill61d53252018-01-31 14:49:24 -05001320// Verify we can pack registers with three builtin varyings.
1321TEST_P(GLSLTest, MaxVaryingVec4_ThreeBuiltins)
Austin Kinross8b695ee2015-03-12 13:12:20 -07001322{
1323 GLint maxVaryings = 0;
1324 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1325
1326 // Generate shader code that uses gl_FragCoord, gl_PointCoord and gl_PointSize.
Jamie Madill61d53252018-01-31 14:49:24 -05001327 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 3, 0, true, true, true, true);
1328}
1329
1330// This covers a problematic case in D3D9 - we are limited by the number of available semantics,
1331// rather than total register use.
1332TEST_P(GLSLTest, MaxVaryingsSpecialCases)
1333{
1334 ANGLE_SKIP_TEST_IF(!IsD3D9());
1335
1336 GLint maxVaryings = 0;
1337 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1338
1339 VaryingTestBase(maxVaryings, 0, 0, 0, 0, 0, 0, 0, true, false, false, false);
1340 VaryingTestBase(maxVaryings - 1, 0, 0, 0, 0, 0, 0, 0, true, true, false, false);
1341 VaryingTestBase(maxVaryings - 2, 0, 0, 0, 0, 0, 0, 0, true, true, false, true);
1342
1343 // Special case for gl_PointSize: we get it for free on D3D9.
1344 VaryingTestBase(maxVaryings - 2, 0, 0, 0, 0, 0, 0, 0, true, true, true, true);
1345}
1346
1347// This covers a problematic case in D3D9 - we are limited by the number of available semantics,
1348// rather than total register use.
1349TEST_P(GLSLTest, MaxMinusTwoVaryingVec2PlusOneSpecialVariable)
1350{
1351 GLint maxVaryings = 0;
1352 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1353
1354 // Generate shader code that uses gl_FragCoord.
1355 VaryingTestBase(0, 0, maxVaryings, 0, 0, 0, 0, 0, true, false, false, !IsD3D9());
Austin Kinross8b695ee2015-03-12 13:12:20 -07001356}
1357
Jamie Madillfa05f602015-05-07 13:47:11 -04001358TEST_P(GLSLTest, MaxVaryingVec3)
Austin Kinrossaf875522014-08-25 21:06:07 -07001359{
1360 GLint maxVaryings = 0;
1361 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1362
Austin Kinross8b695ee2015-03-12 13:12:20 -07001363 VaryingTestBase(0, 0, 0, 0, maxVaryings, 0, 0, 0, false, false, false, true);
Austin Kinrossaf875522014-08-25 21:06:07 -07001364}
1365
Jamie Madillfa05f602015-05-07 13:47:11 -04001366TEST_P(GLSLTest, MaxVaryingVec3Array)
Austin Kinrossaf875522014-08-25 21:06:07 -07001367{
1368 GLint maxVaryings = 0;
1369 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1370
Austin Kinross8b695ee2015-03-12 13:12:20 -07001371 VaryingTestBase(0, 0, 0, 0, 0, maxVaryings / 2, 0, 0, false, false, false, true);
Austin Kinrossaf875522014-08-25 21:06:07 -07001372}
1373
Jamie Madill61d53252018-01-31 14:49:24 -05001374// Only fails on D3D9 because of packing limitations.
Jamie Madill9fc36822015-11-18 13:08:07 -05001375TEST_P(GLSLTest, MaxVaryingVec3AndOneFloat)
Austin Kinrossaf875522014-08-25 21:06:07 -07001376{
1377 GLint maxVaryings = 0;
1378 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1379
Jamie Madill61d53252018-01-31 14:49:24 -05001380 VaryingTestBase(1, 0, 0, 0, maxVaryings, 0, 0, 0, false, false, false, !IsD3D9());
Austin Kinrossaf875522014-08-25 21:06:07 -07001381}
1382
Jamie Madill61d53252018-01-31 14:49:24 -05001383// Only fails on D3D9 because of packing limitations.
Jamie Madill9fc36822015-11-18 13:08:07 -05001384TEST_P(GLSLTest, MaxVaryingVec3ArrayAndOneFloatArray)
Austin Kinrossaf875522014-08-25 21:06:07 -07001385{
1386 GLint maxVaryings = 0;
1387 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1388
Jamie Madill61d53252018-01-31 14:49:24 -05001389 VaryingTestBase(0, 1, 0, 0, 0, maxVaryings / 2, 0, 0, false, false, false, !IsD3D9());
Austin Kinrossaf875522014-08-25 21:06:07 -07001390}
1391
Jamie Madill61d53252018-01-31 14:49:24 -05001392// Only fails on D3D9 because of packing limitations.
Jamie Madill9fc36822015-11-18 13:08:07 -05001393TEST_P(GLSLTest, TwiceMaxVaryingVec2)
Austin Kinrossaf875522014-08-25 21:06:07 -07001394{
Geoff Lange0cc2a42016-01-20 10:58:17 -05001395 if (getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
1396 {
1397 // TODO(geofflang): Figure out why this fails on NVIDIA's GLES driver
1398 std::cout << "Test disabled on OpenGL ES." << std::endl;
1399 return;
1400 }
1401
Geoff Lang69accbd2016-01-25 16:22:32 -05001402#if defined(__APPLE__)
1403 // TODO(geofflang): Find out why this doesn't compile on Apple AND OpenGL drivers
1404 // (http://anglebug.com/1291)
Jamie Madill518b9fa2016-03-02 11:26:02 -05001405 if (IsAMD() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
Geoff Lang69accbd2016-01-25 16:22:32 -05001406 {
1407 std::cout << "Test disabled on Apple AMD OpenGL." << std::endl;
1408 return;
1409 }
1410#endif
1411
Austin Kinrossaf875522014-08-25 21:06:07 -07001412 GLint maxVaryings = 0;
1413 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1414
Jamie Madill61d53252018-01-31 14:49:24 -05001415 VaryingTestBase(0, 0, 2 * maxVaryings, 0, 0, 0, 0, 0, false, false, false, !IsD3D9());
Austin Kinrossaf875522014-08-25 21:06:07 -07001416}
1417
Jamie Madillbee59e02014-10-02 10:44:18 -04001418// Disabled because of a failure in D3D9
Jamie Madill9fc36822015-11-18 13:08:07 -05001419TEST_P(GLSLTest, MaxVaryingVec2Arrays)
Austin Kinrossaf875522014-08-25 21:06:07 -07001420{
Jamie Madill518b9fa2016-03-02 11:26:02 -05001421 if (IsD3DSM3())
Jamie Madill9fc36822015-11-18 13:08:07 -05001422 {
1423 std::cout << "Test disabled on SM3." << std::endl;
1424 return;
1425 }
1426
Geoff Lange0cc2a42016-01-20 10:58:17 -05001427 if (getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
1428 {
1429 // TODO(geofflang): Figure out why this fails on NVIDIA's GLES driver
1430 std::cout << "Test disabled on OpenGL ES." << std::endl;
1431 return;
1432 }
1433
Geoff Lang69accbd2016-01-25 16:22:32 -05001434#if defined(__APPLE__)
1435 // TODO(geofflang): Find out why this doesn't compile on Apple AND OpenGL drivers
1436 // (http://anglebug.com/1291)
Jamie Madill518b9fa2016-03-02 11:26:02 -05001437 if (IsAMD() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
Geoff Lang69accbd2016-01-25 16:22:32 -05001438 {
1439 std::cout << "Test disabled on Apple AMD OpenGL." << std::endl;
1440 return;
1441 }
1442#endif
1443
Austin Kinrossaf875522014-08-25 21:06:07 -07001444 GLint maxVaryings = 0;
1445 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1446
Jamie Madill192745a2016-12-22 15:58:21 -05001447 // Special case: because arrays of mat2 are packed as small grids of two rows by two columns,
1448 // we should be aware that when we're packing into an odd number of varying registers the
1449 // last row will be empty and can not fit the final vec2 arrary.
1450 GLint maxVec2Arrays = (maxVaryings >> 1) << 1;
1451
1452 VaryingTestBase(0, 0, 0, maxVec2Arrays, 0, 0, 0, 0, false, false, false, true);
Austin Kinrossaf875522014-08-25 21:06:07 -07001453}
1454
Geoff Langf60fab62014-11-24 11:21:20 -05001455// Verify shader source with a fixed length that is less than the null-terminated length will compile.
Jamie Madillfa05f602015-05-07 13:47:11 -04001456TEST_P(GLSLTest, FixedShaderLength)
Geoff Langf60fab62014-11-24 11:21:20 -05001457{
1458 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1459
1460 const std::string appendGarbage = "abcasdfasdfasdfasdfasdf";
1461 const std::string source = "void main() { gl_FragColor = vec4(0, 0, 0, 0); }" + appendGarbage;
1462 const char *sourceArray[1] = { source.c_str() };
Corentin Wallez973402f2015-05-11 13:42:22 -04001463 GLint lengths[1] = { static_cast<GLint>(source.length() - appendGarbage.length()) };
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001464 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
Geoff Langf60fab62014-11-24 11:21:20 -05001465 glCompileShader(shader);
1466
1467 GLint compileResult;
1468 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1469 EXPECT_NE(compileResult, 0);
1470}
1471
1472// Verify that a negative shader source length is treated as a null-terminated length.
Jamie Madillfa05f602015-05-07 13:47:11 -04001473TEST_P(GLSLTest, NegativeShaderLength)
Geoff Langf60fab62014-11-24 11:21:20 -05001474{
1475 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1476
1477 const char *sourceArray[1] = { "void main() { gl_FragColor = vec4(0, 0, 0, 0); }" };
1478 GLint lengths[1] = { -10 };
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001479 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
Geoff Langf60fab62014-11-24 11:21:20 -05001480 glCompileShader(shader);
1481
1482 GLint compileResult;
1483 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1484 EXPECT_NE(compileResult, 0);
1485}
1486
Corentin Wallez9a9c0482016-04-12 10:36:25 -04001487// Check that having an invalid char after the "." doesn't cause an assert.
1488TEST_P(GLSLTest, InvalidFieldFirstChar)
1489{
1490 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
1491 const char *source = "void main() {vec4 x; x.}";
1492 glShaderSource(shader, 1, &source, 0);
1493 glCompileShader(shader);
1494
1495 GLint compileResult;
1496 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1497 EXPECT_EQ(0, compileResult);
1498}
1499
Geoff Langf60fab62014-11-24 11:21:20 -05001500// Verify that a length array with mixed positive and negative values compiles.
Jamie Madillfa05f602015-05-07 13:47:11 -04001501TEST_P(GLSLTest, MixedShaderLengths)
Geoff Langf60fab62014-11-24 11:21:20 -05001502{
1503 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1504
1505 const char *sourceArray[] =
1506 {
1507 "void main()",
1508 "{",
1509 " gl_FragColor = vec4(0, 0, 0, 0);",
1510 "}",
1511 };
1512 GLint lengths[] =
1513 {
1514 -10,
1515 1,
Corentin Wallez973402f2015-05-11 13:42:22 -04001516 static_cast<GLint>(strlen(sourceArray[2])),
Geoff Langf60fab62014-11-24 11:21:20 -05001517 -1,
1518 };
1519 ASSERT_EQ(ArraySize(sourceArray), ArraySize(lengths));
1520
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001521 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
Geoff Langf60fab62014-11-24 11:21:20 -05001522 glCompileShader(shader);
1523
1524 GLint compileResult;
1525 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1526 EXPECT_NE(compileResult, 0);
1527}
1528
1529// Verify that zero-length shader source does not affect shader compilation.
Jamie Madillfa05f602015-05-07 13:47:11 -04001530TEST_P(GLSLTest, ZeroShaderLength)
Geoff Langf60fab62014-11-24 11:21:20 -05001531{
1532 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1533
1534 const char *sourceArray[] =
1535 {
1536 "adfasdf",
1537 "34534",
1538 "void main() { gl_FragColor = vec4(0, 0, 0, 0); }",
1539 "",
1540 "asdfasdfsdsdf",
1541 };
1542 GLint lengths[] =
1543 {
1544 0,
1545 0,
1546 -1,
1547 0,
1548 0,
1549 };
1550 ASSERT_EQ(ArraySize(sourceArray), ArraySize(lengths));
1551
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001552 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
Geoff Langf60fab62014-11-24 11:21:20 -05001553 glCompileShader(shader);
1554
1555 GLint compileResult;
1556 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1557 EXPECT_NE(compileResult, 0);
1558}
Jamie Madill21c1e452014-12-29 11:33:41 -05001559
1560// Tests that bad index expressions don't crash ANGLE's translator.
1561// https://code.google.com/p/angleproject/issues/detail?id=857
Jamie Madillfa05f602015-05-07 13:47:11 -04001562TEST_P(GLSLTest, BadIndexBug)
Jamie Madill21c1e452014-12-29 11:33:41 -05001563{
1564 const std::string &fragmentShaderSourceVec =
1565 "precision mediump float;\n"
1566 "uniform vec4 uniformVec;\n"
1567 "void main()\n"
1568 "{\n"
1569 " gl_FragColor = vec4(uniformVec[int()]);\n"
1570 "}";
1571
1572 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, fragmentShaderSourceVec);
1573 EXPECT_EQ(0u, shader);
1574
1575 if (shader != 0)
1576 {
1577 glDeleteShader(shader);
1578 }
1579
1580 const std::string &fragmentShaderSourceMat =
1581 "precision mediump float;\n"
1582 "uniform mat4 uniformMat;\n"
1583 "void main()\n"
1584 "{\n"
1585 " gl_FragColor = vec4(uniformMat[int()]);\n"
1586 "}";
1587
1588 shader = CompileShader(GL_FRAGMENT_SHADER, fragmentShaderSourceMat);
1589 EXPECT_EQ(0u, shader);
1590
1591 if (shader != 0)
1592 {
1593 glDeleteShader(shader);
1594 }
1595
1596 const std::string &fragmentShaderSourceArray =
1597 "precision mediump float;\n"
1598 "uniform vec4 uniformArray;\n"
1599 "void main()\n"
1600 "{\n"
1601 " gl_FragColor = vec4(uniformArray[int()]);\n"
1602 "}";
1603
1604 shader = CompileShader(GL_FRAGMENT_SHADER, fragmentShaderSourceArray);
1605 EXPECT_EQ(0u, shader);
1606
1607 if (shader != 0)
1608 {
1609 glDeleteShader(shader);
1610 }
Jamie Madill37997142015-01-28 10:06:34 -05001611}
1612
Jamie Madill2e295e22015-04-29 10:41:33 -04001613// Test that structs defined in uniforms are translated correctly.
Jamie Madillfa05f602015-05-07 13:47:11 -04001614TEST_P(GLSLTest, StructSpecifiersUniforms)
Jamie Madill2e295e22015-04-29 10:41:33 -04001615{
Olli Etuahoa20af6d2017-09-18 13:32:29 +03001616 const std::string fragmentShaderSource =
1617 R"(precision mediump float;
Jamie Madill2e295e22015-04-29 10:41:33 -04001618
1619 uniform struct S { float field;} s;
1620
1621 void main()
1622 {
1623 gl_FragColor = vec4(1, 0, 0, 1);
1624 gl_FragColor.a += s.field;
Olli Etuahoa20af6d2017-09-18 13:32:29 +03001625 })";
Jamie Madill2e295e22015-04-29 10:41:33 -04001626
1627 GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
1628 EXPECT_NE(0u, program);
1629}
Jamie Madill55def582015-05-04 11:24:57 -04001630
1631// Test that gl_DepthRange is not stored as a uniform location. Since uniforms
1632// beginning with "gl_" are filtered out by our validation logic, we must
1633// bypass the validation to test the behaviour of the implementation.
1634// (note this test is still Impl-independent)
Jamie Madille1faacb2016-12-13 12:42:14 -05001635TEST_P(GLSLTestNoValidation, DepthRangeUniforms)
Jamie Madill55def582015-05-04 11:24:57 -04001636{
Olli Etuahoa20af6d2017-09-18 13:32:29 +03001637 const std::string fragmentShaderSource =
1638 R"(precision mediump float;
Jamie Madill55def582015-05-04 11:24:57 -04001639
1640 void main()
1641 {
1642 gl_FragColor = vec4(gl_DepthRange.near, gl_DepthRange.far, gl_DepthRange.diff, 1);
Olli Etuahoa20af6d2017-09-18 13:32:29 +03001643 })";
Jamie Madill55def582015-05-04 11:24:57 -04001644
Jamie Madille1faacb2016-12-13 12:42:14 -05001645 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShaderSource);
Jamie Madill55def582015-05-04 11:24:57 -04001646
Jamie Madille1faacb2016-12-13 12:42:14 -05001647 // We need to bypass validation for this call.
1648 GLint nearIndex = glGetUniformLocation(program.get(), "gl_DepthRange.near");
Jamie Madill55def582015-05-04 11:24:57 -04001649 EXPECT_EQ(-1, nearIndex);
1650
1651 // Test drawing does not throw an exception.
Jamie Madille1faacb2016-12-13 12:42:14 -05001652 drawQuad(program.get(), "inputAttribute", 0.5f);
Jamie Madill55def582015-05-04 11:24:57 -04001653
1654 EXPECT_GL_NO_ERROR();
Jamie Madill55def582015-05-04 11:24:57 -04001655}
Jamie Madill4052dfc2015-05-06 15:18:49 -04001656
Jamie Madill6c9503e2016-08-16 14:06:32 -04001657std::string GenerateSmallPowShader(double base, double exponent)
1658{
1659 std::stringstream stream;
1660
1661 stream.precision(8);
1662
1663 double result = pow(base, exponent);
1664
1665 stream << "precision highp float;\n"
1666 << "float fun(float arg)\n"
1667 << "{\n"
1668 << " return pow(arg, " << std::fixed << exponent << ");\n"
1669 << "}\n"
1670 << "\n"
1671 << "void main()\n"
1672 << "{\n"
1673 << " const float a = " << std::scientific << base << ";\n"
1674 << " float b = fun(a);\n"
1675 << " if (abs(" << result << " - b) < " << std::abs(result * 0.001) << ")\n"
1676 << " {\n"
1677 << " gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
1678 << " }\n"
1679 << " else\n"
1680 << " {\n"
1681 << " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
1682 << " }\n"
1683 << "}\n";
1684
1685 return stream.str();
1686}
1687
Jamie Madill4052dfc2015-05-06 15:18:49 -04001688// Covers the WebGL test 'glsl/bugs/pow-of-small-constant-in-user-defined-function'
Jamie Madill1048e432016-07-23 18:51:28 -04001689// See http://anglebug.com/851
1690TEST_P(GLSLTest, PowOfSmallConstant)
Jamie Madill4052dfc2015-05-06 15:18:49 -04001691{
Olli Etuaho629a6442017-12-11 10:55:43 +02001692 // Test with problematic exponents that are close to an integer.
1693 std::vector<double> testExponents;
1694 std::array<double, 5> epsilonMultipliers = {-100.0, -1.0, 0.0, 1.0, 100.0};
1695 for (double epsilonMultiplier : epsilonMultipliers)
Jamie Madill6c9503e2016-08-16 14:06:32 -04001696 {
1697 for (int i = -4; i <= 5; ++i)
Jamie Madill4052dfc2015-05-06 15:18:49 -04001698 {
Jamie Madill6c9503e2016-08-16 14:06:32 -04001699 if (i >= -1 && i <= 1)
1700 continue;
1701 const double epsilon = 1.0e-8;
Olli Etuaho629a6442017-12-11 10:55:43 +02001702 double bad = static_cast<double>(i) + epsilonMultiplier * epsilon;
1703 testExponents.push_back(bad);
Jamie Madill4052dfc2015-05-06 15:18:49 -04001704 }
Jamie Madill6c9503e2016-08-16 14:06:32 -04001705 }
Jamie Madill4052dfc2015-05-06 15:18:49 -04001706
Olli Etuaho629a6442017-12-11 10:55:43 +02001707 // Also test with a few exponents that are not close to an integer.
1708 testExponents.push_back(3.6);
1709 testExponents.push_back(3.4);
1710
1711 for (double testExponent : testExponents)
Jamie Madill6c9503e2016-08-16 14:06:32 -04001712 {
Olli Etuaho629a6442017-12-11 10:55:43 +02001713 const std::string &fragmentShaderSource = GenerateSmallPowShader(1.0e-6, testExponent);
Jamie Madill4052dfc2015-05-06 15:18:49 -04001714
Jamie Madill6c9503e2016-08-16 14:06:32 -04001715 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShaderSource);
Jamie Madill4052dfc2015-05-06 15:18:49 -04001716
Jamie Madill6c9503e2016-08-16 14:06:32 -04001717 drawQuad(program.get(), "inputAttribute", 0.5f);
1718
1719 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1720 EXPECT_GL_NO_ERROR();
1721 }
Jamie Madill4052dfc2015-05-06 15:18:49 -04001722}
Jamie Madillfa05f602015-05-07 13:47:11 -04001723
Cooper Partina5ef8d82015-08-19 14:52:21 -07001724// Test that fragment shaders which contain non-constant loop indexers and compiled for FL9_3 and
1725// below
1726// fail with a specific error message.
1727// Additionally test that the same fragment shader compiles successfully with feature levels greater
1728// than FL9_3.
1729TEST_P(GLSLTest, LoopIndexingValidation)
1730{
Olli Etuahoa20af6d2017-09-18 13:32:29 +03001731 const std::string fragmentShaderSource =
1732 R"(precision mediump float;
Cooper Partina5ef8d82015-08-19 14:52:21 -07001733
1734 uniform float loopMax;
1735
1736 void main()
1737 {
1738 gl_FragColor = vec4(1, 0, 0, 1);
1739 for (float l = 0.0; l < loopMax; l++)
1740 {
1741 if (loopMax > 3.0)
1742 {
1743 gl_FragColor.a += 0.1;
1744 }
1745 }
Olli Etuahoa20af6d2017-09-18 13:32:29 +03001746 })";
Cooper Partina5ef8d82015-08-19 14:52:21 -07001747
1748 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1749
1750 const char *sourceArray[1] = {fragmentShaderSource.c_str()};
1751 glShaderSource(shader, 1, sourceArray, nullptr);
1752 glCompileShader(shader);
1753
1754 GLint compileResult;
1755 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1756
1757 // If the test is configured to run limited to Feature Level 9_3, then it is
1758 // assumed that shader compilation will fail with an expected error message containing
1759 // "Loop index cannot be compared with non-constant expression"
Olli Etuaho814a54d2015-08-27 16:23:09 +03001760 if ((GetParam() == ES2_D3D11_FL9_3() || GetParam() == ES2_D3D9()))
Cooper Partina5ef8d82015-08-19 14:52:21 -07001761 {
1762 if (compileResult != 0)
1763 {
1764 FAIL() << "Shader compilation succeeded, expected failure";
1765 }
1766 else
1767 {
1768 GLint infoLogLength;
1769 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
1770
1771 std::string infoLog;
1772 infoLog.resize(infoLogLength);
Yunchao Hef81ce4a2017-04-24 10:49:17 +08001773 glGetShaderInfoLog(shader, static_cast<GLsizei>(infoLog.size()), nullptr, &infoLog[0]);
Cooper Partina5ef8d82015-08-19 14:52:21 -07001774
1775 if (infoLog.find("Loop index cannot be compared with non-constant expression") ==
1776 std::string::npos)
1777 {
1778 FAIL() << "Shader compilation failed with unexpected error message";
1779 }
1780 }
1781 }
1782 else
1783 {
1784 EXPECT_NE(0, compileResult);
1785 }
1786
1787 if (shader != 0)
1788 {
1789 glDeleteShader(shader);
1790 }
1791}
1792
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001793// Tests that the maximum uniforms count returned from querying GL_MAX_VERTEX_UNIFORM_VECTORS
1794// can actually be used.
1795TEST_P(GLSLTest, VerifyMaxVertexUniformVectors)
1796{
Zhenyao Mo1a256722017-01-12 11:52:57 -08001797 if (IsLinux() && IsIntel())
1798 {
1799 std::cout << "Test timed out on Linux Intel. See crbug.com/680631." << std::endl;
1800 return;
1801 }
1802
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001803 int maxUniforms = 10000;
1804 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
1805 EXPECT_GL_NO_ERROR();
1806 std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS = " << maxUniforms << std::endl;
1807
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001808 CompileGLSLWithUniformsAndSamplers(maxUniforms, 0, 0, 0, true);
1809}
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001810
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001811// Tests that the maximum uniforms count returned from querying GL_MAX_VERTEX_UNIFORM_VECTORS
1812// can actually be used along with the maximum number of texture samplers.
1813TEST_P(GLSLTest, VerifyMaxVertexUniformVectorsWithSamplers)
1814{
Geoff Lange0cc2a42016-01-20 10:58:17 -05001815 if (GetParam().eglParameters.renderer == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE ||
1816 GetParam().eglParameters.renderer == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
1817 {
1818 std::cout << "Test disabled on OpenGL." << std::endl;
1819 return;
1820 }
1821
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001822 int maxUniforms = 10000;
1823 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
1824 EXPECT_GL_NO_ERROR();
1825 std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS = " << maxUniforms << std::endl;
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001826
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001827 int maxTextureImageUnits = 0;
1828 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001829
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001830 CompileGLSLWithUniformsAndSamplers(maxUniforms, 0, maxTextureImageUnits, 0, true);
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001831}
1832
1833// Tests that the maximum uniforms count + 1 from querying GL_MAX_VERTEX_UNIFORM_VECTORS
1834// fails shader compilation.
1835TEST_P(GLSLTest, VerifyMaxVertexUniformVectorsExceeded)
1836{
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001837 int maxUniforms = 10000;
1838 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
1839 EXPECT_GL_NO_ERROR();
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001840 std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS + 1 = " << maxUniforms + 1 << std::endl;
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001841
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001842 CompileGLSLWithUniformsAndSamplers(maxUniforms + 1, 0, 0, 0, false);
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001843}
1844
1845// Tests that the maximum uniforms count returned from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
1846// can actually be used.
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001847TEST_P(GLSLTest, VerifyMaxFragmentUniformVectors)
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001848{
Zhenyao Mo1a256722017-01-12 11:52:57 -08001849 if (IsLinux() && IsIntel())
1850 {
1851 std::cout << "Test timed out on Linux Intel. See crbug.com/680631." << std::endl;
1852 return;
1853 }
1854
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001855 int maxUniforms = 10000;
1856 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
1857 EXPECT_GL_NO_ERROR();
1858 std::cout << "Validating GL_MAX_FRAGMENT_UNIFORM_VECTORS = " << maxUniforms << std::endl;
1859
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001860 CompileGLSLWithUniformsAndSamplers(0, maxUniforms, 0, 0, true);
1861}
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001862
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001863// Tests that the maximum uniforms count returned from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
1864// can actually be used along with the maximum number of texture samplers.
1865TEST_P(GLSLTest, VerifyMaxFragmentUniformVectorsWithSamplers)
1866{
Geoff Lange0cc2a42016-01-20 10:58:17 -05001867 if (GetParam().eglParameters.renderer == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE ||
1868 GetParam().eglParameters.renderer == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
1869 {
1870 std::cout << "Test disabled on OpenGL." << std::endl;
1871 return;
1872 }
1873
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001874 int maxUniforms = 10000;
1875 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
1876 EXPECT_GL_NO_ERROR();
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001877
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001878 int maxTextureImageUnits = 0;
1879 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001880
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001881 CompileGLSLWithUniformsAndSamplers(0, maxUniforms, 0, maxTextureImageUnits, true);
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001882}
1883
1884// Tests that the maximum uniforms count + 1 from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
1885// fails shader compilation.
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001886TEST_P(GLSLTest, VerifyMaxFragmentUniformVectorsExceeded)
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001887{
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001888 int maxUniforms = 10000;
1889 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
1890 EXPECT_GL_NO_ERROR();
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001891 std::cout << "Validating GL_MAX_FRAGMENT_UNIFORM_VECTORS + 1 = " << maxUniforms + 1
1892 << std::endl;
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001893
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001894 CompileGLSLWithUniformsAndSamplers(0, maxUniforms + 1, 0, 0, false);
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001895}
1896
Geoff Langba992ab2017-04-19 11:18:14 -04001897// Test compiling shaders using the GL_EXT_shader_texture_lod extension
1898TEST_P(GLSLTest, TextureLOD)
1899{
1900 if (!extensionEnabled("GL_EXT_shader_texture_lod"))
1901 {
1902 std::cout << "Test skipped due to missing GL_EXT_shader_texture_lod." << std::endl;
1903 return;
1904 }
1905
1906 const std::string source =
1907 "#extension GL_EXT_shader_texture_lod : require\n"
1908 "uniform sampler2D u_texture;\n"
1909 "void main() {\n"
1910 " gl_FragColor = texture2DGradEXT(u_texture, vec2(0.0, 0.0), vec2(0.0, 0.0), vec2(0.0, "
1911 "0.0));\n"
1912 "}\n";
1913
1914 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, source);
1915 ASSERT_NE(0u, shader);
1916 glDeleteShader(shader);
1917}
1918
Olli Etuahobe59c2f2016-03-07 11:32:34 +02001919// Test that two constructors which have vec4 and mat2 parameters get disambiguated (issue in
1920// HLSL).
1921TEST_P(GLSLTest_ES3, AmbiguousConstructorCall2x2)
1922{
1923 const std::string fragmentShaderSource =
1924 "#version 300 es\n"
1925 "precision highp float;\n"
1926 "out vec4 my_FragColor;\n"
1927 "void main()\n"
1928 "{\n"
1929 " my_FragColor = vec4(0.0);\n"
1930 "}";
1931
1932 const std::string vertexShaderSource =
1933 "#version 300 es\n"
1934 "precision highp float;\n"
1935 "in vec4 a_vec;\n"
1936 "in mat2 a_mat;\n"
1937 "void main()\n"
1938 "{\n"
1939 " gl_Position = vec4(a_vec) + vec4(a_mat);\n"
1940 "}";
1941
1942 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1943 EXPECT_NE(0u, program);
1944}
1945
1946// Test that two constructors which have mat2x3 and mat3x2 parameters get disambiguated.
1947// This was suspected to be an issue in HLSL, but HLSL seems to be able to natively choose between
1948// the function signatures in this case.
1949TEST_P(GLSLTest_ES3, AmbiguousConstructorCall2x3)
1950{
1951 const std::string fragmentShaderSource =
1952 "#version 300 es\n"
1953 "precision highp float;\n"
1954 "out vec4 my_FragColor;\n"
1955 "void main()\n"
1956 "{\n"
1957 " my_FragColor = vec4(0.0);\n"
1958 "}";
1959
1960 const std::string vertexShaderSource =
1961 "#version 300 es\n"
1962 "precision highp float;\n"
1963 "in mat3x2 a_matA;\n"
1964 "in mat2x3 a_matB;\n"
1965 "void main()\n"
1966 "{\n"
1967 " gl_Position = vec4(a_matA) + vec4(a_matB);\n"
1968 "}";
1969
1970 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1971 EXPECT_NE(0u, program);
1972}
1973
1974// Test that two functions which have vec4 and mat2 parameters get disambiguated (issue in HLSL).
1975TEST_P(GLSLTest_ES3, AmbiguousFunctionCall2x2)
1976{
1977 const std::string fragmentShaderSource =
1978 "#version 300 es\n"
1979 "precision highp float;\n"
1980 "out vec4 my_FragColor;\n"
1981 "void main()\n"
1982 "{\n"
1983 " my_FragColor = vec4(0.0);\n"
1984 "}";
1985
1986 const std::string vertexShaderSource =
1987 "#version 300 es\n"
1988 "precision highp float;\n"
1989 "in vec4 a_vec;\n"
1990 "in mat2 a_mat;\n"
1991 "vec4 foo(vec4 a)\n"
1992 "{\n"
1993 " return a;\n"
1994 "}\n"
1995 "vec4 foo(mat2 a)\n"
1996 "{\n"
1997 " return vec4(a[0][0]);\n"
1998 "}\n"
1999 "void main()\n"
2000 "{\n"
2001 " gl_Position = foo(a_vec) + foo(a_mat);\n"
2002 "}";
2003
2004 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
2005 EXPECT_NE(0u, program);
2006}
2007
2008// Test that an user-defined function with a large number of float4 parameters doesn't fail due to
2009// the function name being too long.
2010TEST_P(GLSLTest_ES3, LargeNumberOfFloat4Parameters)
2011{
2012 const std::string fragmentShaderSource =
2013 "#version 300 es\n"
2014 "precision highp float;\n"
2015 "out vec4 my_FragColor;\n"
2016 "void main()\n"
2017 "{\n"
2018 " my_FragColor = vec4(0.0);\n"
2019 "}";
2020
2021 std::stringstream vertexShaderStream;
2022 const unsigned int paramCount = 1024u;
2023
2024 vertexShaderStream << "#version 300 es\n"
2025 "precision highp float;\n"
2026 "in vec4 a_vec;\n"
2027 "vec4 lotsOfVec4Parameters(";
2028 for (unsigned int i = 0; i < paramCount; ++i)
2029 {
2030 vertexShaderStream << "vec4 a" << i << ", ";
2031 }
2032 vertexShaderStream << "vec4 aLast)\n"
2033 "{\n"
2034 " return ";
2035 for (unsigned int i = 0; i < paramCount; ++i)
2036 {
2037 vertexShaderStream << "a" << i << " + ";
2038 }
2039 vertexShaderStream << "aLast;\n"
2040 "}\n"
2041 "void main()\n"
2042 "{\n"
2043 " gl_Position = lotsOfVec4Parameters(";
2044 for (unsigned int i = 0; i < paramCount; ++i)
2045 {
2046 vertexShaderStream << "a_vec, ";
2047 }
2048 vertexShaderStream << "a_vec);\n"
2049 "}";
2050
2051 GLuint program = CompileProgram(vertexShaderStream.str(), fragmentShaderSource);
2052 EXPECT_NE(0u, program);
2053}
2054
Olli Etuahod4f4c112016-04-15 15:11:24 +03002055// This test was written specifically to stress DeferGlobalInitializers AST transformation.
2056// Test a shader where a global constant array is initialized with an expression containing array
2057// indexing. This initializer is tricky to constant fold, so if it's not constant folded it needs to
2058// be handled in a way that doesn't generate statements in the global scope in HLSL output.
2059// Also includes multiple array initializers in one declaration, where only the second one has
2060// array indexing. This makes sure that the qualifier for the declaration is set correctly if
2061// transformations are applied to the declaration also in the case of ESSL output.
2062TEST_P(GLSLTest_ES3, InitGlobalArrayWithArrayIndexing)
2063{
Yuly Novikov41db2242016-06-25 00:14:28 -04002064 // TODO(ynovikov): re-enable once root cause of http://anglebug.com/1428 is fixed
2065 if (IsAndroid() && IsAdreno() && IsOpenGLES())
2066 {
2067 std::cout << "Test skipped on Adreno OpenGLES on Android." << std::endl;
2068 return;
2069 }
2070
Olli Etuahod4f4c112016-04-15 15:11:24 +03002071 const std::string vertexShaderSource =
2072 "#version 300 es\n"
2073 "precision highp float;\n"
2074 "in vec4 a_vec;\n"
2075 "void main()\n"
2076 "{\n"
2077 " gl_Position = vec4(a_vec);\n"
2078 "}";
2079
2080 const std::string fragmentShaderSource =
2081 "#version 300 es\n"
2082 "precision highp float;\n"
2083 "out vec4 my_FragColor;\n"
2084 "const highp float f[2] = float[2](0.1, 0.2);\n"
2085 "const highp float[2] g = float[2](0.3, 0.4), h = float[2](0.5, f[1]);\n"
2086 "void main()\n"
2087 "{\n"
2088 " my_FragColor = vec4(h[1]);\n"
2089 "}";
2090
2091 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
2092 EXPECT_NE(0u, program);
2093}
2094
Corentin Wallez419bfc92016-06-28 10:54:45 -07002095// Test that index-constant sampler array indexing is supported.
2096TEST_P(GLSLTest, IndexConstantSamplerArrayIndexing)
2097{
2098 if (IsD3D11_FL93()) {
2099 std::cout << "Test skipped on D3D11 FL 9.3." << std::endl;
2100 return;
2101 }
2102
2103 const std::string vertexShaderSource =
2104 "attribute vec4 vPosition;\n"
2105 "void main()\n"
2106 "{\n"
2107 " gl_Position = vPosition;\n"
2108 "}";
2109
2110 const std::string fragmentShaderSource =
2111 "precision mediump float;\n"
2112 "uniform sampler2D uni[2];\n"
2113 "\n"
2114 "float zero(int x)\n"
2115 "{\n"
2116 " return float(x) - float(x);\n"
2117 "}\n"
2118 "\n"
2119 "void main()\n"
2120 "{\n"
2121 " vec4 c = vec4(0,0,0,0);\n"
2122 " for (int ii = 1; ii < 3; ++ii) {\n"
2123 " if (c.x > 255.0) {\n"
2124 " c.x = 255.0 + zero(ii);\n"
2125 " break;\n"
2126 " }\n"
2127 // Index the sampler array with a predictable loop index (index-constant) as opposed to
2128 // a true constant. This is valid in OpenGL ES but isn't in many Desktop OpenGL versions,
2129 // without an extension.
2130 " c += texture2D(uni[ii - 1], vec2(0.5, 0.5));\n"
2131 " }\n"
2132 " gl_FragColor = c;\n"
2133 "}";
2134
2135 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
2136 EXPECT_NE(0u, program);
2137}
2138
Corentin Wallezb00dcee2016-07-11 17:42:58 -04002139// Test that the #pragma directive is supported and doesn't trigger a compilation failure on the
2140// native driver. The only pragma that gets passed to the OpenGL driver is "invariant" but we don't
2141// want to test its behavior, so don't use any varyings.
2142TEST_P(GLSLTest, PragmaDirective)
2143{
2144 const std::string vertexShaderSource =
2145 "#pragma STDGL invariant(all)\n"
2146 "void main()\n"
2147 "{\n"
2148 " gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
2149 "}\n";
2150
2151 const std::string fragmentShaderSource =
2152 "precision mediump float;\n"
2153 "void main()\n"
2154 "{\n"
2155 " gl_FragColor = vec4(1.0);\n"
2156 "}\n";
2157
2158 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
2159 EXPECT_NE(0u, program);
2160}
2161
Olli Etuahoe1d199b2016-07-19 17:14:27 +03002162// Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
2163// The function call that returns the array needs to be evaluated after ++j for the expression to
2164// return the correct value (true).
2165TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderArray)
2166{
2167 const std::string &fragmentShaderSource =
2168 "#version 300 es\n"
2169 "precision mediump float;\n"
2170 "out vec4 my_FragColor; \n"
2171 "int[2] func(int param) {\n"
2172 " return int[2](param, param);\n"
2173 "}\n"
2174 "void main() {\n"
2175 " int a[2]; \n"
2176 " for (int i = 0; i < 2; ++i) {\n"
2177 " a[i] = 1;\n"
2178 " }\n"
2179 " int j = 0; \n"
2180 " bool result = ((++j), (a == func(j)));\n"
2181 " my_FragColor = vec4(0.0, (result ? 1.0 : 0.0), 0.0, 1.0);\n"
2182 "}\n";
2183
2184 GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
2185 ASSERT_NE(0u, program);
2186
2187 drawQuad(program, "inputAttribute", 0.5f);
2188
2189 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2190}
2191
2192// Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
2193// The short-circuiting expression needs to be evaluated after ++j for the expression to return the
2194// correct value (true).
2195TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderShortCircuit)
2196{
2197 const std::string &fragmentShaderSource =
2198 "#version 300 es\n"
2199 "precision mediump float;\n"
2200 "out vec4 my_FragColor; \n"
2201 "void main() {\n"
2202 " int j = 0; \n"
2203 " bool result = ((++j), (j == 1 ? true : (++j == 3)));\n"
2204 " my_FragColor = vec4(0.0, ((result && j == 1) ? 1.0 : 0.0), 0.0, 1.0);\n"
2205 "}\n";
2206
2207 GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
2208 ASSERT_NE(0u, program);
2209
2210 drawQuad(program, "inputAttribute", 0.5f);
2211
2212 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2213}
2214
Jamie Madill666f65a2016-08-26 01:34:37 +00002215// Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
2216// Indexing the vector needs to be evaluated after func() for the right result.
2217TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderDynamicVectorIndexingInLValue)
2218{
2219 const std::string &fragmentShaderSource =
2220 "#version 300 es\n"
2221 "precision mediump float;\n"
2222 "out vec4 my_FragColor;\n"
2223 "uniform int u_zero;\n"
2224 "int sideEffectCount = 0;\n"
2225 "float func() {\n"
2226 " ++sideEffectCount;\n"
2227 " return -1.0;\n"
2228 "}\n"
2229 "void main() {\n"
2230 " vec4 v = vec4(0.0, 2.0, 4.0, 6.0); \n"
2231 " float f = (func(), (++v[u_zero + sideEffectCount]));\n"
2232 " bool green = abs(f - 3.0) < 0.01 && abs(v[1] - 3.0) < 0.01 && sideEffectCount == 1;\n"
2233 " my_FragColor = vec4(0.0, (green ? 1.0 : 0.0), 0.0, 1.0);\n"
2234 "}\n";
2235
2236 GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
2237 ASSERT_NE(0u, program);
2238
2239 drawQuad(program, "inputAttribute", 0.5f);
2240
2241 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2242}
2243
Jamie Madillc9bde922016-07-24 17:58:50 -04002244// Test that using gl_PointCoord with GL_TRIANGLES doesn't produce a link error.
2245// From WebGL test conformance/rendering/point-specific-shader-variables.html
2246// See http://anglebug.com/1380
2247TEST_P(GLSLTest, RenderTrisWithPointCoord)
2248{
2249 const std::string &vert =
2250 "attribute vec2 aPosition;\n"
2251 "void main()\n"
2252 "{\n"
2253 " gl_Position = vec4(aPosition, 0, 1);\n"
2254 " gl_PointSize = 1.0;\n"
2255 "}";
2256 const std::string &frag =
2257 "void main()\n"
2258 "{\n"
2259 " gl_FragColor = vec4(gl_PointCoord.xy, 0, 1);\n"
2260 " gl_FragColor = vec4(0, 1, 0, 1);\n"
2261 "}";
2262
2263 ANGLE_GL_PROGRAM(prog, vert, frag);
2264 drawQuad(prog.get(), "aPosition", 0.5f);
2265 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2266}
2267
Jamie Madill5655b842016-08-02 11:00:07 -04002268// Convers a bug with the integer pow statement workaround.
2269TEST_P(GLSLTest, NestedPowStatements)
2270{
2271 const std::string &vert =
2272 "attribute vec2 position;\n"
2273 "void main()\n"
2274 "{\n"
2275 " gl_Position = vec4(position, 0, 1);\n"
2276 "}";
2277 const std::string &frag =
2278 "precision mediump float;\n"
2279 "float func(float v)\n"
2280 "{\n"
2281 " float f1 = pow(v, 2.0);\n"
2282 " return pow(f1 + v, 2.0);\n"
2283 "}\n"
2284 "void main()\n"
2285 "{\n"
2286 " float v = func(2.0);\n"
2287 " gl_FragColor = abs(v - 36.0) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
2288 "}";
2289
2290 ANGLE_GL_PROGRAM(prog, vert, frag);
2291 drawQuad(prog.get(), "position", 0.5f);
2292 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2293}
2294
Qiankun Miaof52fe932016-12-07 13:39:15 +08002295// Test that -float calculation is correct.
2296TEST_P(GLSLTest_ES3, UnaryMinusOperatorFloat)
2297{
Qiankun Miaof52fe932016-12-07 13:39:15 +08002298 const std::string &vert =
2299 "#version 300 es\n"
2300 "in highp vec4 position;\n"
2301 "void main() {\n"
2302 " gl_Position = position;\n"
2303 "}\n";
2304 const std::string &frag =
2305 "#version 300 es\n"
2306 "out highp vec4 o_color;\n"
2307 "void main() {\n"
2308 " highp float f = -1.0;\n"
2309 " // atan(tan(0.5), -f) should be 0.5.\n"
2310 " highp float v = atan(tan(0.5), -f);\n"
2311 " o_color = abs(v - 0.5) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
2312 "}\n";
2313
2314 ANGLE_GL_PROGRAM(prog, vert, frag);
2315 drawQuad(prog.get(), "position", 0.5f);
2316 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2317}
2318
Olli Etuahoda9fb092016-12-09 17:32:29 +00002319// Test that atan(vec2, vec2) calculation is correct.
2320TEST_P(GLSLTest_ES3, AtanVec2)
2321{
2322 const std::string &vert =
2323 "#version 300 es\n"
2324 "in highp vec4 position;\n"
2325 "void main() {\n"
2326 " gl_Position = position;\n"
2327 "}\n";
2328 const std::string &frag =
2329 "#version 300 es\n"
2330 "out highp vec4 o_color;\n"
2331 "void main() {\n"
2332 " highp float f = 1.0;\n"
2333 " // atan(tan(0.5), f) should be 0.5.\n"
2334 " highp vec2 v = atan(vec2(tan(0.5)), vec2(f));\n"
2335 " o_color = (abs(v[0] - 0.5) < 0.001 && abs(v[1] - 0.5) < 0.001) ? vec4(0, 1, 0, 1) : "
2336 "vec4(1, 0, 0, 1);\n"
2337 "}\n";
2338
2339 ANGLE_GL_PROGRAM(prog, vert, frag);
2340 drawQuad(prog.get(), "position", 0.5f);
2341 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2342}
2343
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002344// Convers a bug with the unary minus operator on signed integer workaround.
2345TEST_P(GLSLTest_ES3, UnaryMinusOperatorSignedInt)
2346{
2347 const std::string &vert =
2348 "#version 300 es\n"
2349 "in highp vec4 position;\n"
2350 "out mediump vec4 v_color;\n"
2351 "uniform int ui_one;\n"
2352 "uniform int ui_two;\n"
2353 "uniform int ui_three;\n"
2354 "void main() {\n"
2355 " int s[3];\n"
2356 " s[0] = ui_one;\n"
2357 " s[1] = -(-(-ui_two + 1) + 1);\n" // s[1] = -ui_two
2358 " s[2] = ui_three;\n"
2359 " int result = 0;\n"
2360 " for (int i = 0; i < ui_three; i++) {\n"
2361 " result += s[i];\n"
2362 " }\n"
2363 " v_color = (result == 2) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
2364 " gl_Position = position;\n"
2365 "}\n";
2366 const std::string &frag =
2367 "#version 300 es\n"
2368 "in mediump vec4 v_color;\n"
2369 "layout(location=0) out mediump vec4 o_color;\n"
2370 "void main() {\n"
2371 " o_color = v_color;\n"
2372 "}\n";
2373
2374 ANGLE_GL_PROGRAM(prog, vert, frag);
2375
Jamie Madille1faacb2016-12-13 12:42:14 -05002376 GLint oneIndex = glGetUniformLocation(prog.get(), "ui_one");
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002377 ASSERT_NE(-1, oneIndex);
Jamie Madille1faacb2016-12-13 12:42:14 -05002378 GLint twoIndex = glGetUniformLocation(prog.get(), "ui_two");
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002379 ASSERT_NE(-1, twoIndex);
Jamie Madille1faacb2016-12-13 12:42:14 -05002380 GLint threeIndex = glGetUniformLocation(prog.get(), "ui_three");
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002381 ASSERT_NE(-1, threeIndex);
2382 glUseProgram(prog.get());
2383 glUniform1i(oneIndex, 1);
2384 glUniform1i(twoIndex, 2);
2385 glUniform1i(threeIndex, 3);
2386
2387 drawQuad(prog.get(), "position", 0.5f);
2388 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2389}
2390
2391// Convers a bug with the unary minus operator on unsigned integer workaround.
2392TEST_P(GLSLTest_ES3, UnaryMinusOperatorUnsignedInt)
2393{
2394 const std::string &vert =
2395 "#version 300 es\n"
2396 "in highp vec4 position;\n"
2397 "out mediump vec4 v_color;\n"
2398 "uniform uint ui_one;\n"
2399 "uniform uint ui_two;\n"
2400 "uniform uint ui_three;\n"
2401 "void main() {\n"
2402 " uint s[3];\n"
2403 " s[0] = ui_one;\n"
2404 " s[1] = -(-(-ui_two + 1u) + 1u);\n" // s[1] = -ui_two
2405 " s[2] = ui_three;\n"
2406 " uint result = 0u;\n"
2407 " for (uint i = 0u; i < ui_three; i++) {\n"
2408 " result += s[i];\n"
2409 " }\n"
2410 " v_color = (result == 2u) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
2411 " gl_Position = position;\n"
2412 "}\n";
2413 const std::string &frag =
2414 "#version 300 es\n"
2415 "in mediump vec4 v_color;\n"
2416 "layout(location=0) out mediump vec4 o_color;\n"
2417 "void main() {\n"
2418 " o_color = v_color;\n"
2419 "}\n";
2420
2421 ANGLE_GL_PROGRAM(prog, vert, frag);
2422
Jamie Madille1faacb2016-12-13 12:42:14 -05002423 GLint oneIndex = glGetUniformLocation(prog.get(), "ui_one");
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002424 ASSERT_NE(-1, oneIndex);
Jamie Madille1faacb2016-12-13 12:42:14 -05002425 GLint twoIndex = glGetUniformLocation(prog.get(), "ui_two");
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002426 ASSERT_NE(-1, twoIndex);
Jamie Madille1faacb2016-12-13 12:42:14 -05002427 GLint threeIndex = glGetUniformLocation(prog.get(), "ui_three");
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002428 ASSERT_NE(-1, threeIndex);
2429 glUseProgram(prog.get());
2430 glUniform1ui(oneIndex, 1u);
2431 glUniform1ui(twoIndex, 2u);
2432 glUniform1ui(threeIndex, 3u);
2433
2434 drawQuad(prog.get(), "position", 0.5f);
2435 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2436}
2437
Olli Etuahoab481642016-08-26 12:09:10 +03002438// Test a nested sequence operator with a ternary operator inside. The ternary operator is
2439// intended to be such that it gets converted to an if statement on the HLSL backend.
2440TEST_P(GLSLTest, NestedSequenceOperatorWithTernaryInside)
2441{
2442 const std::string &vert =
2443 "attribute vec2 position;\n"
2444 "void main()\n"
2445 "{\n"
2446 " gl_Position = vec4(position, 0, 1);\n"
2447 "}";
2448
2449 // Note that the uniform keep_flop_positive doesn't need to be set - the test expects it to have
2450 // its default value false.
2451 const std::string &frag =
2452 "precision mediump float;\n"
2453 "uniform bool keep_flop_positive;\n"
2454 "float flop;\n"
2455 "void main() {\n"
2456 " flop = -1.0,\n"
2457 " (flop *= -1.0,\n"
2458 " keep_flop_positive ? 0.0 : flop *= -1.0),\n"
2459 " gl_FragColor = vec4(0, -flop, 0, 1);\n"
2460 "}";
2461
2462 ANGLE_GL_PROGRAM(prog, vert, frag);
2463 drawQuad(prog.get(), "position", 0.5f);
2464 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2465}
2466
Geoff Lang28a97ee2016-09-22 13:01:26 -04002467// Test that using a sampler2D and samplerExternalOES in the same shader works (anglebug.com/1534)
2468TEST_P(GLSLTest, ExternalAnd2DSampler)
2469{
2470 if (!extensionEnabled("GL_OES_EGL_image_external"))
2471 {
2472 std::cout << "Test skipped because GL_OES_EGL_image_external is not available."
2473 << std::endl;
2474 return;
2475 }
2476
2477 const std::string fragmentShader =
Olli Etuaho703671e2017-11-08 17:47:18 +02002478 R"(
2479 #extension GL_OES_EGL_image_external : enable
2480 precision mediump float;
2481 uniform samplerExternalOES tex0;
2482 uniform sampler2D tex1;
2483 void main(void)
2484 {
2485 vec2 uv = vec2(0.0, 0.0);
2486 gl_FragColor = texture2D(tex0, uv) + texture2D(tex1, uv);
2487 })";
Geoff Lang28a97ee2016-09-22 13:01:26 -04002488
2489 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2490}
2491
Olli Etuaho56a2f952016-12-08 12:16:27 +00002492// Test that literal infinity can be written out from the shader translator.
2493// A similar test can't be made for NaNs, since ESSL 3.00.6 requirements for NaNs are very loose.
2494TEST_P(GLSLTest_ES3, LiteralInfinityOutput)
2495{
2496 const std::string &fragmentShader =
2497 "#version 300 es\n"
2498 "precision highp float;\n"
2499 "out vec4 out_color;\n"
2500 "uniform float u;\n"
2501 "void main()\n"
2502 "{\n"
2503 " float infVar = 1.0e40 - u;\n"
2504 " bool correct = isinf(infVar) && infVar > 0.0;\n"
2505 " out_color = correct ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
2506 "}\n";
2507
2508 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2509 drawQuad(program.get(), "inputAttribute", 0.5f);
2510 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2511}
2512
2513// Test that literal negative infinity can be written out from the shader translator.
2514// A similar test can't be made for NaNs, since ESSL 3.00.6 requirements for NaNs are very loose.
2515TEST_P(GLSLTest_ES3, LiteralNegativeInfinityOutput)
2516{
2517 const std::string &fragmentShader =
2518 "#version 300 es\n"
2519 "precision highp float;\n"
2520 "out vec4 out_color;\n"
2521 "uniform float u;\n"
2522 "void main()\n"
2523 "{\n"
2524 " float infVar = -1.0e40 + u;\n"
2525 " bool correct = isinf(infVar) && infVar < 0.0;\n"
2526 " out_color = correct ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
2527 "}\n";
2528
2529 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2530 drawQuad(program.get(), "inputAttribute", 0.5f);
2531 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2532}
2533
Corentin Wallez36fd1002016-12-08 11:30:44 -05002534// The following MultipleDeclaration* tests are testing TranslatorHLSL specific simplification
2535// passes. Because the interaction of multiple passes must be tested, it is difficult to write
2536// a unittest for them. Instead we add the tests as end2end so will in particular test
2537// TranslatorHLSL when run on Windows.
2538
2539// Test that passes splitting multiple declarations and comma operators are correctly ordered.
2540TEST_P(GLSLTest_ES3, MultipleDeclarationWithCommaOperator)
2541{
2542 const std::string &fragmentShader =
Olli Etuaho7caa80e2017-11-14 15:03:14 +02002543 R"(#version 300 es
2544 precision mediump float;
2545 out vec4 color;
2546
2547 uniform float u;
2548 float c = 0.0;
2549 float sideEffect()
2550 {
2551 c = u;
2552 return c;
2553 }
2554
2555 void main(void)
2556 {
2557 float a = 0.0, b = ((gl_FragCoord.x < 0.5 ? a : sideEffect()), a);
2558 color = vec4(b + c);
2559 })";
Corentin Wallez36fd1002016-12-08 11:30:44 -05002560
2561 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2562}
2563
2564// Test that passes splitting multiple declarations and comma operators and for loops are
2565// correctly ordered.
2566TEST_P(GLSLTest_ES3, MultipleDeclarationWithCommaOperatorInForLoop)
2567{
2568 const std::string &fragmentShader =
Olli Etuaho7caa80e2017-11-14 15:03:14 +02002569 R"(#version 300 es
2570 precision mediump float;
2571 out vec4 color;
2572
2573 uniform float u;
2574 float c = 0.0;
2575 float sideEffect()
2576 {
2577 c = u;
2578 return c;
2579 }
2580
2581 void main(void)
2582 {
2583 for(float a = 0.0, b = ((gl_FragCoord.x < 0.5 ? a : sideEffect()), a); a < 10.0; a++)
2584 {
2585 b += 1.0;
2586 color = vec4(b);
2587 }
2588 })";
Corentin Wallez36fd1002016-12-08 11:30:44 -05002589
2590 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2591}
2592
2593// Test that splitting multiple declaration in for loops works with no loop condition
2594TEST_P(GLSLTest_ES3, MultipleDeclarationInForLoopEmptyCondition)
2595{
2596 const std::string &fragmentShader =
2597 "#version 300 es\n"
2598 "precision mediump float;\n"
2599 "out vec4 color;\n"
2600 "void main(void)\n"
2601 "{\n"
2602 " for(float a = 0.0, b = 1.0;; a++)\n"
2603 " {\n"
2604 " b += 1.0;\n"
2605 " if (a > 10.0) {break;}\n"
2606 " color = vec4(b);\n"
2607 " }\n"
2608 "}\n";
2609
2610 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2611}
2612
2613// Test that splitting multiple declaration in for loops works with no loop expression
2614TEST_P(GLSLTest_ES3, MultipleDeclarationInForLoopEmptyExpression)
2615{
2616 const std::string &fragmentShader =
2617 "#version 300 es\n"
2618 "precision mediump float;\n"
2619 "out vec4 color;\n"
2620 "void main(void)\n"
2621 "{\n"
2622 " for(float a = 0.0, b = 1.0; a < 10.0;)\n"
2623 " {\n"
2624 " b += 1.0;\n"
2625 " a += 1.0;\n"
2626 " color = vec4(b);\n"
2627 " }\n"
2628 "}\n";
2629
2630 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2631}
2632
Olli Etuaho8f6eb2a2017-01-12 17:04:58 +00002633// Test that dynamic indexing of a matrix inside a dynamic indexing of a vector in an l-value works
2634// correctly.
2635TEST_P(GLSLTest_ES3, NestedDynamicIndexingInLValue)
2636{
2637 const std::string &fragmentShader =
2638 "#version 300 es\n"
2639 "precision mediump float;\n"
2640 "out vec4 my_FragColor;\n"
2641 "uniform int u_zero;\n"
2642 "void main() {\n"
2643 " mat2 m = mat2(0.0, 0.0, 0.0, 0.0);\n"
2644 " m[u_zero + 1][u_zero + 1] = float(u_zero + 1);\n"
2645 " float f = m[1][1];\n"
2646 " my_FragColor = vec4(1.0 - f, f, 0.0, 1.0);\n"
2647 "}\n";
2648
2649 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2650 drawQuad(program.get(), "inputAttribute", 0.5f);
2651 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2652}
2653
Jamie Madill192745a2016-12-22 15:58:21 -05002654class WebGLGLSLTest : public GLSLTest
2655{
2656 protected:
2657 WebGLGLSLTest() { setWebGLCompatibilityEnabled(true); }
2658};
2659
2660TEST_P(WebGLGLSLTest, MaxVaryingVec4PlusFragCoord)
2661{
2662 GLint maxVaryings = 0;
2663 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2664
2665 // Generate shader code that uses gl_FragCoord, a special fragment shader variables.
2666 // This test should fail, since we are really using (maxVaryings + 1) varyings.
2667 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, true, false, false, false);
2668}
2669
2670TEST_P(WebGLGLSLTest, MaxVaryingVec4PlusPointCoord)
2671{
2672 GLint maxVaryings = 0;
2673 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2674
2675 // Generate shader code that uses gl_FragCoord, a special fragment shader variables.
2676 // This test should fail, since we are really using (maxVaryings + 1) varyings.
2677 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, false, true, false, false);
2678}
2679
2680TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec3)
2681{
2682 GLint maxVaryings = 0;
2683 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2684
2685 VaryingTestBase(0, 0, 0, 0, maxVaryings + 1, 0, 0, 0, false, false, false, false);
2686}
2687
2688TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec3Array)
2689{
2690 GLint maxVaryings = 0;
2691 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2692
2693 VaryingTestBase(0, 0, 0, 0, 0, maxVaryings / 2 + 1, 0, 0, false, false, false, false);
2694}
2695
2696TEST_P(WebGLGLSLTest, MaxVaryingVec3AndOneVec2)
2697{
2698 GLint maxVaryings = 0;
2699 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2700
2701 VaryingTestBase(0, 0, 1, 0, maxVaryings, 0, 0, 0, false, false, false, false);
2702}
2703
2704TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec2)
2705{
2706 GLint maxVaryings = 0;
2707 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2708
2709 VaryingTestBase(0, 0, 2 * maxVaryings + 1, 0, 0, 0, 0, 0, false, false, false, false);
2710}
2711
2712TEST_P(WebGLGLSLTest, MaxVaryingVec3ArrayAndMaxPlusOneFloatArray)
2713{
2714 GLint maxVaryings = 0;
2715 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2716
2717 VaryingTestBase(0, maxVaryings / 2 + 1, 0, 0, 0, 0, 0, maxVaryings / 2, false, false, false,
2718 false);
2719}
2720
Jamie Madill6c9503e2016-08-16 14:06:32 -04002721} // anonymous namespace
2722
Olli Etuaho9250cb22017-01-21 10:51:27 +00002723// Test that FindLSB and FindMSB return correct values in their corner cases.
2724TEST_P(GLSLTest_ES31, FindMSBAndFindLSBCornerCases)
2725{
Olli Etuaho61bd9fe2017-01-27 14:20:34 -08002726 // Suspecting AMD driver bug - failure seen on bots running on AMD R5 230.
2727 if (IsAMD() && IsOpenGL() && IsLinux())
2728 {
2729 std::cout << "Test skipped on AMD OpenGL Linux" << std::endl;
2730 return;
2731 }
2732
Yuly Novikov4e36db82018-01-19 17:35:33 -05002733 // Failing on N5X Oreo http://anglebug.com/2304
2734 ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
2735
Olli Etuaho9250cb22017-01-21 10:51:27 +00002736 const std::string &fragmentShader =
2737 "#version 310 es\n"
2738 "precision mediump float;\n"
2739 "out vec4 my_FragColor;\n"
2740 "uniform int u_zero;\n"
2741 "void main() {\n"
2742 " if (findLSB(u_zero) == -1 && findMSB(u_zero) == -1 && findMSB(u_zero - 1) == -1)\n"
2743 " {\n"
2744 " my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
2745 " }\n"
2746 " else\n"
2747 " {\n"
2748 " my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
2749 " }\n"
2750 "}\n";
2751
2752 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2753 drawQuad(program.get(), "inputAttribute", 0.5f);
2754 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2755}
2756
Olli Etuahoc9da71f2017-03-06 16:28:54 +00002757// Test that writing into a swizzled vector that is dynamically indexed succeeds.
2758TEST_P(GLSLTest_ES3, WriteIntoDynamicIndexingOfSwizzledVector)
2759{
Corentin Wallez6445ddf2017-03-08 19:00:32 -05002760 if (IsOpenGL())
Olli Etuahoc9da71f2017-03-06 16:28:54 +00002761 {
2762 // http://anglebug.com/1924
Corentin Wallez6445ddf2017-03-08 19:00:32 -05002763 std::cout << "Test skipped on all OpenGL configurations because it has incorrect results"
2764 << std::endl;
Olli Etuahoc9da71f2017-03-06 16:28:54 +00002765 return;
2766 }
2767
2768 // The shader first assigns v.x to v.z (1.0)
2769 // Then v.y to v.y (2.0)
2770 // Then v.z to v.x (1.0)
2771 const std::string &fragmentShader =
2772 "#version 300 es\n"
2773 "precision highp float;\n"
2774 "out vec4 my_FragColor;\n"
2775 "void main() {\n"
2776 " vec3 v = vec3(1.0, 2.0, 3.0);\n"
2777 " for (int i = 0; i < 3; i++) {\n"
2778 " v.zyx[i] = v[i];\n"
2779 " }\n"
2780 " my_FragColor = distance(v, vec3(1.0, 2.0, 1.0)) < 0.01 ? vec4(0, 1, 0, 1) : vec4(1, "
2781 "0, 0, 1);\n"
2782 "}\n";
2783
2784 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2785 drawQuad(program.get(), "inputAttribute", 0.5f);
2786 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2787}
2788
Jamie Madill8aeeed62017-03-15 18:09:26 -04002789// This test covers a bug (and associated workaround) with nested sampling operations in the HLSL
2790// compiler DLL.
2791TEST_P(GLSLTest_ES3, NestedSamplingOperation)
2792{
2793 // This seems to be bugged on some version of Android. Might not affect the newest versions.
2794 // TODO(jmadill): Lift suppression when Chromium bots are upgraded.
2795 if (IsAndroid() && IsOpenGLES())
2796 {
2797 std::cout << "Test skipped on Android because of bug with Nexus 5X." << std::endl;
2798 return;
2799 }
2800
2801 const std::string &vertexShader =
2802 "#version 300 es\n"
2803 "out vec2 texCoord;\n"
2804 "in vec2 position;\n"
2805 "void main()\n"
2806 "{\n"
2807 " gl_Position = vec4(position, 0, 1);\n"
2808 " texCoord = position * 0.5 + vec2(0.5);\n"
2809 "}\n";
2810
2811 const std::string &simpleFragmentShader =
2812 "#version 300 es\n"
2813 "in mediump vec2 texCoord;\n"
2814 "out mediump vec4 fragColor;\n"
2815 "void main()\n"
2816 "{\n"
2817 " fragColor = vec4(texCoord, 0, 1);\n"
2818 "}\n";
2819
2820 const std::string &nestedFragmentShader =
2821 "#version 300 es\n"
2822 "uniform mediump sampler2D samplerA;\n"
2823 "uniform mediump sampler2D samplerB;\n"
2824 "in mediump vec2 texCoord;\n"
2825 "out mediump vec4 fragColor;\n"
2826 "void main ()\n"
2827 "{\n"
2828 " fragColor = texture(samplerB, texture(samplerA, texCoord).xy);\n"
2829 "}\n";
2830
2831 ANGLE_GL_PROGRAM(initProg, vertexShader, simpleFragmentShader);
2832 ANGLE_GL_PROGRAM(nestedProg, vertexShader, nestedFragmentShader);
2833
2834 // Initialize a first texture with default texCoord data.
2835 GLTexture texA;
2836 glActiveTexture(GL_TEXTURE0);
2837 glBindTexture(GL_TEXTURE_2D, texA);
2838 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
2839 GL_UNSIGNED_BYTE, nullptr);
2840 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2841 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2842
2843 GLFramebuffer fbo;
2844 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2845 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texA, 0);
2846
2847 drawQuad(initProg, "position", 0.5f);
2848 ASSERT_GL_NO_ERROR();
2849
2850 // Initialize a second texture with a simple color pattern.
2851 GLTexture texB;
2852 glActiveTexture(GL_TEXTURE1);
2853 glBindTexture(GL_TEXTURE_2D, texB);
2854
2855 std::array<GLColor, 4> simpleColors = {
2856 {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
2857 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2858 simpleColors.data());
2859 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2860 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2861
2862 // Draw with the nested program, using the first texture to index the second.
2863 glBindFramebuffer(GL_FRAMEBUFFER, 0);
2864 glUseProgram(nestedProg);
2865 GLint samplerALoc = glGetUniformLocation(nestedProg, "samplerA");
2866 ASSERT_NE(-1, samplerALoc);
2867 glUniform1i(samplerALoc, 0);
2868 GLint samplerBLoc = glGetUniformLocation(nestedProg, "samplerB");
2869 ASSERT_NE(-1, samplerBLoc);
2870 glUniform1i(samplerBLoc, 1);
2871
2872 drawQuad(nestedProg, "position", 0.5f);
2873 ASSERT_GL_NO_ERROR();
2874
2875 // Compute four texel centers.
2876 Vector2 windowSize(getWindowWidth(), getWindowHeight());
2877 Vector2 quarterWindowSize = windowSize / 4;
2878 Vector2 ul = quarterWindowSize;
2879 Vector2 ur(windowSize.x() - quarterWindowSize.x(), quarterWindowSize.y());
2880 Vector2 ll(quarterWindowSize.x(), windowSize.y() - quarterWindowSize.y());
2881 Vector2 lr = windowSize - quarterWindowSize;
2882
2883 EXPECT_PIXEL_COLOR_EQ_VEC2(ul, simpleColors[0]);
2884 EXPECT_PIXEL_COLOR_EQ_VEC2(ur, simpleColors[1]);
2885 EXPECT_PIXEL_COLOR_EQ_VEC2(ll, simpleColors[2]);
2886 EXPECT_PIXEL_COLOR_EQ_VEC2(lr, simpleColors[3]);
2887}
2888
Olli Etuaho81629262017-04-19 11:56:01 +03002889// Tests that using a constant declaration as the only statement in a for loop without curly braces
2890// doesn't crash.
2891TEST_P(GLSLTest, ConstantStatementInForLoop)
2892{
2893 const std::string &vertexShader =
2894 "void main()\n"
2895 "{\n"
2896 " for (int i = 0; i < 10; ++i)\n"
2897 " const int b = 0;\n"
2898 "}\n";
2899
2900 GLuint shader = CompileShader(GL_VERTEX_SHADER, vertexShader);
2901 EXPECT_NE(0u, shader);
2902 glDeleteShader(shader);
2903}
2904
2905// Tests that using a constant declaration as a loop init expression doesn't crash. Note that this
2906// test doesn't work on D3D9 due to looping limitations, so it is only run on ES3.
2907TEST_P(GLSLTest_ES3, ConstantStatementAsLoopInit)
2908{
2909 const std::string &vertexShader =
2910 "void main()\n"
2911 "{\n"
2912 " for (const int i = 0; i < 0;) {}\n"
2913 "}\n";
2914
2915 GLuint shader = CompileShader(GL_VERTEX_SHADER, vertexShader);
2916 EXPECT_NE(0u, shader);
2917 glDeleteShader(shader);
2918}
2919
Olli Etuaho9733cee2017-05-11 19:14:35 +03002920// Test that uninitialized local variables are initialized to 0.
2921TEST_P(GLSLTest_ES3, InitUninitializedLocals)
2922{
2923 if (IsAndroid() && IsOpenGLES())
2924 {
2925 // http://anglebug.com/2046
2926 std::cout
2927 << "Test skipped on Android GLES because local variable initialization is disabled."
2928 << std::endl;
2929 return;
2930 }
2931
Olli Etuaho9733cee2017-05-11 19:14:35 +03002932 const std::string &fragmentShader =
2933 "#version 300 es\n"
2934 "precision mediump float;\n"
2935 "out vec4 my_FragColor;\n"
2936 "int result = 0;\n"
2937 "void main()\n"
2938 "{\n"
2939 " int u;\n"
2940 " result += u;\n"
2941 " int k = 0;\n"
2942 " for (int i[2], j = i[0] + 1; k < 2; ++k)\n"
2943 " {\n"
2944 " result += j;\n"
2945 " }\n"
2946 " if (result == 2)\n"
2947 " {\n"
2948 " my_FragColor = vec4(0, 1, 0, 1);\n"
2949 " }\n"
2950 " else\n"
2951 " {\n"
2952 " my_FragColor = vec4(1, 0, 0, 1);\n"
2953 " }\n"
2954 "}\n";
2955
2956 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2957 drawQuad(program.get(), "inputAttribute", 0.5f);
2958 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2959}
2960
2961// Test that uninitialized structs containing arrays of structs are initialized to 0. This
2962// specifically tests with two different struct variables declared in the same block.
2963TEST_P(GLSLTest, InitUninitializedStructContainingArrays)
2964{
2965 if (IsAndroid() && IsOpenGLES())
2966 {
2967 // http://anglebug.com/2046
2968 std::cout
2969 << "Test skipped on Android GLES because local variable initialization is disabled."
2970 << std::endl;
2971 return;
2972 }
2973
2974 if (IsOSX() && IsOpenGL())
2975 {
2976 // http://anglebug.com/2041
2977 std::cout << "Test skipped on Mac OpenGL because local variable initialization is disabled."
2978 << std::endl;
2979 return;
2980 }
2981
2982 const std::string &fragmentShader =
2983 "precision mediump float;\n"
2984 "struct T\n"
2985 "{\n"
2986 " int a[2];\n"
2987 "};\n"
2988 "struct S\n"
2989 "{\n"
2990 " T t[2];\n"
2991 "};\n"
2992 "void main()\n"
2993 "{\n"
2994 " S s;\n"
2995 " S s2;\n"
2996 " if (s.t[1].a[1] == 0 && s2.t[1].a[1] == 0)\n"
2997 " {\n"
2998 " gl_FragColor = vec4(0, 1, 0, 1);\n"
2999 " }\n"
3000 " else\n"
3001 " {\n"
3002 " gl_FragColor = vec4(1, 0, 0, 1);\n"
3003 " }\n"
3004 "}\n";
3005
3006 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3007 drawQuad(program.get(), "inputAttribute", 0.5f);
3008 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3009}
3010
Geoff Langbb1e7502017-06-05 16:40:09 -04003011// Verify that two shaders with the same uniform name and members but different structure names will
3012// not link.
3013TEST_P(GLSLTest, StructureNameMatchingTest)
3014{
3015 const char *vsSource =
3016 "// Structures must have the same name, sequence of type names, and\n"
3017 "// type definitions, and field names to be considered the same type.\n"
3018 "// GLSL 1.017 4.2.4\n"
3019 "precision mediump float;\n"
3020 "struct info {\n"
3021 " vec4 pos;\n"
3022 " vec4 color;\n"
3023 "};\n"
3024 "\n"
3025 "uniform info uni;\n"
3026 "void main()\n"
3027 "{\n"
3028 " gl_Position = uni.pos;\n"
3029 "}\n";
3030
3031 GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
3032 ASSERT_NE(0u, vs);
3033 glDeleteShader(vs);
3034
3035 const char *fsSource =
3036 "// Structures must have the same name, sequence of type names, and\n"
3037 "// type definitions, and field names to be considered the same type.\n"
3038 "// GLSL 1.017 4.2.4\n"
3039 "precision mediump float;\n"
3040 "struct info1 {\n"
3041 " vec4 pos;\n"
3042 " vec4 color;\n"
3043 "};\n"
3044 "\n"
3045 "uniform info1 uni;\n"
3046 "void main()\n"
3047 "{\n"
3048 " gl_FragColor = uni.color;\n"
3049 "}\n";
3050
3051 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
3052 ASSERT_NE(0u, fs);
3053 glDeleteShader(fs);
3054
3055 GLuint program = CompileProgram(vsSource, fsSource);
3056 EXPECT_EQ(0u, program);
3057}
3058
Olli Etuaho9733cee2017-05-11 19:14:35 +03003059// Test that an uninitialized nameless struct inside a for loop init statement works.
3060TEST_P(GLSLTest_ES3, UninitializedNamelessStructInForInitStatement)
3061{
3062 if (IsAndroid() && IsOpenGLES())
3063 {
3064 // http://anglebug.com/2046
3065 std::cout
3066 << "Test skipped on Android GLES because local variable initialization is disabled."
3067 << std::endl;
3068 return;
3069 }
3070
3071 if (IsOSX() && IsOpenGL())
3072 {
3073 // http://anglebug.com/2041
3074 std::cout << "Test skipped on Mac OpenGL because local variable initialization is disabled."
3075 << std::endl;
3076 return;
3077 }
3078
3079 const std::string &fragmentShader =
3080 "#version 300 es\n"
3081 "precision highp float;\n"
3082 "out vec4 my_FragColor;\n"
3083 "void main()\n"
3084 "{\n"
3085 " my_FragColor = vec4(1, 0, 0, 1);\n"
3086 " for (struct { float q; } b; b.q < 2.0; b.q++) {\n"
3087 " my_FragColor = vec4(0, 1, 0, 1);\n"
3088 " }\n"
3089 "}\n";
3090
3091 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3092 drawQuad(program.get(), "inputAttribute", 0.5f);
3093 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3094}
3095
Olli Etuaho0ffc4412017-05-19 14:18:55 +03003096// Test that uninitialized global variables are initialized to 0.
3097TEST_P(WebGLGLSLTest, InitUninitializedGlobals)
3098{
3099 const std::string &fragmentShader =
3100 "precision mediump float;\n"
3101 "int result;\n"
3102 "int i[2], j = i[0] + 1;\n"
3103 "void main()\n"
3104 "{\n"
3105 " result += j;\n"
3106 " if (result == 1)\n"
3107 " {\n"
3108 " gl_FragColor = vec4(0, 1, 0, 1);\n"
3109 " }\n"
3110 " else\n"
3111 " {\n"
3112 " gl_FragColor = vec4(1, 0, 0, 1);\n"
3113 " }\n"
3114 "}\n";
3115
3116 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3117 drawQuad(program.get(), "inputAttribute", 0.5f, 1.0f, true);
3118 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3119}
3120
3121// Test that an uninitialized nameless struct in the global scope works.
3122TEST_P(WebGLGLSLTest, UninitializedNamelessStructInGlobalScope)
3123{
3124 const std::string &fragmentShader =
3125 "precision mediump float;\n"
3126 "struct { float q; } b;\n"
3127 "void main()\n"
3128 "{\n"
3129 " gl_FragColor = vec4(1, 0, 0, 1);\n"
3130 " if (b.q == 0.0)\n"
3131 " {\n"
3132 " gl_FragColor = vec4(0, 1, 0, 1);\n"
3133 " }\n"
3134 "}\n";
3135
3136 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3137 drawQuad(program.get(), "inputAttribute", 0.5f, 1.0f, true);
3138 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3139}
3140
Olli Etuaho914b79a2017-06-19 16:03:19 +03003141// Test that a loop condition that has an initializer declares a variable.
3142TEST_P(GLSLTest_ES3, ConditionInitializerDeclaresVariable)
3143{
3144 const std::string &fragmentShader =
3145 "#version 300 es\n"
3146 "precision highp float;\n"
3147 "out vec4 my_FragColor;\n"
3148 "void main()\n"
3149 "{\n"
3150 " float i = 0.0;\n"
3151 " while (bool foo = (i < 1.5))\n"
3152 " {\n"
3153 " if (!foo)\n"
3154 " {\n"
3155 " ++i;\n"
3156 " }\n"
3157 " if (i > 3.5)\n"
3158 " {\n"
3159 " break;\n"
3160 " }\n"
3161 " ++i;\n"
3162 " }\n"
3163 " my_FragColor = vec4(i * 0.5 - 1.0, i * 0.5, 0.0, 1.0);\n"
3164 "}\n";
3165
3166 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3167 drawQuad(program.get(), "inputAttribute", 0.5f);
3168 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3169}
3170
Olli Etuahoff526f12017-06-30 12:26:54 +03003171// Test that a variable hides a user-defined function with the same name after its initializer.
3172// GLSL ES 1.00.17 section 4.2.2: "A variable declaration is visible immediately following the
3173// initializer if present, otherwise immediately following the identifier"
3174TEST_P(GLSLTest, VariableHidesUserDefinedFunctionAfterInitializer)
3175{
3176 const std::string &fragmentShader =
3177 "precision mediump float;\n"
3178 "uniform vec4 u;\n"
3179 "vec4 foo()\n"
3180 "{\n"
3181 " return u;\n"
3182 "}\n"
3183 "void main()\n"
3184 "{\n"
3185 " vec4 foo = foo();\n"
3186 " gl_FragColor = foo + vec4(0, 1, 0, 1);\n"
3187 "}\n";
3188
3189 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3190 drawQuad(program.get(), "inputAttribute", 0.5f);
3191 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3192}
3193
Olli Etuaho088031e2017-07-03 15:59:33 +03003194// Test that structs with identical members are not ambiguous as function arguments.
3195TEST_P(GLSLTest, StructsWithSameMembersDisambiguatedByName)
3196{
3197 const std::string &fragmentShader =
3198 "precision mediump float;\n"
3199 "uniform float u_zero;\n"
3200 "struct S { float foo; };\n"
3201 "struct S2 { float foo; };\n"
3202 "float get(S s) { return s.foo + u_zero; }\n"
3203 "float get(S2 s2) { return 0.25 + s2.foo + u_zero; }\n"
3204 "void main()\n"
3205 "{\n"
3206 " S s;\n"
3207 " s.foo = 0.5;\n"
3208 " S2 s2;\n"
3209 " s2.foo = 0.25;\n"
3210 " gl_FragColor = vec4(0.0, get(s) + get(s2), 0.0, 1.0);\n"
3211 "}\n";
3212
3213 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3214 drawQuad(program.get(), "inputAttribute", 0.5f);
3215 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3216}
3217
Olli Etuaho06a06f52017-07-12 12:22:15 +03003218// Test that a varying struct that's not statically used in the fragment shader works.
3219// GLSL ES 3.00.6 section 4.3.10.
3220TEST_P(GLSLTest_ES3, VaryingStructNotStaticallyUsedInFragmentShader)
3221{
3222 const std::string &vertexShader =
3223 "#version 300 es\n"
3224 "struct S {\n"
3225 " vec4 field;\n"
3226 "};\n"
3227 "out S varStruct;\n"
3228 "void main()\n"
3229 "{\n"
3230 " gl_Position = vec4(1.0);\n"
3231 " varStruct.field = vec4(0.0, 0.5, 0.0, 0.0);\n"
3232 "}\n";
3233
3234 const std::string &fragmentShader =
3235 "#version 300 es\n"
3236 "precision mediump float;\n"
3237 "struct S {\n"
3238 " vec4 field;\n"
3239 "};\n"
3240 "in S varStruct;\n"
3241 "out vec4 col;\n"
3242 "void main()\n"
3243 "{\n"
3244 " col = vec4(1.0);\n"
3245 "}\n";
3246
3247 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3248}
3249
3250// Test that a varying struct that's not declared in the fragment shader links successfully.
3251// GLSL ES 3.00.6 section 4.3.10.
3252TEST_P(GLSLTest_ES3, VaryingStructNotDeclaredInFragmentShader)
3253{
3254 const std::string &vertexShader =
3255 "#version 300 es\n"
3256 "struct S {\n"
3257 " vec4 field;\n"
3258 "};\n"
3259 "out S varStruct;\n"
3260 "void main()\n"
3261 "{\n"
3262 " gl_Position = vec4(1.0);\n"
3263 " varStruct.field = vec4(0.0, 0.5, 0.0, 0.0);\n"
3264 "}\n";
3265
3266 const std::string &fragmentShader =
3267 "#version 300 es\n"
3268 "precision mediump float;\n"
3269 "out vec4 col;\n"
3270 "void main()\n"
3271 "{\n"
3272 " col = vec4(1.0);\n"
3273 "}\n";
3274
3275 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3276}
3277
3278// Test that a varying struct that gets used in the fragment shader works.
3279TEST_P(GLSLTest_ES3, VaryingStructUsedInFragmentShader)
3280{
3281 const std::string &vertexShader =
3282 "#version 300 es\n"
3283 "in vec4 inputAttribute;\n"
3284 "struct S {\n"
3285 " vec4 field;\n"
3286 "};\n"
3287 "out S varStruct;\n"
3288 "void main()\n"
3289 "{\n"
3290 " gl_Position = inputAttribute;\n"
3291 " varStruct.field = vec4(0.0, 1.0, 0.0, 1.0);\n"
3292 "}\n";
3293
3294 const std::string &fragmentShader =
3295 "#version 300 es\n"
3296 "precision mediump float;\n"
3297 "out vec4 col;\n"
3298 "struct S {\n"
3299 " vec4 field;\n"
3300 "};\n"
3301 "in S varStruct;\n"
3302 "void main()\n"
3303 "{\n"
3304 " col = varStruct.field;\n"
3305 "}\n";
3306
3307 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3308 drawQuad(program.get(), "inputAttribute", 0.5f);
3309 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3310}
3311
Olli Etuaho3860b6c2017-07-19 16:17:24 +03003312// This test covers passing an array of structs containing samplers as a function argument.
3313TEST_P(GLSLTest, ArrayOfStructsWithSamplersAsFunctionArg)
3314{
3315 if (IsAndroid() && IsAdreno() && IsOpenGLES())
3316 {
3317 // Shader failed to compile on Android. http://anglebug.com/2114
3318 std::cout << "Test skipped on Adreno OpenGLES on Android." << std::endl;
3319 return;
3320 }
3321
3322 const std::string &vertexShader =
3323 "attribute vec2 position;\n"
3324 "void main()\n"
3325 "{\n"
3326 " gl_Position = vec4(position, 0, 1);\n"
3327 "}\n";
3328
3329 const std::string &fragmentShader =
3330 "precision mediump float;\n"
3331 "struct S\n"
3332 "{\n"
3333 " sampler2D samplerMember; \n"
3334 "};\n"
3335 "uniform S uStructs[2];\n"
3336 "uniform vec2 uTexCoord;\n"
3337 "\n"
3338 "vec4 foo(S[2] structs)\n"
3339 "{\n"
3340 " return texture2D(structs[0].samplerMember, uTexCoord);\n"
3341 "}\n"
3342 "void main()\n"
3343 "{\n"
3344 " gl_FragColor = foo(uStructs);\n"
3345 "}\n";
3346
3347 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3348
3349 // Initialize the texture with green.
3350 GLTexture tex;
3351 glActiveTexture(GL_TEXTURE0);
3352 glBindTexture(GL_TEXTURE_2D, tex);
3353 GLubyte texData[] = {0u, 255u, 0u, 255u};
3354 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
3355 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3356 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3357 ASSERT_GL_NO_ERROR();
3358
3359 // Draw
3360 glUseProgram(program);
3361 GLint samplerMemberLoc = glGetUniformLocation(program, "uStructs[0].samplerMember");
3362 ASSERT_NE(-1, samplerMemberLoc);
3363 glUniform1i(samplerMemberLoc, 0);
3364 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
3365 ASSERT_NE(-1, texCoordLoc);
3366 glUniform2f(texCoordLoc, 0.5f, 0.5f);
3367
3368 drawQuad(program, "position", 0.5f);
3369 ASSERT_GL_NO_ERROR();
3370
3371 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
3372}
3373
Olli Etuaho28839f02017-08-15 11:38:16 +03003374// This test covers passing a struct containing an array of samplers as a function argument.
3375TEST_P(GLSLTest, StructWithSamplerArrayAsFunctionArg)
3376{
3377 if (IsAndroid() && IsAdreno() && IsOpenGLES())
3378 {
3379 // Shader failed to compile on Android. http://anglebug.com/2114
3380 std::cout << "Test skipped on Adreno OpenGLES on Android." << std::endl;
3381 return;
3382 }
3383
3384 const std::string &vertexShader =
3385 "attribute vec2 position;\n"
3386 "void main()\n"
3387 "{\n"
3388 " gl_Position = vec4(position, 0, 1);\n"
3389 "}\n";
3390
3391 const std::string &fragmentShader =
3392 "precision mediump float;\n"
3393 "struct S\n"
3394 "{\n"
3395 " sampler2D samplerMembers[2];\n"
3396 "};\n"
3397 "uniform S uStruct;\n"
3398 "uniform vec2 uTexCoord;\n"
3399 "\n"
3400 "vec4 foo(S str)\n"
3401 "{\n"
3402 " return texture2D(str.samplerMembers[0], uTexCoord);\n"
3403 "}\n"
3404 "void main()\n"
3405 "{\n"
3406 " gl_FragColor = foo(uStruct);\n"
3407 "}\n";
3408
3409 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3410
3411 // Initialize the texture with green.
3412 GLTexture tex;
3413 glActiveTexture(GL_TEXTURE0);
3414 glBindTexture(GL_TEXTURE_2D, tex);
3415 GLubyte texData[] = {0u, 255u, 0u, 255u};
3416 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
3417 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3418 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3419 ASSERT_GL_NO_ERROR();
3420
3421 // Draw
3422 glUseProgram(program);
3423 GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMembers[0]");
3424 ASSERT_NE(-1, samplerMemberLoc);
3425 glUniform1i(samplerMemberLoc, 0);
3426 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
3427 ASSERT_NE(-1, texCoordLoc);
3428 glUniform2f(texCoordLoc, 0.5f, 0.5f);
3429
3430 drawQuad(program, "position", 0.5f);
3431 ASSERT_GL_NO_ERROR();
3432
3433 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
3434}
3435
Olli Etuahoa16a84f2017-09-12 13:49:18 +03003436// Test that a global variable declared after main() works. This is a regression test for an issue
3437// in global variable initialization.
3438TEST_P(WebGLGLSLTest, GlobalVariableDeclaredAfterMain)
3439{
3440 const std::string &fragmentShader =
3441 "precision mediump float;\n"
3442 "int getFoo();\n"
3443 "uniform int u_zero;\n"
3444 "void main()\n"
3445 "{\n"
3446 " gl_FragColor = vec4(1, 0, 0, 1);\n"
3447 " if (getFoo() == 0)\n"
3448 " {\n"
3449 " gl_FragColor = vec4(0, 1, 0, 1);\n"
3450 " }\n"
3451 "}\n"
3452 "int foo;\n"
3453 "int getFoo()\n"
3454 "{\n"
3455 " foo = u_zero;\n"
3456 " return foo;\n"
3457 "}\n";
3458
3459 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3460 drawQuad(program.get(), "inputAttribute", 0.5f, 1.0f, true);
3461 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3462}
3463
Olli Etuahobb5a7e22017-08-30 13:03:12 +03003464// Test calling array length() with a "this" expression having side effects inside a loop condition.
3465// The spec says that sequence operator operands need to run in sequence.
3466TEST_P(GLSLTest_ES3, ArrayLengthOnExpressionWithSideEffectsInLoopCondition)
3467{
3468 // "a" gets doubled three times in the below program.
3469 const std::string &fragmentShader =
3470 R"(#version 300 es
3471 precision highp float;
3472 out vec4 my_FragColor;
3473 uniform int u_zero;
3474 int a;
3475 int[2] doubleA()
3476 {
3477 a *= 2;
3478 return int[2](a, a);
3479 }
3480 void main()
3481 {
3482 a = u_zero + 1;
3483 for (int i = 0; i < doubleA().length(); ++i)
3484 {}
3485 if (a == 8)
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
3500// Test calling array length() with a "this" expression having side effects that interact with side
3501// effects of another operand of the same sequence operator. The spec says that sequence operator
3502// operands need to run in order from left to right (ESSL 3.00.6 section 5.9).
3503TEST_P(GLSLTest_ES3, ArrayLengthOnExpressionWithSideEffectsInSequence)
3504{
3505 const std::string &fragmentShader =
3506 R"(#version 300 es
3507 precision highp float;
3508 out vec4 my_FragColor;
3509 uniform int u_zero;
3510 int a;
3511 int[3] doubleA()
3512 {
3513 a *= 2;
3514 return int[3](a, a, a);
3515 }
3516 void main()
3517 {
3518 a = u_zero;
3519 int b = (a++, doubleA().length());
3520 if (b == 3 && a == 2)
3521 {
3522 my_FragColor = vec4(0, 1, 0, 1);
3523 }
3524 else
3525 {
3526 my_FragColor = vec4(1, 0, 0, 1);
3527 }
3528 })";
3529
3530 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3531 drawQuad(program.get(), "inputAttribute", 0.5f);
3532 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3533}
3534
3535// Test calling array length() with a "this" expression that also contains a call of array length().
3536// Both "this" expressions also have side effects.
3537TEST_P(GLSLTest_ES3, NestedArrayLengthMethodsWithSideEffects)
3538{
3539 const std::string &fragmentShader =
3540 R"(#version 300 es
3541 precision highp float;
3542 out vec4 my_FragColor;
3543 uniform int u_zero;
3544 int a;
3545 int[3] multiplyA(int multiplier)
3546 {
3547 a *= multiplier;
3548 return int[3](a, a, a);
3549 }
3550 void main()
3551 {
3552 a = u_zero + 1;
3553 int b = multiplyA(multiplyA(2).length()).length();
3554 if (b == 3 && a == 6)
3555 {
3556 my_FragColor = vec4(0, 1, 0, 1);
3557 }
3558 else
3559 {
3560 my_FragColor = vec4(1, 0, 0, 1);
3561 }
3562 })";
3563
3564 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3565 drawQuad(program.get(), "inputAttribute", 0.5f);
3566 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3567}
3568
Olli Etuaho78507c62017-10-10 15:06:45 +03003569// Test that statements inside switch() get translated to correct HLSL.
3570TEST_P(GLSLTest_ES3, DifferentStatementsInsideSwitch)
3571{
3572 const std::string &fragmentShader =
3573 R"(#version 300 es
3574
3575 precision highp float;
3576
3577 uniform int u;
3578
3579 void main()
3580 {
3581 switch (u)
3582 {
3583 case 0:
3584 ivec2 i;
3585 i.yx;
3586 }
3587 })";
3588 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3589}
3590
Olli Etuaho852fe872017-10-10 15:13:59 +03003591// Test that switch fall-through works correctly.
3592// This is a regression test for http://anglebug.com/2178
3593TEST_P(GLSLTest_ES3, SwitchFallThroughCodeDuplication)
3594{
3595 const std::string &fragmentShader =
3596 R"(#version 300 es
3597
3598 precision highp float;
3599
3600 out vec4 my_FragColor;
3601
3602 uniform int u_zero;
3603
3604 void main()
3605 {
3606 int i = 0;
3607 // switch should fall through both cases.
3608 switch(u_zero)
3609 {
3610 case 0:
3611 i += 1;
3612 case 1:
3613 i += 2;
3614 }
3615 if (i == 3)
3616 {
3617 my_FragColor = vec4(0, 1, 0, 1);
3618 }
3619 else
3620 {
3621 my_FragColor = vec4(1, 0, 0, 1);
3622 }
3623 })";
3624
3625 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3626 drawQuad(program.get(), "inputAttribute", 0.5f);
3627 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3628}
3629
Olli Etuaho923ecef2017-10-11 12:01:38 +03003630// Test that a switch statement with an empty block inside as a final statement compiles.
3631TEST_P(GLSLTest_ES3, SwitchFinalCaseHasEmptyBlock)
3632{
3633 const std::string &fragmentShader =
3634 R"(#version 300 es
3635
3636 precision mediump float;
3637 uniform int i;
3638 void main()
3639 {
3640 switch (i)
3641 {
3642 case 0:
3643 break;
3644 default:
3645 {}
3646 }
3647 })";
3648 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3649}
3650
3651// Test that a switch statement with an empty declaration inside as a final statement compiles.
3652TEST_P(GLSLTest_ES3, SwitchFinalCaseHasEmptyDeclaration)
3653{
3654 const std::string &fragmentShader =
3655 R"(#version 300 es
3656
3657 precision mediump float;
3658 uniform int i;
3659 void main()
3660 {
3661 switch (i)
3662 {
3663 case 0:
3664 break;
3665 default:
3666 float;
3667 }
3668 })";
3669 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3670}
3671
Olli Etuaho4bd730c2017-10-10 14:14:19 +03003672// Test switch/case where break/return statements are within blocks.
3673TEST_P(GLSLTest_ES3, SwitchBreakOrReturnInsideBlocks)
3674{
3675 const std::string &fragmentShader =
3676 R"(#version 300 es
3677
3678 precision highp float;
3679
3680 uniform int u_zero;
3681 out vec4 my_FragColor;
3682
3683 bool test(int n)
3684 {
3685 switch(n) {
3686 case 0:
3687 {
3688 {
3689 break;
3690 }
3691 }
3692 case 1:
3693 {
3694 return true;
3695 }
3696 case 2:
3697 {
3698 n++;
3699 }
3700 }
3701 return false;
3702 }
3703
3704 void main()
3705 {
3706 my_FragColor = test(u_zero + 1) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
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 Etuahof6d242e2017-10-12 17:21:06 +03003714// Test switch/case where a variable is declared inside one of the cases and is accessed by a
3715// subsequent case.
3716TEST_P(GLSLTest_ES3, SwitchWithVariableDeclarationInside)
3717{
3718 const std::string &fragmentShader =
3719 R"(#version 300 es
3720
3721 precision highp float;
3722 out vec4 my_FragColor;
3723
3724 uniform int u_zero;
3725
3726 void main()
3727 {
3728 my_FragColor = vec4(1, 0, 0, 1);
3729 switch (u_zero)
3730 {
3731 case 0:
3732 ivec2 i;
3733 i = ivec2(1, 0);
3734 default:
3735 my_FragColor = vec4(0, i[0], 0, 1);
3736 }
3737 })";
3738
3739 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3740 drawQuad(program.get(), "inputAttribute", 0.5f);
3741 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3742}
3743
3744// Test nested switch/case where a variable is declared inside one of the cases and is accessed by a
3745// subsequent case.
3746TEST_P(GLSLTest_ES3, NestedSwitchWithVariableDeclarationInside)
3747{
3748 const std::string &fragmentShader =
3749 R"(#version 300 es
3750
3751 precision highp float;
3752 out vec4 my_FragColor;
3753
3754 uniform int u_zero;
3755 uniform int u_zero2;
3756
3757 void main()
3758 {
3759 my_FragColor = vec4(1, 0, 0, 1);
3760 switch (u_zero)
3761 {
3762 case 0:
3763 ivec2 i;
3764 i = ivec2(1, 0);
3765 switch (u_zero2)
3766 {
3767 case 0:
3768 int j;
3769 default:
3770 j = 1;
3771 i *= j;
3772 }
3773 default:
3774 my_FragColor = vec4(0, i[0], 0, 1);
3775 }
3776 })";
3777
3778 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3779 drawQuad(program.get(), "inputAttribute", 0.5f);
3780 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3781}
3782
Olli Etuahoc1f14fb2017-10-28 19:17:23 +03003783// Test that an empty switch/case statement is translated in a way that compiles and executes the
3784// init-statement.
3785TEST_P(GLSLTest_ES3, EmptySwitch)
3786{
3787 const std::string &fragmentShader =
3788 R"(#version 300 es
3789
3790 precision highp float;
3791
3792 uniform int u_zero;
3793 out vec4 my_FragColor;
3794
3795 void main()
3796 {
3797 int i = u_zero;
3798 switch(++i) {}
3799 my_FragColor = (i == 1) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
3800 })";
3801
3802 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3803 drawQuad(program.get(), "inputAttribute", 0.5f);
3804 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3805}
3806
Olli Etuahobd3cd502017-11-03 15:48:52 +02003807// Test that a constant struct inside an expression is handled correctly.
3808TEST_P(GLSLTest_ES3, ConstStructInsideExpression)
3809{
3810 // Incorrect output color was seen on Android. http://anglebug.com/2226
3811 ANGLE_SKIP_TEST_IF(IsAndroid() && !IsNVIDIA() && IsOpenGLES());
3812
3813 const std::string &fragmentShader =
3814 R"(#version 300 es
3815
3816 precision highp float;
3817 out vec4 my_FragColor;
3818
3819 uniform float u_zero;
3820
3821 struct S
3822 {
3823 float field;
3824 };
3825
3826 void main()
3827 {
3828 const S constS = S(1.0);
3829 S nonConstS = constS;
3830 nonConstS.field = u_zero;
3831 bool fail = (constS == nonConstS);
3832 my_FragColor = vec4(0, 1, 0, 1);
3833 if (fail)
3834 {
3835 my_FragColor = vec4(1, 0, 0, 1);
3836 }
3837 })";
3838
3839 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3840 drawQuad(program.get(), "inputAttribute", 0.5f);
3841 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3842}
3843
3844// Test that a varying struct that's defined as a part of the declaration is handled correctly.
3845TEST_P(GLSLTest_ES3, VaryingStructWithInlineDefinition)
3846{
3847 const std::string &vertexShader =
3848 R"(#version 300 es
3849 in vec4 inputAttribute;
3850
3851 flat out struct S
3852 {
3853 int field;
3854 } v_s;
3855
3856 void main()
3857 {
3858 v_s.field = 1;
3859 gl_Position = inputAttribute;
3860 })";
3861
3862 const std::string &fragmentShader =
3863 R"(#version 300 es
3864
3865 precision highp float;
3866 out vec4 my_FragColor;
3867
3868 flat in struct S
3869 {
3870 int field;
3871 } v_s;
3872
3873 void main()
3874 {
3875 bool success = (v_s.field == 1);
3876 my_FragColor = vec4(1, 0, 0, 1);
3877 if (success)
3878 {
3879 my_FragColor = vec4(0, 1, 0, 1);
3880 }
3881 })";
3882
3883 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3884 drawQuad(program.get(), "inputAttribute", 0.5f);
3885 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3886}
3887
Olli Etuaho661fc482017-10-16 12:17:05 +03003888// Test vector/scalar arithmetic (in this case multiplication and addition). Meant to reproduce a
3889// bug that appeared in NVIDIA OpenGL drivers and that is worked around by
3890// VectorizeVectorScalarArithmetic AST transform.
3891TEST_P(GLSLTest, VectorScalarMultiplyAndAddInLoop)
3892{
3893 const std::string &fragmentShader =
3894 R"(
3895
3896 precision mediump float;
3897
3898 void main() {
3899 gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
3900 for (int i = 0; i < 2; i++)
3901 {
3902 gl_FragColor += (2.0 * gl_FragCoord.x);
3903 }
3904 if (gl_FragColor.g == gl_FragColor.r &&
3905 gl_FragColor.b == gl_FragColor.r &&
3906 gl_FragColor.a == gl_FragColor.r)
3907 {
3908 gl_FragColor = vec4(0, 1, 0, 1);
3909 }
3910 })";
3911
3912 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3913 drawQuad(program.get(), "inputAttribute", 0.5f);
3914 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3915}
3916
3917// Test vector/scalar arithmetic (in this case compound division and addition). Meant to reproduce a
3918// bug that appeared in NVIDIA OpenGL drivers and that is worked around by
3919// VectorizeVectorScalarArithmetic AST transform.
3920TEST_P(GLSLTest, VectorScalarDivideAndAddInLoop)
3921{
3922 const std::string &fragmentShader =
3923 R"(
3924
3925 precision mediump float;
3926
3927 void main() {
3928 gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
3929 for (int i = 0; i < 2; i++)
3930 {
3931 float x = gl_FragCoord.x;
3932 gl_FragColor = gl_FragColor + (x /= 2.0);
3933 }
3934 if (gl_FragColor.g == gl_FragColor.r &&
3935 gl_FragColor.b == gl_FragColor.r &&
3936 gl_FragColor.a == gl_FragColor.r)
3937 {
3938 gl_FragColor = vec4(0, 1, 0, 1);
3939 }
3940 })";
3941
3942 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3943 drawQuad(program.get(), "inputAttribute", 0.5f);
3944 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3945}
3946
Olli Etuahob8cb9392017-12-20 14:23:19 +02003947// Test that a varying with a flat qualifier that is used as an operand of a folded ternary operator
3948// is handled correctly.
3949TEST_P(GLSLTest_ES3, FlatVaryingUsedInFoldedTernary)
3950{
3951 const std::string &vertexShader =
3952 R"(#version 300 es
3953
3954 in vec4 inputAttribute;
3955
3956 flat out int v;
3957
3958 void main()
3959 {
3960 v = 1;
3961 gl_Position = inputAttribute;
3962 })";
3963
3964 const std::string &fragmentShader =
3965 R"(#version 300 es
3966
3967 precision highp float;
3968 out vec4 my_FragColor;
3969
3970 flat in int v;
3971
3972 void main()
3973 {
3974 my_FragColor = vec4(0, (true ? v : 0), 0, 1);
3975 })";
3976
3977 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3978 drawQuad(program.get(), "inputAttribute", 0.5f);
3979 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3980}
3981
Jiawei Shao02f15232017-12-27 10:10:28 +08003982// Verify that the link error message from last link failure is cleared when the new link is
3983// finished.
3984TEST_P(GLSLTest, ClearLinkErrorLog)
3985{
3986 const std::string &vertexShader =
3987 R"(
3988
3989 attribute vec4 vert_in;
3990 varying vec4 vert_out;
3991 void main()
3992 {
3993 gl_Position = vert_in;
3994 vert_out = vert_in;
3995 })";
3996
3997 const std::string &fragmentShader =
3998 R"(
3999
4000 precision mediump float;
4001 varying vec4 frag_in;
4002 void main()
4003 {
4004 gl_FragColor = frag_in;
4005 })";
4006
4007 GLuint vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
4008 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);
4009
4010 GLuint program = glCreateProgram();
4011
4012 // The first time the program link fails because of lack of fragment shader.
4013 glAttachShader(program, vs);
4014 glLinkProgram(program);
4015 GLint linkStatus = GL_TRUE;
4016 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
4017 ASSERT_FALSE(linkStatus);
4018
4019 const std::string &lackOfFragmentShader = QueryErrorMessage(program);
4020
4021 // The second time the program link fails because of the mismatch of the varying types.
4022 glAttachShader(program, fs);
4023 glLinkProgram(program);
4024 linkStatus = GL_TRUE;
4025 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
4026 ASSERT_FALSE(linkStatus);
4027
4028 const std::string &varyingTypeMismatch = QueryErrorMessage(program);
4029
4030 EXPECT_EQ(std::string::npos, varyingTypeMismatch.find(lackOfFragmentShader));
4031
4032 glDetachShader(program, vs);
4033 glDetachShader(program, fs);
4034 glDeleteShader(vs);
4035 glDeleteShader(fs);
4036 glDeleteProgram(program);
4037
4038 ASSERT_GL_NO_ERROR();
4039}
4040
Jiawei Shao881b7bf2017-12-25 11:18:37 +08004041// Validate error messages when the link mismatch occurs on the type of a non-struct varying.
4042TEST_P(GLSLTest, ErrorMessageOfVaryingMismatch)
4043{
4044 const std::string &vertexShader =
4045 R"(
4046
4047 attribute vec4 inputAttribute;
4048 varying vec4 vertex_out;
4049 void main()
4050 {
4051 vertex_out = inputAttribute;
4052 gl_Position = inputAttribute;
4053 })";
4054
4055 const std::string &fragmentShader =
4056 R"(
4057
4058 precision mediump float;
4059 varying float vertex_out;
4060 void main()
4061 {
4062 gl_FragColor = vec4(vertex_out, 0.0, 0.0, 1.0);
4063 })";
4064
4065 validateComponentsInErrorMessage(vertexShader, fragmentShader, "Types", "varying 'vertex_out'");
4066}
4067
4068// Validate error messages when the link mismatch occurs on the name of a varying field.
4069TEST_P(GLSLTest_ES3, ErrorMessageOfVaryingStructFieldNameMismatch)
4070{
4071 const std::string &vertexShader =
4072 R"(#version 300 es
4073
4074 in vec4 inputAttribute;
4075 struct S {
4076 float val1;
4077 vec4 val2;
4078 };
4079 out S vertex_out;
4080 void main()
4081 {
4082 vertex_out.val2 = inputAttribute;
4083 vertex_out.val1 = inputAttribute[0];
4084 gl_Position = inputAttribute;
4085 })";
4086
4087 const std::string &fragmentShader =
4088 R"(#version 300 es
4089
4090 precision mediump float;
4091 struct S {
4092 float val1;
4093 vec4 val3;
4094 };
4095 in S vertex_out;
4096 layout (location = 0) out vec4 frag_out;
4097 void main()
4098 {
4099 frag_out = vec4(vertex_out.val1, 0.0, 0.0, 1.0);
4100 })";
4101
4102 validateComponentsInErrorMessage(vertexShader, fragmentShader, "Field names",
4103 "varying 'vertex_out'");
4104}
4105
4106// Validate error messages when the link mismatch occurs on the type of a varying field.
4107TEST_P(GLSLTest_ES3, ErrorMessageOfVaryingStructFieldMismatch)
4108{
4109 const std::string &vertexShader =
4110 R"(#version 300 es
4111
4112 in vec4 inputAttribute;
4113 struct S {
4114 float val1;
4115 vec4 val2;
4116 };
4117 out S vertex_out;
4118 void main()
4119 {
4120 vertex_out.val2 = inputAttribute;
4121 vertex_out.val1 = inputAttribute[0];
4122 gl_Position = inputAttribute;
4123 })";
4124
4125 const std::string &fragmentShader =
4126 R"(#version 300 es
4127
4128 precision mediump float;
4129 struct S {
4130 float val1;
4131 vec2 val2;
4132 };
4133 in S vertex_out;
4134 layout (location = 0) out vec4 frag_out;
4135 void main()
4136 {
4137 frag_out = vec4(vertex_out.val1, 0.0, 0.0, 1.0);
4138 })";
4139
4140 validateComponentsInErrorMessage(vertexShader, fragmentShader, "Types",
4141 "varying 'vertex_out' member 'vertex_out.val2'");
4142}
4143
4144// Validate error messages when the link mismatch occurs on the name of a struct member of a uniform
4145// field.
4146TEST_P(GLSLTest, ErrorMessageOfLinkUniformStructFieldNameMismatch)
4147{
4148 const std::string &vertexShader =
4149 R"(
4150
4151 struct T
4152 {
4153 vec2 t1;
4154 vec3 t2;
4155 };
4156 struct S {
4157 T val1;
4158 vec4 val2;
4159 };
4160 uniform S uni;
4161
4162 attribute vec4 inputAttribute;
4163 varying vec4 vertex_out;
4164 void main()
4165 {
4166 vertex_out = uni.val2;
4167 gl_Position = inputAttribute;
4168 })";
4169
4170 const std::string &fragmentShader =
4171 R"(
4172
4173 precision highp float;
4174 struct T
4175 {
4176 vec2 t1;
4177 vec3 t3;
4178 };
4179 struct S {
4180 T val1;
4181 vec4 val2;
4182 };
4183 uniform S uni;
4184
4185 varying vec4 vertex_out;
4186 void main()
4187 {
4188 gl_FragColor = vec4(uni.val1.t1[0], 0.0, 0.0, 1.0);
4189 })";
4190
4191 validateComponentsInErrorMessage(vertexShader, fragmentShader, "Field names",
4192 "uniform 'uni' member 'uni.val1'");
4193}
4194
4195// Validate error messages when the link mismatch occurs on the type of a non-struct uniform block
4196// field.
4197TEST_P(GLSLTest_ES3, ErrorMessageOfLinkInterfaceBlockFieldMismatch)
4198{
4199 const std::string &vertexShader =
4200 R"(#version 300 es
4201
4202 uniform S {
4203 vec2 val1;
4204 vec4 val2;
4205 } uni;
4206
4207 in vec4 inputAttribute;
4208 out vec4 vertex_out;
4209 void main()
4210 {
4211 vertex_out = uni.val2;
4212 gl_Position = inputAttribute;
4213 })";
4214
4215 const std::string &fragmentShader =
4216 R"(#version 300 es
4217
4218 precision highp float;
4219 uniform S {
4220 vec2 val1;
4221 vec3 val2;
4222 } uni;
4223
4224 in vec4 vertex_out;
4225 layout (location = 0) out vec4 frag_out;
4226 void main()
4227 {
4228 frag_out = vec4(uni.val1[0], 0.0, 0.0, 1.0);
4229 })";
4230
4231 validateComponentsInErrorMessage(vertexShader, fragmentShader, "Types",
4232 "interface block 'S' member 'S.val2'");
4233}
4234
4235// Validate error messages when the link mismatch occurs on the type of a member of a uniform block
4236// struct field.
4237TEST_P(GLSLTest_ES3, ErrorMessageOfLinkInterfaceBlockStructFieldMismatch)
4238{
4239 const std::string &vertexShader =
4240 R"(#version 300 es
4241
4242 struct T
4243 {
4244 vec2 t1;
4245 vec3 t2;
4246 };
4247 uniform S {
4248 T val1;
4249 vec4 val2;
4250 } uni;
4251
4252 in vec4 inputAttribute;
4253 out vec4 vertex_out;
4254 void main()
4255 {
4256 vertex_out = uni.val2;
4257 gl_Position = inputAttribute;
4258 })";
4259
4260 const std::string &fragmentShader =
4261 R"(#version 300 es
4262
4263 precision highp float;
4264 struct T
4265 {
4266 vec2 t1;
4267 vec4 t2;
4268 };
4269 uniform S {
4270 T val1;
4271 vec4 val2;
4272 } uni;
4273
4274 in vec4 vertex_out;
4275 layout (location = 0) out vec4 frag_out;
4276 void main()
4277 {
4278 frag_out = vec4(uni.val1.t1[0], 0.0, 0.0, 1.0);
4279 })";
4280
4281 validateComponentsInErrorMessage(vertexShader, fragmentShader, "Types",
4282 "interface block 'S' member 'S.val1.t2'");
4283}
4284
Jamie Madillfa05f602015-05-07 13:47:11 -04004285// 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 -05004286ANGLE_INSTANTIATE_TEST(GLSLTest,
4287 ES2_D3D9(),
4288 ES2_D3D11(),
4289 ES2_D3D11_FL9_3(),
4290 ES2_OPENGL(),
4291 ES3_OPENGL(),
4292 ES2_OPENGLES(),
4293 ES3_OPENGLES());
Jamie Madillfa05f602015-05-07 13:47:11 -04004294
4295// 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 -05004296ANGLE_INSTANTIATE_TEST(GLSLTest_ES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
Jamie Madill192745a2016-12-22 15:58:21 -05004297
4298ANGLE_INSTANTIATE_TEST(WebGLGLSLTest, ES2_D3D11(), ES2_OPENGL(), ES2_OPENGLES());
Olli Etuaho9250cb22017-01-21 10:51:27 +00004299
4300ANGLE_INSTANTIATE_TEST(GLSLTest_ES31, ES31_D3D11(), ES31_OPENGL(), ES31_OPENGLES());