blob: 9066773ea56cddec531ac25a1bcbaa9addeafc06 [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 Madillfa05f602015-05-07 13:47:11 -04001300TEST_P(GLSLTest, MaxMinusTwoVaryingVec4PlusTwoSpecialVariables)
Austin Kinross8b695ee2015-03-12 13:12:20 -07001301{
1302 GLint maxVaryings = 0;
1303 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1304
1305 // Generate shader code that uses gl_FragCoord and gl_PointCoord, two special fragment shader variables.
1306 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 2, 0, true, true, false, true);
1307}
1308
Jamie Madillfa05f602015-05-07 13:47:11 -04001309TEST_P(GLSLTest, MaxMinusTwoVaryingVec4PlusThreeSpecialVariables)
Austin Kinross8b695ee2015-03-12 13:12:20 -07001310{
Geoff Lange0cc2a42016-01-20 10:58:17 -05001311 // TODO(geofflang): Figure out why this fails on OpenGL AMD (http://anglebug.com/1291)
Jamie Madill518b9fa2016-03-02 11:26:02 -05001312 if (IsAMD() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
Geoff Lange0cc2a42016-01-20 10:58:17 -05001313 {
1314 std::cout << "Test disabled on OpenGL." << std::endl;
1315 return;
1316 }
1317
Austin Kinross8b695ee2015-03-12 13:12:20 -07001318 GLint maxVaryings = 0;
1319 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1320
1321 // Generate shader code that uses gl_FragCoord, gl_PointCoord and gl_PointSize.
1322 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 2, 0, true, true, true, true);
1323}
1324
Jamie Madillfa05f602015-05-07 13:47:11 -04001325TEST_P(GLSLTest, MaxVaryingVec3)
Austin Kinrossaf875522014-08-25 21:06:07 -07001326{
1327 GLint maxVaryings = 0;
1328 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1329
Austin Kinross8b695ee2015-03-12 13:12:20 -07001330 VaryingTestBase(0, 0, 0, 0, maxVaryings, 0, 0, 0, false, false, false, true);
Austin Kinrossaf875522014-08-25 21:06:07 -07001331}
1332
Jamie Madillfa05f602015-05-07 13:47:11 -04001333TEST_P(GLSLTest, MaxVaryingVec3Array)
Austin Kinrossaf875522014-08-25 21:06:07 -07001334{
1335 GLint maxVaryings = 0;
1336 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1337
Austin Kinross8b695ee2015-03-12 13:12:20 -07001338 VaryingTestBase(0, 0, 0, 0, 0, maxVaryings / 2, 0, 0, false, false, false, true);
Austin Kinrossaf875522014-08-25 21:06:07 -07001339}
1340
Jamie Madillbee59e02014-10-02 10:44:18 -04001341// Disabled because of a failure in D3D9
Jamie Madill9fc36822015-11-18 13:08:07 -05001342TEST_P(GLSLTest, MaxVaryingVec3AndOneFloat)
Austin Kinrossaf875522014-08-25 21:06:07 -07001343{
Jamie Madill518b9fa2016-03-02 11:26:02 -05001344 if (IsD3D9())
Jamie Madill9fc36822015-11-18 13:08:07 -05001345 {
1346 std::cout << "Test disabled on D3D9." << std::endl;
1347 return;
1348 }
1349
Austin Kinrossaf875522014-08-25 21:06:07 -07001350 GLint maxVaryings = 0;
1351 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1352
Austin Kinross8b695ee2015-03-12 13:12:20 -07001353 VaryingTestBase(1, 0, 0, 0, maxVaryings, 0, 0, 0, false, false, false, true);
Austin Kinrossaf875522014-08-25 21:06:07 -07001354}
1355
Jamie Madillbee59e02014-10-02 10:44:18 -04001356// Disabled because of a failure in D3D9
Jamie Madill9fc36822015-11-18 13:08:07 -05001357TEST_P(GLSLTest, MaxVaryingVec3ArrayAndOneFloatArray)
Austin Kinrossaf875522014-08-25 21:06:07 -07001358{
Jamie Madill518b9fa2016-03-02 11:26:02 -05001359 if (IsD3D9())
Jamie Madill9fc36822015-11-18 13:08:07 -05001360 {
1361 std::cout << "Test disabled on D3D9." << std::endl;
1362 return;
1363 }
1364
Austin Kinrossaf875522014-08-25 21:06:07 -07001365 GLint maxVaryings = 0;
1366 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1367
Austin Kinross8b695ee2015-03-12 13:12:20 -07001368 VaryingTestBase(0, 1, 0, 0, 0, maxVaryings / 2, 0, 0, false, false, false, true);
Austin Kinrossaf875522014-08-25 21:06:07 -07001369}
1370
Jamie Madillbee59e02014-10-02 10:44:18 -04001371// Disabled because of a failure in D3D9
Jamie Madill9fc36822015-11-18 13:08:07 -05001372TEST_P(GLSLTest, TwiceMaxVaryingVec2)
Austin Kinrossaf875522014-08-25 21:06:07 -07001373{
Jamie Madill518b9fa2016-03-02 11:26:02 -05001374 if (IsD3D9())
Jamie Madill9fc36822015-11-18 13:08:07 -05001375 {
1376 std::cout << "Test disabled on D3D9." << std::endl;
1377 return;
1378 }
1379
Geoff Lange0cc2a42016-01-20 10:58:17 -05001380 if (getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
1381 {
1382 // TODO(geofflang): Figure out why this fails on NVIDIA's GLES driver
1383 std::cout << "Test disabled on OpenGL ES." << std::endl;
1384 return;
1385 }
1386
Geoff Lang69accbd2016-01-25 16:22:32 -05001387#if defined(__APPLE__)
1388 // TODO(geofflang): Find out why this doesn't compile on Apple AND OpenGL drivers
1389 // (http://anglebug.com/1291)
Jamie Madill518b9fa2016-03-02 11:26:02 -05001390 if (IsAMD() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
Geoff Lang69accbd2016-01-25 16:22:32 -05001391 {
1392 std::cout << "Test disabled on Apple AMD OpenGL." << std::endl;
1393 return;
1394 }
1395#endif
1396
Austin Kinrossaf875522014-08-25 21:06:07 -07001397 GLint maxVaryings = 0;
1398 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1399
Austin Kinross8b695ee2015-03-12 13:12:20 -07001400 VaryingTestBase(0, 0, 2 * maxVaryings, 0, 0, 0, 0, 0, false, false, false, true);
Austin Kinrossaf875522014-08-25 21:06:07 -07001401}
1402
Jamie Madillbee59e02014-10-02 10:44:18 -04001403// Disabled because of a failure in D3D9
Jamie Madill9fc36822015-11-18 13:08:07 -05001404TEST_P(GLSLTest, MaxVaryingVec2Arrays)
Austin Kinrossaf875522014-08-25 21:06:07 -07001405{
Jamie Madill518b9fa2016-03-02 11:26:02 -05001406 if (IsD3DSM3())
Jamie Madill9fc36822015-11-18 13:08:07 -05001407 {
1408 std::cout << "Test disabled on SM3." << std::endl;
1409 return;
1410 }
1411
Geoff Lange0cc2a42016-01-20 10:58:17 -05001412 if (getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
1413 {
1414 // TODO(geofflang): Figure out why this fails on NVIDIA's GLES driver
1415 std::cout << "Test disabled on OpenGL ES." << std::endl;
1416 return;
1417 }
1418
Geoff Lang69accbd2016-01-25 16:22:32 -05001419#if defined(__APPLE__)
1420 // TODO(geofflang): Find out why this doesn't compile on Apple AND OpenGL drivers
1421 // (http://anglebug.com/1291)
Jamie Madill518b9fa2016-03-02 11:26:02 -05001422 if (IsAMD() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
Geoff Lang69accbd2016-01-25 16:22:32 -05001423 {
1424 std::cout << "Test disabled on Apple AMD OpenGL." << std::endl;
1425 return;
1426 }
1427#endif
1428
Austin Kinrossaf875522014-08-25 21:06:07 -07001429 GLint maxVaryings = 0;
1430 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1431
Jamie Madill192745a2016-12-22 15:58:21 -05001432 // Special case: because arrays of mat2 are packed as small grids of two rows by two columns,
1433 // we should be aware that when we're packing into an odd number of varying registers the
1434 // last row will be empty and can not fit the final vec2 arrary.
1435 GLint maxVec2Arrays = (maxVaryings >> 1) << 1;
1436
1437 VaryingTestBase(0, 0, 0, maxVec2Arrays, 0, 0, 0, 0, false, false, false, true);
Austin Kinrossaf875522014-08-25 21:06:07 -07001438}
1439
Geoff Langf60fab62014-11-24 11:21:20 -05001440// Verify shader source with a fixed length that is less than the null-terminated length will compile.
Jamie Madillfa05f602015-05-07 13:47:11 -04001441TEST_P(GLSLTest, FixedShaderLength)
Geoff Langf60fab62014-11-24 11:21:20 -05001442{
1443 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1444
1445 const std::string appendGarbage = "abcasdfasdfasdfasdfasdf";
1446 const std::string source = "void main() { gl_FragColor = vec4(0, 0, 0, 0); }" + appendGarbage;
1447 const char *sourceArray[1] = { source.c_str() };
Corentin Wallez973402f2015-05-11 13:42:22 -04001448 GLint lengths[1] = { static_cast<GLint>(source.length() - appendGarbage.length()) };
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001449 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
Geoff Langf60fab62014-11-24 11:21:20 -05001450 glCompileShader(shader);
1451
1452 GLint compileResult;
1453 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1454 EXPECT_NE(compileResult, 0);
1455}
1456
1457// Verify that a negative shader source length is treated as a null-terminated length.
Jamie Madillfa05f602015-05-07 13:47:11 -04001458TEST_P(GLSLTest, NegativeShaderLength)
Geoff Langf60fab62014-11-24 11:21:20 -05001459{
1460 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1461
1462 const char *sourceArray[1] = { "void main() { gl_FragColor = vec4(0, 0, 0, 0); }" };
1463 GLint lengths[1] = { -10 };
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
Corentin Wallez9a9c0482016-04-12 10:36:25 -04001472// Check that having an invalid char after the "." doesn't cause an assert.
1473TEST_P(GLSLTest, InvalidFieldFirstChar)
1474{
1475 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
1476 const char *source = "void main() {vec4 x; x.}";
1477 glShaderSource(shader, 1, &source, 0);
1478 glCompileShader(shader);
1479
1480 GLint compileResult;
1481 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1482 EXPECT_EQ(0, compileResult);
1483}
1484
Geoff Langf60fab62014-11-24 11:21:20 -05001485// Verify that a length array with mixed positive and negative values compiles.
Jamie Madillfa05f602015-05-07 13:47:11 -04001486TEST_P(GLSLTest, MixedShaderLengths)
Geoff Langf60fab62014-11-24 11:21:20 -05001487{
1488 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1489
1490 const char *sourceArray[] =
1491 {
1492 "void main()",
1493 "{",
1494 " gl_FragColor = vec4(0, 0, 0, 0);",
1495 "}",
1496 };
1497 GLint lengths[] =
1498 {
1499 -10,
1500 1,
Corentin Wallez973402f2015-05-11 13:42:22 -04001501 static_cast<GLint>(strlen(sourceArray[2])),
Geoff Langf60fab62014-11-24 11:21:20 -05001502 -1,
1503 };
1504 ASSERT_EQ(ArraySize(sourceArray), ArraySize(lengths));
1505
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001506 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
Geoff Langf60fab62014-11-24 11:21:20 -05001507 glCompileShader(shader);
1508
1509 GLint compileResult;
1510 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1511 EXPECT_NE(compileResult, 0);
1512}
1513
1514// Verify that zero-length shader source does not affect shader compilation.
Jamie Madillfa05f602015-05-07 13:47:11 -04001515TEST_P(GLSLTest, ZeroShaderLength)
Geoff Langf60fab62014-11-24 11:21:20 -05001516{
1517 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1518
1519 const char *sourceArray[] =
1520 {
1521 "adfasdf",
1522 "34534",
1523 "void main() { gl_FragColor = vec4(0, 0, 0, 0); }",
1524 "",
1525 "asdfasdfsdsdf",
1526 };
1527 GLint lengths[] =
1528 {
1529 0,
1530 0,
1531 -1,
1532 0,
1533 0,
1534 };
1535 ASSERT_EQ(ArraySize(sourceArray), ArraySize(lengths));
1536
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001537 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
Geoff Langf60fab62014-11-24 11:21:20 -05001538 glCompileShader(shader);
1539
1540 GLint compileResult;
1541 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1542 EXPECT_NE(compileResult, 0);
1543}
Jamie Madill21c1e452014-12-29 11:33:41 -05001544
1545// Tests that bad index expressions don't crash ANGLE's translator.
1546// https://code.google.com/p/angleproject/issues/detail?id=857
Jamie Madillfa05f602015-05-07 13:47:11 -04001547TEST_P(GLSLTest, BadIndexBug)
Jamie Madill21c1e452014-12-29 11:33:41 -05001548{
1549 const std::string &fragmentShaderSourceVec =
1550 "precision mediump float;\n"
1551 "uniform vec4 uniformVec;\n"
1552 "void main()\n"
1553 "{\n"
1554 " gl_FragColor = vec4(uniformVec[int()]);\n"
1555 "}";
1556
1557 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, fragmentShaderSourceVec);
1558 EXPECT_EQ(0u, shader);
1559
1560 if (shader != 0)
1561 {
1562 glDeleteShader(shader);
1563 }
1564
1565 const std::string &fragmentShaderSourceMat =
1566 "precision mediump float;\n"
1567 "uniform mat4 uniformMat;\n"
1568 "void main()\n"
1569 "{\n"
1570 " gl_FragColor = vec4(uniformMat[int()]);\n"
1571 "}";
1572
1573 shader = CompileShader(GL_FRAGMENT_SHADER, fragmentShaderSourceMat);
1574 EXPECT_EQ(0u, shader);
1575
1576 if (shader != 0)
1577 {
1578 glDeleteShader(shader);
1579 }
1580
1581 const std::string &fragmentShaderSourceArray =
1582 "precision mediump float;\n"
1583 "uniform vec4 uniformArray;\n"
1584 "void main()\n"
1585 "{\n"
1586 " gl_FragColor = vec4(uniformArray[int()]);\n"
1587 "}";
1588
1589 shader = CompileShader(GL_FRAGMENT_SHADER, fragmentShaderSourceArray);
1590 EXPECT_EQ(0u, shader);
1591
1592 if (shader != 0)
1593 {
1594 glDeleteShader(shader);
1595 }
Jamie Madill37997142015-01-28 10:06:34 -05001596}
1597
Jamie Madill2e295e22015-04-29 10:41:33 -04001598// Test that structs defined in uniforms are translated correctly.
Jamie Madillfa05f602015-05-07 13:47:11 -04001599TEST_P(GLSLTest, StructSpecifiersUniforms)
Jamie Madill2e295e22015-04-29 10:41:33 -04001600{
Olli Etuahoa20af6d2017-09-18 13:32:29 +03001601 const std::string fragmentShaderSource =
1602 R"(precision mediump float;
Jamie Madill2e295e22015-04-29 10:41:33 -04001603
1604 uniform struct S { float field;} s;
1605
1606 void main()
1607 {
1608 gl_FragColor = vec4(1, 0, 0, 1);
1609 gl_FragColor.a += s.field;
Olli Etuahoa20af6d2017-09-18 13:32:29 +03001610 })";
Jamie Madill2e295e22015-04-29 10:41:33 -04001611
1612 GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
1613 EXPECT_NE(0u, program);
1614}
Jamie Madill55def582015-05-04 11:24:57 -04001615
1616// Test that gl_DepthRange is not stored as a uniform location. Since uniforms
1617// beginning with "gl_" are filtered out by our validation logic, we must
1618// bypass the validation to test the behaviour of the implementation.
1619// (note this test is still Impl-independent)
Jamie Madille1faacb2016-12-13 12:42:14 -05001620TEST_P(GLSLTestNoValidation, DepthRangeUniforms)
Jamie Madill55def582015-05-04 11:24:57 -04001621{
Olli Etuahoa20af6d2017-09-18 13:32:29 +03001622 const std::string fragmentShaderSource =
1623 R"(precision mediump float;
Jamie Madill55def582015-05-04 11:24:57 -04001624
1625 void main()
1626 {
1627 gl_FragColor = vec4(gl_DepthRange.near, gl_DepthRange.far, gl_DepthRange.diff, 1);
Olli Etuahoa20af6d2017-09-18 13:32:29 +03001628 })";
Jamie Madill55def582015-05-04 11:24:57 -04001629
Jamie Madille1faacb2016-12-13 12:42:14 -05001630 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShaderSource);
Jamie Madill55def582015-05-04 11:24:57 -04001631
Jamie Madille1faacb2016-12-13 12:42:14 -05001632 // We need to bypass validation for this call.
1633 GLint nearIndex = glGetUniformLocation(program.get(), "gl_DepthRange.near");
Jamie Madill55def582015-05-04 11:24:57 -04001634 EXPECT_EQ(-1, nearIndex);
1635
1636 // Test drawing does not throw an exception.
Jamie Madille1faacb2016-12-13 12:42:14 -05001637 drawQuad(program.get(), "inputAttribute", 0.5f);
Jamie Madill55def582015-05-04 11:24:57 -04001638
1639 EXPECT_GL_NO_ERROR();
Jamie Madill55def582015-05-04 11:24:57 -04001640}
Jamie Madill4052dfc2015-05-06 15:18:49 -04001641
Jamie Madill6c9503e2016-08-16 14:06:32 -04001642std::string GenerateSmallPowShader(double base, double exponent)
1643{
1644 std::stringstream stream;
1645
1646 stream.precision(8);
1647
1648 double result = pow(base, exponent);
1649
1650 stream << "precision highp float;\n"
1651 << "float fun(float arg)\n"
1652 << "{\n"
1653 << " return pow(arg, " << std::fixed << exponent << ");\n"
1654 << "}\n"
1655 << "\n"
1656 << "void main()\n"
1657 << "{\n"
1658 << " const float a = " << std::scientific << base << ";\n"
1659 << " float b = fun(a);\n"
1660 << " if (abs(" << result << " - b) < " << std::abs(result * 0.001) << ")\n"
1661 << " {\n"
1662 << " gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
1663 << " }\n"
1664 << " else\n"
1665 << " {\n"
1666 << " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
1667 << " }\n"
1668 << "}\n";
1669
1670 return stream.str();
1671}
1672
Jamie Madill4052dfc2015-05-06 15:18:49 -04001673// Covers the WebGL test 'glsl/bugs/pow-of-small-constant-in-user-defined-function'
Jamie Madill1048e432016-07-23 18:51:28 -04001674// See http://anglebug.com/851
1675TEST_P(GLSLTest, PowOfSmallConstant)
Jamie Madill4052dfc2015-05-06 15:18:49 -04001676{
Olli Etuaho629a6442017-12-11 10:55:43 +02001677 // Test with problematic exponents that are close to an integer.
1678 std::vector<double> testExponents;
1679 std::array<double, 5> epsilonMultipliers = {-100.0, -1.0, 0.0, 1.0, 100.0};
1680 for (double epsilonMultiplier : epsilonMultipliers)
Jamie Madill6c9503e2016-08-16 14:06:32 -04001681 {
1682 for (int i = -4; i <= 5; ++i)
Jamie Madill4052dfc2015-05-06 15:18:49 -04001683 {
Jamie Madill6c9503e2016-08-16 14:06:32 -04001684 if (i >= -1 && i <= 1)
1685 continue;
1686 const double epsilon = 1.0e-8;
Olli Etuaho629a6442017-12-11 10:55:43 +02001687 double bad = static_cast<double>(i) + epsilonMultiplier * epsilon;
1688 testExponents.push_back(bad);
Jamie Madill4052dfc2015-05-06 15:18:49 -04001689 }
Jamie Madill6c9503e2016-08-16 14:06:32 -04001690 }
Jamie Madill4052dfc2015-05-06 15:18:49 -04001691
Olli Etuaho629a6442017-12-11 10:55:43 +02001692 // Also test with a few exponents that are not close to an integer.
1693 testExponents.push_back(3.6);
1694 testExponents.push_back(3.4);
1695
1696 for (double testExponent : testExponents)
Jamie Madill6c9503e2016-08-16 14:06:32 -04001697 {
Olli Etuaho629a6442017-12-11 10:55:43 +02001698 const std::string &fragmentShaderSource = GenerateSmallPowShader(1.0e-6, testExponent);
Jamie Madill4052dfc2015-05-06 15:18:49 -04001699
Jamie Madill6c9503e2016-08-16 14:06:32 -04001700 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShaderSource);
Jamie Madill4052dfc2015-05-06 15:18:49 -04001701
Jamie Madill6c9503e2016-08-16 14:06:32 -04001702 drawQuad(program.get(), "inputAttribute", 0.5f);
1703
1704 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1705 EXPECT_GL_NO_ERROR();
1706 }
Jamie Madill4052dfc2015-05-06 15:18:49 -04001707}
Jamie Madillfa05f602015-05-07 13:47:11 -04001708
Cooper Partina5ef8d82015-08-19 14:52:21 -07001709// Test that fragment shaders which contain non-constant loop indexers and compiled for FL9_3 and
1710// below
1711// fail with a specific error message.
1712// Additionally test that the same fragment shader compiles successfully with feature levels greater
1713// than FL9_3.
1714TEST_P(GLSLTest, LoopIndexingValidation)
1715{
Olli Etuahoa20af6d2017-09-18 13:32:29 +03001716 const std::string fragmentShaderSource =
1717 R"(precision mediump float;
Cooper Partina5ef8d82015-08-19 14:52:21 -07001718
1719 uniform float loopMax;
1720
1721 void main()
1722 {
1723 gl_FragColor = vec4(1, 0, 0, 1);
1724 for (float l = 0.0; l < loopMax; l++)
1725 {
1726 if (loopMax > 3.0)
1727 {
1728 gl_FragColor.a += 0.1;
1729 }
1730 }
Olli Etuahoa20af6d2017-09-18 13:32:29 +03001731 })";
Cooper Partina5ef8d82015-08-19 14:52:21 -07001732
1733 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1734
1735 const char *sourceArray[1] = {fragmentShaderSource.c_str()};
1736 glShaderSource(shader, 1, sourceArray, nullptr);
1737 glCompileShader(shader);
1738
1739 GLint compileResult;
1740 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1741
1742 // If the test is configured to run limited to Feature Level 9_3, then it is
1743 // assumed that shader compilation will fail with an expected error message containing
1744 // "Loop index cannot be compared with non-constant expression"
Olli Etuaho814a54d2015-08-27 16:23:09 +03001745 if ((GetParam() == ES2_D3D11_FL9_3() || GetParam() == ES2_D3D9()))
Cooper Partina5ef8d82015-08-19 14:52:21 -07001746 {
1747 if (compileResult != 0)
1748 {
1749 FAIL() << "Shader compilation succeeded, expected failure";
1750 }
1751 else
1752 {
1753 GLint infoLogLength;
1754 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
1755
1756 std::string infoLog;
1757 infoLog.resize(infoLogLength);
Yunchao Hef81ce4a2017-04-24 10:49:17 +08001758 glGetShaderInfoLog(shader, static_cast<GLsizei>(infoLog.size()), nullptr, &infoLog[0]);
Cooper Partina5ef8d82015-08-19 14:52:21 -07001759
1760 if (infoLog.find("Loop index cannot be compared with non-constant expression") ==
1761 std::string::npos)
1762 {
1763 FAIL() << "Shader compilation failed with unexpected error message";
1764 }
1765 }
1766 }
1767 else
1768 {
1769 EXPECT_NE(0, compileResult);
1770 }
1771
1772 if (shader != 0)
1773 {
1774 glDeleteShader(shader);
1775 }
1776}
1777
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001778// Tests that the maximum uniforms count returned from querying GL_MAX_VERTEX_UNIFORM_VECTORS
1779// can actually be used.
1780TEST_P(GLSLTest, VerifyMaxVertexUniformVectors)
1781{
Zhenyao Mo1a256722017-01-12 11:52:57 -08001782 if (IsLinux() && IsIntel())
1783 {
1784 std::cout << "Test timed out on Linux Intel. See crbug.com/680631." << std::endl;
1785 return;
1786 }
1787
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001788 int maxUniforms = 10000;
1789 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
1790 EXPECT_GL_NO_ERROR();
1791 std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS = " << maxUniforms << std::endl;
1792
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001793 CompileGLSLWithUniformsAndSamplers(maxUniforms, 0, 0, 0, true);
1794}
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001795
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001796// Tests that the maximum uniforms count returned from querying GL_MAX_VERTEX_UNIFORM_VECTORS
1797// can actually be used along with the maximum number of texture samplers.
1798TEST_P(GLSLTest, VerifyMaxVertexUniformVectorsWithSamplers)
1799{
Geoff Lange0cc2a42016-01-20 10:58:17 -05001800 if (GetParam().eglParameters.renderer == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE ||
1801 GetParam().eglParameters.renderer == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
1802 {
1803 std::cout << "Test disabled on OpenGL." << std::endl;
1804 return;
1805 }
1806
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001807 int maxUniforms = 10000;
1808 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
1809 EXPECT_GL_NO_ERROR();
1810 std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS = " << maxUniforms << std::endl;
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001811
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001812 int maxTextureImageUnits = 0;
1813 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001814
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001815 CompileGLSLWithUniformsAndSamplers(maxUniforms, 0, maxTextureImageUnits, 0, true);
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001816}
1817
1818// Tests that the maximum uniforms count + 1 from querying GL_MAX_VERTEX_UNIFORM_VECTORS
1819// fails shader compilation.
1820TEST_P(GLSLTest, VerifyMaxVertexUniformVectorsExceeded)
1821{
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001822 int maxUniforms = 10000;
1823 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
1824 EXPECT_GL_NO_ERROR();
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001825 std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS + 1 = " << maxUniforms + 1 << std::endl;
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001826
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001827 CompileGLSLWithUniformsAndSamplers(maxUniforms + 1, 0, 0, 0, false);
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001828}
1829
1830// Tests that the maximum uniforms count returned from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
1831// can actually be used.
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001832TEST_P(GLSLTest, VerifyMaxFragmentUniformVectors)
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001833{
Zhenyao Mo1a256722017-01-12 11:52:57 -08001834 if (IsLinux() && IsIntel())
1835 {
1836 std::cout << "Test timed out on Linux Intel. See crbug.com/680631." << std::endl;
1837 return;
1838 }
1839
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001840 int maxUniforms = 10000;
1841 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
1842 EXPECT_GL_NO_ERROR();
1843 std::cout << "Validating GL_MAX_FRAGMENT_UNIFORM_VECTORS = " << maxUniforms << std::endl;
1844
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001845 CompileGLSLWithUniformsAndSamplers(0, maxUniforms, 0, 0, true);
1846}
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001847
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001848// Tests that the maximum uniforms count returned from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
1849// can actually be used along with the maximum number of texture samplers.
1850TEST_P(GLSLTest, VerifyMaxFragmentUniformVectorsWithSamplers)
1851{
Geoff Lange0cc2a42016-01-20 10:58:17 -05001852 if (GetParam().eglParameters.renderer == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE ||
1853 GetParam().eglParameters.renderer == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
1854 {
1855 std::cout << "Test disabled on OpenGL." << std::endl;
1856 return;
1857 }
1858
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001859 int maxUniforms = 10000;
1860 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
1861 EXPECT_GL_NO_ERROR();
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001862
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001863 int maxTextureImageUnits = 0;
1864 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001865
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001866 CompileGLSLWithUniformsAndSamplers(0, maxUniforms, 0, maxTextureImageUnits, true);
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001867}
1868
1869// Tests that the maximum uniforms count + 1 from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
1870// fails shader compilation.
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001871TEST_P(GLSLTest, VerifyMaxFragmentUniformVectorsExceeded)
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001872{
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001873 int maxUniforms = 10000;
1874 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
1875 EXPECT_GL_NO_ERROR();
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001876 std::cout << "Validating GL_MAX_FRAGMENT_UNIFORM_VECTORS + 1 = " << maxUniforms + 1
1877 << std::endl;
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001878
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001879 CompileGLSLWithUniformsAndSamplers(0, maxUniforms + 1, 0, 0, false);
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001880}
1881
Geoff Langba992ab2017-04-19 11:18:14 -04001882// Test compiling shaders using the GL_EXT_shader_texture_lod extension
1883TEST_P(GLSLTest, TextureLOD)
1884{
1885 if (!extensionEnabled("GL_EXT_shader_texture_lod"))
1886 {
1887 std::cout << "Test skipped due to missing GL_EXT_shader_texture_lod." << std::endl;
1888 return;
1889 }
1890
1891 const std::string source =
1892 "#extension GL_EXT_shader_texture_lod : require\n"
1893 "uniform sampler2D u_texture;\n"
1894 "void main() {\n"
1895 " gl_FragColor = texture2DGradEXT(u_texture, vec2(0.0, 0.0), vec2(0.0, 0.0), vec2(0.0, "
1896 "0.0));\n"
1897 "}\n";
1898
1899 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, source);
1900 ASSERT_NE(0u, shader);
1901 glDeleteShader(shader);
1902}
1903
Olli Etuahobe59c2f2016-03-07 11:32:34 +02001904// Test that two constructors which have vec4 and mat2 parameters get disambiguated (issue in
1905// HLSL).
1906TEST_P(GLSLTest_ES3, AmbiguousConstructorCall2x2)
1907{
1908 const std::string fragmentShaderSource =
1909 "#version 300 es\n"
1910 "precision highp float;\n"
1911 "out vec4 my_FragColor;\n"
1912 "void main()\n"
1913 "{\n"
1914 " my_FragColor = vec4(0.0);\n"
1915 "}";
1916
1917 const std::string vertexShaderSource =
1918 "#version 300 es\n"
1919 "precision highp float;\n"
1920 "in vec4 a_vec;\n"
1921 "in mat2 a_mat;\n"
1922 "void main()\n"
1923 "{\n"
1924 " gl_Position = vec4(a_vec) + vec4(a_mat);\n"
1925 "}";
1926
1927 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1928 EXPECT_NE(0u, program);
1929}
1930
1931// Test that two constructors which have mat2x3 and mat3x2 parameters get disambiguated.
1932// This was suspected to be an issue in HLSL, but HLSL seems to be able to natively choose between
1933// the function signatures in this case.
1934TEST_P(GLSLTest_ES3, AmbiguousConstructorCall2x3)
1935{
1936 const std::string fragmentShaderSource =
1937 "#version 300 es\n"
1938 "precision highp float;\n"
1939 "out vec4 my_FragColor;\n"
1940 "void main()\n"
1941 "{\n"
1942 " my_FragColor = vec4(0.0);\n"
1943 "}";
1944
1945 const std::string vertexShaderSource =
1946 "#version 300 es\n"
1947 "precision highp float;\n"
1948 "in mat3x2 a_matA;\n"
1949 "in mat2x3 a_matB;\n"
1950 "void main()\n"
1951 "{\n"
1952 " gl_Position = vec4(a_matA) + vec4(a_matB);\n"
1953 "}";
1954
1955 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1956 EXPECT_NE(0u, program);
1957}
1958
1959// Test that two functions which have vec4 and mat2 parameters get disambiguated (issue in HLSL).
1960TEST_P(GLSLTest_ES3, AmbiguousFunctionCall2x2)
1961{
1962 const std::string fragmentShaderSource =
1963 "#version 300 es\n"
1964 "precision highp float;\n"
1965 "out vec4 my_FragColor;\n"
1966 "void main()\n"
1967 "{\n"
1968 " my_FragColor = vec4(0.0);\n"
1969 "}";
1970
1971 const std::string vertexShaderSource =
1972 "#version 300 es\n"
1973 "precision highp float;\n"
1974 "in vec4 a_vec;\n"
1975 "in mat2 a_mat;\n"
1976 "vec4 foo(vec4 a)\n"
1977 "{\n"
1978 " return a;\n"
1979 "}\n"
1980 "vec4 foo(mat2 a)\n"
1981 "{\n"
1982 " return vec4(a[0][0]);\n"
1983 "}\n"
1984 "void main()\n"
1985 "{\n"
1986 " gl_Position = foo(a_vec) + foo(a_mat);\n"
1987 "}";
1988
1989 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1990 EXPECT_NE(0u, program);
1991}
1992
1993// Test that an user-defined function with a large number of float4 parameters doesn't fail due to
1994// the function name being too long.
1995TEST_P(GLSLTest_ES3, LargeNumberOfFloat4Parameters)
1996{
1997 const std::string fragmentShaderSource =
1998 "#version 300 es\n"
1999 "precision highp float;\n"
2000 "out vec4 my_FragColor;\n"
2001 "void main()\n"
2002 "{\n"
2003 " my_FragColor = vec4(0.0);\n"
2004 "}";
2005
2006 std::stringstream vertexShaderStream;
2007 const unsigned int paramCount = 1024u;
2008
2009 vertexShaderStream << "#version 300 es\n"
2010 "precision highp float;\n"
2011 "in vec4 a_vec;\n"
2012 "vec4 lotsOfVec4Parameters(";
2013 for (unsigned int i = 0; i < paramCount; ++i)
2014 {
2015 vertexShaderStream << "vec4 a" << i << ", ";
2016 }
2017 vertexShaderStream << "vec4 aLast)\n"
2018 "{\n"
2019 " return ";
2020 for (unsigned int i = 0; i < paramCount; ++i)
2021 {
2022 vertexShaderStream << "a" << i << " + ";
2023 }
2024 vertexShaderStream << "aLast;\n"
2025 "}\n"
2026 "void main()\n"
2027 "{\n"
2028 " gl_Position = lotsOfVec4Parameters(";
2029 for (unsigned int i = 0; i < paramCount; ++i)
2030 {
2031 vertexShaderStream << "a_vec, ";
2032 }
2033 vertexShaderStream << "a_vec);\n"
2034 "}";
2035
2036 GLuint program = CompileProgram(vertexShaderStream.str(), fragmentShaderSource);
2037 EXPECT_NE(0u, program);
2038}
2039
Olli Etuahod4f4c112016-04-15 15:11:24 +03002040// This test was written specifically to stress DeferGlobalInitializers AST transformation.
2041// Test a shader where a global constant array is initialized with an expression containing array
2042// indexing. This initializer is tricky to constant fold, so if it's not constant folded it needs to
2043// be handled in a way that doesn't generate statements in the global scope in HLSL output.
2044// Also includes multiple array initializers in one declaration, where only the second one has
2045// array indexing. This makes sure that the qualifier for the declaration is set correctly if
2046// transformations are applied to the declaration also in the case of ESSL output.
2047TEST_P(GLSLTest_ES3, InitGlobalArrayWithArrayIndexing)
2048{
Yuly Novikov41db2242016-06-25 00:14:28 -04002049 // TODO(ynovikov): re-enable once root cause of http://anglebug.com/1428 is fixed
2050 if (IsAndroid() && IsAdreno() && IsOpenGLES())
2051 {
2052 std::cout << "Test skipped on Adreno OpenGLES on Android." << std::endl;
2053 return;
2054 }
2055
Olli Etuahod4f4c112016-04-15 15:11:24 +03002056 const std::string vertexShaderSource =
2057 "#version 300 es\n"
2058 "precision highp float;\n"
2059 "in vec4 a_vec;\n"
2060 "void main()\n"
2061 "{\n"
2062 " gl_Position = vec4(a_vec);\n"
2063 "}";
2064
2065 const std::string fragmentShaderSource =
2066 "#version 300 es\n"
2067 "precision highp float;\n"
2068 "out vec4 my_FragColor;\n"
2069 "const highp float f[2] = float[2](0.1, 0.2);\n"
2070 "const highp float[2] g = float[2](0.3, 0.4), h = float[2](0.5, f[1]);\n"
2071 "void main()\n"
2072 "{\n"
2073 " my_FragColor = vec4(h[1]);\n"
2074 "}";
2075
2076 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
2077 EXPECT_NE(0u, program);
2078}
2079
Corentin Wallez419bfc92016-06-28 10:54:45 -07002080// Test that index-constant sampler array indexing is supported.
2081TEST_P(GLSLTest, IndexConstantSamplerArrayIndexing)
2082{
2083 if (IsD3D11_FL93()) {
2084 std::cout << "Test skipped on D3D11 FL 9.3." << std::endl;
2085 return;
2086 }
2087
2088 const std::string vertexShaderSource =
2089 "attribute vec4 vPosition;\n"
2090 "void main()\n"
2091 "{\n"
2092 " gl_Position = vPosition;\n"
2093 "}";
2094
2095 const std::string fragmentShaderSource =
2096 "precision mediump float;\n"
2097 "uniform sampler2D uni[2];\n"
2098 "\n"
2099 "float zero(int x)\n"
2100 "{\n"
2101 " return float(x) - float(x);\n"
2102 "}\n"
2103 "\n"
2104 "void main()\n"
2105 "{\n"
2106 " vec4 c = vec4(0,0,0,0);\n"
2107 " for (int ii = 1; ii < 3; ++ii) {\n"
2108 " if (c.x > 255.0) {\n"
2109 " c.x = 255.0 + zero(ii);\n"
2110 " break;\n"
2111 " }\n"
2112 // Index the sampler array with a predictable loop index (index-constant) as opposed to
2113 // a true constant. This is valid in OpenGL ES but isn't in many Desktop OpenGL versions,
2114 // without an extension.
2115 " c += texture2D(uni[ii - 1], vec2(0.5, 0.5));\n"
2116 " }\n"
2117 " gl_FragColor = c;\n"
2118 "}";
2119
2120 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
2121 EXPECT_NE(0u, program);
2122}
2123
Corentin Wallezb00dcee2016-07-11 17:42:58 -04002124// Test that the #pragma directive is supported and doesn't trigger a compilation failure on the
2125// native driver. The only pragma that gets passed to the OpenGL driver is "invariant" but we don't
2126// want to test its behavior, so don't use any varyings.
2127TEST_P(GLSLTest, PragmaDirective)
2128{
2129 const std::string vertexShaderSource =
2130 "#pragma STDGL invariant(all)\n"
2131 "void main()\n"
2132 "{\n"
2133 " gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
2134 "}\n";
2135
2136 const std::string fragmentShaderSource =
2137 "precision mediump float;\n"
2138 "void main()\n"
2139 "{\n"
2140 " gl_FragColor = vec4(1.0);\n"
2141 "}\n";
2142
2143 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
2144 EXPECT_NE(0u, program);
2145}
2146
Olli Etuahoe1d199b2016-07-19 17:14:27 +03002147// Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
2148// The function call that returns the array needs to be evaluated after ++j for the expression to
2149// return the correct value (true).
2150TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderArray)
2151{
2152 const std::string &fragmentShaderSource =
2153 "#version 300 es\n"
2154 "precision mediump float;\n"
2155 "out vec4 my_FragColor; \n"
2156 "int[2] func(int param) {\n"
2157 " return int[2](param, param);\n"
2158 "}\n"
2159 "void main() {\n"
2160 " int a[2]; \n"
2161 " for (int i = 0; i < 2; ++i) {\n"
2162 " a[i] = 1;\n"
2163 " }\n"
2164 " int j = 0; \n"
2165 " bool result = ((++j), (a == func(j)));\n"
2166 " my_FragColor = vec4(0.0, (result ? 1.0 : 0.0), 0.0, 1.0);\n"
2167 "}\n";
2168
2169 GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
2170 ASSERT_NE(0u, program);
2171
2172 drawQuad(program, "inputAttribute", 0.5f);
2173
2174 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2175}
2176
2177// Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
2178// The short-circuiting expression needs to be evaluated after ++j for the expression to return the
2179// correct value (true).
2180TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderShortCircuit)
2181{
2182 const std::string &fragmentShaderSource =
2183 "#version 300 es\n"
2184 "precision mediump float;\n"
2185 "out vec4 my_FragColor; \n"
2186 "void main() {\n"
2187 " int j = 0; \n"
2188 " bool result = ((++j), (j == 1 ? true : (++j == 3)));\n"
2189 " my_FragColor = vec4(0.0, ((result && j == 1) ? 1.0 : 0.0), 0.0, 1.0);\n"
2190 "}\n";
2191
2192 GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
2193 ASSERT_NE(0u, program);
2194
2195 drawQuad(program, "inputAttribute", 0.5f);
2196
2197 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2198}
2199
Jamie Madill666f65a2016-08-26 01:34:37 +00002200// Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
2201// Indexing the vector needs to be evaluated after func() for the right result.
2202TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderDynamicVectorIndexingInLValue)
2203{
2204 const std::string &fragmentShaderSource =
2205 "#version 300 es\n"
2206 "precision mediump float;\n"
2207 "out vec4 my_FragColor;\n"
2208 "uniform int u_zero;\n"
2209 "int sideEffectCount = 0;\n"
2210 "float func() {\n"
2211 " ++sideEffectCount;\n"
2212 " return -1.0;\n"
2213 "}\n"
2214 "void main() {\n"
2215 " vec4 v = vec4(0.0, 2.0, 4.0, 6.0); \n"
2216 " float f = (func(), (++v[u_zero + sideEffectCount]));\n"
2217 " bool green = abs(f - 3.0) < 0.01 && abs(v[1] - 3.0) < 0.01 && sideEffectCount == 1;\n"
2218 " my_FragColor = vec4(0.0, (green ? 1.0 : 0.0), 0.0, 1.0);\n"
2219 "}\n";
2220
2221 GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
2222 ASSERT_NE(0u, program);
2223
2224 drawQuad(program, "inputAttribute", 0.5f);
2225
2226 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2227}
2228
Jamie Madillc9bde922016-07-24 17:58:50 -04002229// Test that using gl_PointCoord with GL_TRIANGLES doesn't produce a link error.
2230// From WebGL test conformance/rendering/point-specific-shader-variables.html
2231// See http://anglebug.com/1380
2232TEST_P(GLSLTest, RenderTrisWithPointCoord)
2233{
2234 const std::string &vert =
2235 "attribute vec2 aPosition;\n"
2236 "void main()\n"
2237 "{\n"
2238 " gl_Position = vec4(aPosition, 0, 1);\n"
2239 " gl_PointSize = 1.0;\n"
2240 "}";
2241 const std::string &frag =
2242 "void main()\n"
2243 "{\n"
2244 " gl_FragColor = vec4(gl_PointCoord.xy, 0, 1);\n"
2245 " gl_FragColor = vec4(0, 1, 0, 1);\n"
2246 "}";
2247
2248 ANGLE_GL_PROGRAM(prog, vert, frag);
2249 drawQuad(prog.get(), "aPosition", 0.5f);
2250 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2251}
2252
Jamie Madill5655b842016-08-02 11:00:07 -04002253// Convers a bug with the integer pow statement workaround.
2254TEST_P(GLSLTest, NestedPowStatements)
2255{
2256 const std::string &vert =
2257 "attribute vec2 position;\n"
2258 "void main()\n"
2259 "{\n"
2260 " gl_Position = vec4(position, 0, 1);\n"
2261 "}";
2262 const std::string &frag =
2263 "precision mediump float;\n"
2264 "float func(float v)\n"
2265 "{\n"
2266 " float f1 = pow(v, 2.0);\n"
2267 " return pow(f1 + v, 2.0);\n"
2268 "}\n"
2269 "void main()\n"
2270 "{\n"
2271 " float v = func(2.0);\n"
2272 " gl_FragColor = abs(v - 36.0) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
2273 "}";
2274
2275 ANGLE_GL_PROGRAM(prog, vert, frag);
2276 drawQuad(prog.get(), "position", 0.5f);
2277 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2278}
2279
Qiankun Miaof52fe932016-12-07 13:39:15 +08002280// Test that -float calculation is correct.
2281TEST_P(GLSLTest_ES3, UnaryMinusOperatorFloat)
2282{
Qiankun Miaof52fe932016-12-07 13:39:15 +08002283 const std::string &vert =
2284 "#version 300 es\n"
2285 "in highp vec4 position;\n"
2286 "void main() {\n"
2287 " gl_Position = position;\n"
2288 "}\n";
2289 const std::string &frag =
2290 "#version 300 es\n"
2291 "out highp vec4 o_color;\n"
2292 "void main() {\n"
2293 " highp float f = -1.0;\n"
2294 " // atan(tan(0.5), -f) should be 0.5.\n"
2295 " highp float v = atan(tan(0.5), -f);\n"
2296 " o_color = abs(v - 0.5) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
2297 "}\n";
2298
2299 ANGLE_GL_PROGRAM(prog, vert, frag);
2300 drawQuad(prog.get(), "position", 0.5f);
2301 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2302}
2303
Olli Etuahoda9fb092016-12-09 17:32:29 +00002304// Test that atan(vec2, vec2) calculation is correct.
2305TEST_P(GLSLTest_ES3, AtanVec2)
2306{
2307 const std::string &vert =
2308 "#version 300 es\n"
2309 "in highp vec4 position;\n"
2310 "void main() {\n"
2311 " gl_Position = position;\n"
2312 "}\n";
2313 const std::string &frag =
2314 "#version 300 es\n"
2315 "out highp vec4 o_color;\n"
2316 "void main() {\n"
2317 " highp float f = 1.0;\n"
2318 " // atan(tan(0.5), f) should be 0.5.\n"
2319 " highp vec2 v = atan(vec2(tan(0.5)), vec2(f));\n"
2320 " o_color = (abs(v[0] - 0.5) < 0.001 && abs(v[1] - 0.5) < 0.001) ? vec4(0, 1, 0, 1) : "
2321 "vec4(1, 0, 0, 1);\n"
2322 "}\n";
2323
2324 ANGLE_GL_PROGRAM(prog, vert, frag);
2325 drawQuad(prog.get(), "position", 0.5f);
2326 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2327}
2328
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002329// Convers a bug with the unary minus operator on signed integer workaround.
2330TEST_P(GLSLTest_ES3, UnaryMinusOperatorSignedInt)
2331{
2332 const std::string &vert =
2333 "#version 300 es\n"
2334 "in highp vec4 position;\n"
2335 "out mediump vec4 v_color;\n"
2336 "uniform int ui_one;\n"
2337 "uniform int ui_two;\n"
2338 "uniform int ui_three;\n"
2339 "void main() {\n"
2340 " int s[3];\n"
2341 " s[0] = ui_one;\n"
2342 " s[1] = -(-(-ui_two + 1) + 1);\n" // s[1] = -ui_two
2343 " s[2] = ui_three;\n"
2344 " int result = 0;\n"
2345 " for (int i = 0; i < ui_three; i++) {\n"
2346 " result += s[i];\n"
2347 " }\n"
2348 " v_color = (result == 2) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
2349 " gl_Position = position;\n"
2350 "}\n";
2351 const std::string &frag =
2352 "#version 300 es\n"
2353 "in mediump vec4 v_color;\n"
2354 "layout(location=0) out mediump vec4 o_color;\n"
2355 "void main() {\n"
2356 " o_color = v_color;\n"
2357 "}\n";
2358
2359 ANGLE_GL_PROGRAM(prog, vert, frag);
2360
Jamie Madille1faacb2016-12-13 12:42:14 -05002361 GLint oneIndex = glGetUniformLocation(prog.get(), "ui_one");
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002362 ASSERT_NE(-1, oneIndex);
Jamie Madille1faacb2016-12-13 12:42:14 -05002363 GLint twoIndex = glGetUniformLocation(prog.get(), "ui_two");
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002364 ASSERT_NE(-1, twoIndex);
Jamie Madille1faacb2016-12-13 12:42:14 -05002365 GLint threeIndex = glGetUniformLocation(prog.get(), "ui_three");
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002366 ASSERT_NE(-1, threeIndex);
2367 glUseProgram(prog.get());
2368 glUniform1i(oneIndex, 1);
2369 glUniform1i(twoIndex, 2);
2370 glUniform1i(threeIndex, 3);
2371
2372 drawQuad(prog.get(), "position", 0.5f);
2373 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2374}
2375
2376// Convers a bug with the unary minus operator on unsigned integer workaround.
2377TEST_P(GLSLTest_ES3, UnaryMinusOperatorUnsignedInt)
2378{
2379 const std::string &vert =
2380 "#version 300 es\n"
2381 "in highp vec4 position;\n"
2382 "out mediump vec4 v_color;\n"
2383 "uniform uint ui_one;\n"
2384 "uniform uint ui_two;\n"
2385 "uniform uint ui_three;\n"
2386 "void main() {\n"
2387 " uint s[3];\n"
2388 " s[0] = ui_one;\n"
2389 " s[1] = -(-(-ui_two + 1u) + 1u);\n" // s[1] = -ui_two
2390 " s[2] = ui_three;\n"
2391 " uint result = 0u;\n"
2392 " for (uint i = 0u; i < ui_three; i++) {\n"
2393 " result += s[i];\n"
2394 " }\n"
2395 " v_color = (result == 2u) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
2396 " gl_Position = position;\n"
2397 "}\n";
2398 const std::string &frag =
2399 "#version 300 es\n"
2400 "in mediump vec4 v_color;\n"
2401 "layout(location=0) out mediump vec4 o_color;\n"
2402 "void main() {\n"
2403 " o_color = v_color;\n"
2404 "}\n";
2405
2406 ANGLE_GL_PROGRAM(prog, vert, frag);
2407
Jamie Madille1faacb2016-12-13 12:42:14 -05002408 GLint oneIndex = glGetUniformLocation(prog.get(), "ui_one");
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002409 ASSERT_NE(-1, oneIndex);
Jamie Madille1faacb2016-12-13 12:42:14 -05002410 GLint twoIndex = glGetUniformLocation(prog.get(), "ui_two");
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002411 ASSERT_NE(-1, twoIndex);
Jamie Madille1faacb2016-12-13 12:42:14 -05002412 GLint threeIndex = glGetUniformLocation(prog.get(), "ui_three");
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002413 ASSERT_NE(-1, threeIndex);
2414 glUseProgram(prog.get());
2415 glUniform1ui(oneIndex, 1u);
2416 glUniform1ui(twoIndex, 2u);
2417 glUniform1ui(threeIndex, 3u);
2418
2419 drawQuad(prog.get(), "position", 0.5f);
2420 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2421}
2422
Olli Etuahoab481642016-08-26 12:09:10 +03002423// Test a nested sequence operator with a ternary operator inside. The ternary operator is
2424// intended to be such that it gets converted to an if statement on the HLSL backend.
2425TEST_P(GLSLTest, NestedSequenceOperatorWithTernaryInside)
2426{
2427 const std::string &vert =
2428 "attribute vec2 position;\n"
2429 "void main()\n"
2430 "{\n"
2431 " gl_Position = vec4(position, 0, 1);\n"
2432 "}";
2433
2434 // Note that the uniform keep_flop_positive doesn't need to be set - the test expects it to have
2435 // its default value false.
2436 const std::string &frag =
2437 "precision mediump float;\n"
2438 "uniform bool keep_flop_positive;\n"
2439 "float flop;\n"
2440 "void main() {\n"
2441 " flop = -1.0,\n"
2442 " (flop *= -1.0,\n"
2443 " keep_flop_positive ? 0.0 : flop *= -1.0),\n"
2444 " gl_FragColor = vec4(0, -flop, 0, 1);\n"
2445 "}";
2446
2447 ANGLE_GL_PROGRAM(prog, vert, frag);
2448 drawQuad(prog.get(), "position", 0.5f);
2449 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2450}
2451
Geoff Lang28a97ee2016-09-22 13:01:26 -04002452// Test that using a sampler2D and samplerExternalOES in the same shader works (anglebug.com/1534)
2453TEST_P(GLSLTest, ExternalAnd2DSampler)
2454{
2455 if (!extensionEnabled("GL_OES_EGL_image_external"))
2456 {
2457 std::cout << "Test skipped because GL_OES_EGL_image_external is not available."
2458 << std::endl;
2459 return;
2460 }
2461
2462 const std::string fragmentShader =
Olli Etuaho703671e2017-11-08 17:47:18 +02002463 R"(
2464 #extension GL_OES_EGL_image_external : enable
2465 precision mediump float;
2466 uniform samplerExternalOES tex0;
2467 uniform sampler2D tex1;
2468 void main(void)
2469 {
2470 vec2 uv = vec2(0.0, 0.0);
2471 gl_FragColor = texture2D(tex0, uv) + texture2D(tex1, uv);
2472 })";
Geoff Lang28a97ee2016-09-22 13:01:26 -04002473
2474 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2475}
2476
Olli Etuaho56a2f952016-12-08 12:16:27 +00002477// Test that literal infinity can be written out from the shader translator.
2478// A similar test can't be made for NaNs, since ESSL 3.00.6 requirements for NaNs are very loose.
2479TEST_P(GLSLTest_ES3, LiteralInfinityOutput)
2480{
2481 const std::string &fragmentShader =
2482 "#version 300 es\n"
2483 "precision highp float;\n"
2484 "out vec4 out_color;\n"
2485 "uniform float u;\n"
2486 "void main()\n"
2487 "{\n"
2488 " float infVar = 1.0e40 - u;\n"
2489 " bool correct = isinf(infVar) && infVar > 0.0;\n"
2490 " out_color = correct ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
2491 "}\n";
2492
2493 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2494 drawQuad(program.get(), "inputAttribute", 0.5f);
2495 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2496}
2497
2498// Test that literal negative infinity can be written out from the shader translator.
2499// A similar test can't be made for NaNs, since ESSL 3.00.6 requirements for NaNs are very loose.
2500TEST_P(GLSLTest_ES3, LiteralNegativeInfinityOutput)
2501{
2502 const std::string &fragmentShader =
2503 "#version 300 es\n"
2504 "precision highp float;\n"
2505 "out vec4 out_color;\n"
2506 "uniform float u;\n"
2507 "void main()\n"
2508 "{\n"
2509 " float infVar = -1.0e40 + u;\n"
2510 " bool correct = isinf(infVar) && infVar < 0.0;\n"
2511 " out_color = correct ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
2512 "}\n";
2513
2514 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2515 drawQuad(program.get(), "inputAttribute", 0.5f);
2516 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2517}
2518
Corentin Wallez36fd1002016-12-08 11:30:44 -05002519// The following MultipleDeclaration* tests are testing TranslatorHLSL specific simplification
2520// passes. Because the interaction of multiple passes must be tested, it is difficult to write
2521// a unittest for them. Instead we add the tests as end2end so will in particular test
2522// TranslatorHLSL when run on Windows.
2523
2524// Test that passes splitting multiple declarations and comma operators are correctly ordered.
2525TEST_P(GLSLTest_ES3, MultipleDeclarationWithCommaOperator)
2526{
2527 const std::string &fragmentShader =
Olli Etuaho7caa80e2017-11-14 15:03:14 +02002528 R"(#version 300 es
2529 precision mediump float;
2530 out vec4 color;
2531
2532 uniform float u;
2533 float c = 0.0;
2534 float sideEffect()
2535 {
2536 c = u;
2537 return c;
2538 }
2539
2540 void main(void)
2541 {
2542 float a = 0.0, b = ((gl_FragCoord.x < 0.5 ? a : sideEffect()), a);
2543 color = vec4(b + c);
2544 })";
Corentin Wallez36fd1002016-12-08 11:30:44 -05002545
2546 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2547}
2548
2549// Test that passes splitting multiple declarations and comma operators and for loops are
2550// correctly ordered.
2551TEST_P(GLSLTest_ES3, MultipleDeclarationWithCommaOperatorInForLoop)
2552{
2553 const std::string &fragmentShader =
Olli Etuaho7caa80e2017-11-14 15:03:14 +02002554 R"(#version 300 es
2555 precision mediump float;
2556 out vec4 color;
2557
2558 uniform float u;
2559 float c = 0.0;
2560 float sideEffect()
2561 {
2562 c = u;
2563 return c;
2564 }
2565
2566 void main(void)
2567 {
2568 for(float a = 0.0, b = ((gl_FragCoord.x < 0.5 ? a : sideEffect()), a); a < 10.0; a++)
2569 {
2570 b += 1.0;
2571 color = vec4(b);
2572 }
2573 })";
Corentin Wallez36fd1002016-12-08 11:30:44 -05002574
2575 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2576}
2577
2578// Test that splitting multiple declaration in for loops works with no loop condition
2579TEST_P(GLSLTest_ES3, MultipleDeclarationInForLoopEmptyCondition)
2580{
2581 const std::string &fragmentShader =
2582 "#version 300 es\n"
2583 "precision mediump float;\n"
2584 "out vec4 color;\n"
2585 "void main(void)\n"
2586 "{\n"
2587 " for(float a = 0.0, b = 1.0;; a++)\n"
2588 " {\n"
2589 " b += 1.0;\n"
2590 " if (a > 10.0) {break;}\n"
2591 " color = vec4(b);\n"
2592 " }\n"
2593 "}\n";
2594
2595 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2596}
2597
2598// Test that splitting multiple declaration in for loops works with no loop expression
2599TEST_P(GLSLTest_ES3, MultipleDeclarationInForLoopEmptyExpression)
2600{
2601 const std::string &fragmentShader =
2602 "#version 300 es\n"
2603 "precision mediump float;\n"
2604 "out vec4 color;\n"
2605 "void main(void)\n"
2606 "{\n"
2607 " for(float a = 0.0, b = 1.0; a < 10.0;)\n"
2608 " {\n"
2609 " b += 1.0;\n"
2610 " a += 1.0;\n"
2611 " color = vec4(b);\n"
2612 " }\n"
2613 "}\n";
2614
2615 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2616}
2617
Olli Etuaho8f6eb2a2017-01-12 17:04:58 +00002618// Test that dynamic indexing of a matrix inside a dynamic indexing of a vector in an l-value works
2619// correctly.
2620TEST_P(GLSLTest_ES3, NestedDynamicIndexingInLValue)
2621{
2622 const std::string &fragmentShader =
2623 "#version 300 es\n"
2624 "precision mediump float;\n"
2625 "out vec4 my_FragColor;\n"
2626 "uniform int u_zero;\n"
2627 "void main() {\n"
2628 " mat2 m = mat2(0.0, 0.0, 0.0, 0.0);\n"
2629 " m[u_zero + 1][u_zero + 1] = float(u_zero + 1);\n"
2630 " float f = m[1][1];\n"
2631 " my_FragColor = vec4(1.0 - f, f, 0.0, 1.0);\n"
2632 "}\n";
2633
2634 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2635 drawQuad(program.get(), "inputAttribute", 0.5f);
2636 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2637}
2638
Jamie Madill192745a2016-12-22 15:58:21 -05002639class WebGLGLSLTest : public GLSLTest
2640{
2641 protected:
2642 WebGLGLSLTest() { setWebGLCompatibilityEnabled(true); }
2643};
2644
2645TEST_P(WebGLGLSLTest, MaxVaryingVec4PlusFragCoord)
2646{
2647 GLint maxVaryings = 0;
2648 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2649
2650 // Generate shader code that uses gl_FragCoord, a special fragment shader variables.
2651 // This test should fail, since we are really using (maxVaryings + 1) varyings.
2652 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, true, false, false, false);
2653}
2654
2655TEST_P(WebGLGLSLTest, MaxVaryingVec4PlusPointCoord)
2656{
2657 GLint maxVaryings = 0;
2658 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2659
2660 // Generate shader code that uses gl_FragCoord, a special fragment shader variables.
2661 // This test should fail, since we are really using (maxVaryings + 1) varyings.
2662 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, false, true, false, false);
2663}
2664
2665TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec3)
2666{
2667 GLint maxVaryings = 0;
2668 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2669
2670 VaryingTestBase(0, 0, 0, 0, maxVaryings + 1, 0, 0, 0, false, false, false, false);
2671}
2672
2673TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec3Array)
2674{
2675 GLint maxVaryings = 0;
2676 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2677
2678 VaryingTestBase(0, 0, 0, 0, 0, maxVaryings / 2 + 1, 0, 0, false, false, false, false);
2679}
2680
2681TEST_P(WebGLGLSLTest, MaxVaryingVec3AndOneVec2)
2682{
2683 GLint maxVaryings = 0;
2684 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2685
2686 VaryingTestBase(0, 0, 1, 0, maxVaryings, 0, 0, 0, false, false, false, false);
2687}
2688
2689TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec2)
2690{
2691 GLint maxVaryings = 0;
2692 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2693
2694 VaryingTestBase(0, 0, 2 * maxVaryings + 1, 0, 0, 0, 0, 0, false, false, false, false);
2695}
2696
2697TEST_P(WebGLGLSLTest, MaxVaryingVec3ArrayAndMaxPlusOneFloatArray)
2698{
2699 GLint maxVaryings = 0;
2700 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2701
2702 VaryingTestBase(0, maxVaryings / 2 + 1, 0, 0, 0, 0, 0, maxVaryings / 2, false, false, false,
2703 false);
2704}
2705
Jamie Madill6c9503e2016-08-16 14:06:32 -04002706} // anonymous namespace
2707
Olli Etuaho9250cb22017-01-21 10:51:27 +00002708// Test that FindLSB and FindMSB return correct values in their corner cases.
2709TEST_P(GLSLTest_ES31, FindMSBAndFindLSBCornerCases)
2710{
Olli Etuaho61bd9fe2017-01-27 14:20:34 -08002711 // Suspecting AMD driver bug - failure seen on bots running on AMD R5 230.
2712 if (IsAMD() && IsOpenGL() && IsLinux())
2713 {
2714 std::cout << "Test skipped on AMD OpenGL Linux" << std::endl;
2715 return;
2716 }
2717
Yuly Novikov4e36db82018-01-19 17:35:33 -05002718 // Failing on N5X Oreo http://anglebug.com/2304
2719 ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
2720
Olli Etuaho9250cb22017-01-21 10:51:27 +00002721 const std::string &fragmentShader =
2722 "#version 310 es\n"
2723 "precision mediump float;\n"
2724 "out vec4 my_FragColor;\n"
2725 "uniform int u_zero;\n"
2726 "void main() {\n"
2727 " if (findLSB(u_zero) == -1 && findMSB(u_zero) == -1 && findMSB(u_zero - 1) == -1)\n"
2728 " {\n"
2729 " my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
2730 " }\n"
2731 " else\n"
2732 " {\n"
2733 " my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
2734 " }\n"
2735 "}\n";
2736
2737 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2738 drawQuad(program.get(), "inputAttribute", 0.5f);
2739 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2740}
2741
Olli Etuahoc9da71f2017-03-06 16:28:54 +00002742// Test that writing into a swizzled vector that is dynamically indexed succeeds.
2743TEST_P(GLSLTest_ES3, WriteIntoDynamicIndexingOfSwizzledVector)
2744{
Corentin Wallez6445ddf2017-03-08 19:00:32 -05002745 if (IsOpenGL())
Olli Etuahoc9da71f2017-03-06 16:28:54 +00002746 {
2747 // http://anglebug.com/1924
Corentin Wallez6445ddf2017-03-08 19:00:32 -05002748 std::cout << "Test skipped on all OpenGL configurations because it has incorrect results"
2749 << std::endl;
Olli Etuahoc9da71f2017-03-06 16:28:54 +00002750 return;
2751 }
2752
2753 // The shader first assigns v.x to v.z (1.0)
2754 // Then v.y to v.y (2.0)
2755 // Then v.z to v.x (1.0)
2756 const std::string &fragmentShader =
2757 "#version 300 es\n"
2758 "precision highp float;\n"
2759 "out vec4 my_FragColor;\n"
2760 "void main() {\n"
2761 " vec3 v = vec3(1.0, 2.0, 3.0);\n"
2762 " for (int i = 0; i < 3; i++) {\n"
2763 " v.zyx[i] = v[i];\n"
2764 " }\n"
2765 " my_FragColor = distance(v, vec3(1.0, 2.0, 1.0)) < 0.01 ? vec4(0, 1, 0, 1) : vec4(1, "
2766 "0, 0, 1);\n"
2767 "}\n";
2768
2769 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2770 drawQuad(program.get(), "inputAttribute", 0.5f);
2771 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2772}
2773
Jamie Madill8aeeed62017-03-15 18:09:26 -04002774// This test covers a bug (and associated workaround) with nested sampling operations in the HLSL
2775// compiler DLL.
2776TEST_P(GLSLTest_ES3, NestedSamplingOperation)
2777{
2778 // This seems to be bugged on some version of Android. Might not affect the newest versions.
2779 // TODO(jmadill): Lift suppression when Chromium bots are upgraded.
2780 if (IsAndroid() && IsOpenGLES())
2781 {
2782 std::cout << "Test skipped on Android because of bug with Nexus 5X." << std::endl;
2783 return;
2784 }
2785
2786 const std::string &vertexShader =
2787 "#version 300 es\n"
2788 "out vec2 texCoord;\n"
2789 "in vec2 position;\n"
2790 "void main()\n"
2791 "{\n"
2792 " gl_Position = vec4(position, 0, 1);\n"
2793 " texCoord = position * 0.5 + vec2(0.5);\n"
2794 "}\n";
2795
2796 const std::string &simpleFragmentShader =
2797 "#version 300 es\n"
2798 "in mediump vec2 texCoord;\n"
2799 "out mediump vec4 fragColor;\n"
2800 "void main()\n"
2801 "{\n"
2802 " fragColor = vec4(texCoord, 0, 1);\n"
2803 "}\n";
2804
2805 const std::string &nestedFragmentShader =
2806 "#version 300 es\n"
2807 "uniform mediump sampler2D samplerA;\n"
2808 "uniform mediump sampler2D samplerB;\n"
2809 "in mediump vec2 texCoord;\n"
2810 "out mediump vec4 fragColor;\n"
2811 "void main ()\n"
2812 "{\n"
2813 " fragColor = texture(samplerB, texture(samplerA, texCoord).xy);\n"
2814 "}\n";
2815
2816 ANGLE_GL_PROGRAM(initProg, vertexShader, simpleFragmentShader);
2817 ANGLE_GL_PROGRAM(nestedProg, vertexShader, nestedFragmentShader);
2818
2819 // Initialize a first texture with default texCoord data.
2820 GLTexture texA;
2821 glActiveTexture(GL_TEXTURE0);
2822 glBindTexture(GL_TEXTURE_2D, texA);
2823 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
2824 GL_UNSIGNED_BYTE, nullptr);
2825 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2826 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2827
2828 GLFramebuffer fbo;
2829 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2830 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texA, 0);
2831
2832 drawQuad(initProg, "position", 0.5f);
2833 ASSERT_GL_NO_ERROR();
2834
2835 // Initialize a second texture with a simple color pattern.
2836 GLTexture texB;
2837 glActiveTexture(GL_TEXTURE1);
2838 glBindTexture(GL_TEXTURE_2D, texB);
2839
2840 std::array<GLColor, 4> simpleColors = {
2841 {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
2842 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2843 simpleColors.data());
2844 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2845 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2846
2847 // Draw with the nested program, using the first texture to index the second.
2848 glBindFramebuffer(GL_FRAMEBUFFER, 0);
2849 glUseProgram(nestedProg);
2850 GLint samplerALoc = glGetUniformLocation(nestedProg, "samplerA");
2851 ASSERT_NE(-1, samplerALoc);
2852 glUniform1i(samplerALoc, 0);
2853 GLint samplerBLoc = glGetUniformLocation(nestedProg, "samplerB");
2854 ASSERT_NE(-1, samplerBLoc);
2855 glUniform1i(samplerBLoc, 1);
2856
2857 drawQuad(nestedProg, "position", 0.5f);
2858 ASSERT_GL_NO_ERROR();
2859
2860 // Compute four texel centers.
2861 Vector2 windowSize(getWindowWidth(), getWindowHeight());
2862 Vector2 quarterWindowSize = windowSize / 4;
2863 Vector2 ul = quarterWindowSize;
2864 Vector2 ur(windowSize.x() - quarterWindowSize.x(), quarterWindowSize.y());
2865 Vector2 ll(quarterWindowSize.x(), windowSize.y() - quarterWindowSize.y());
2866 Vector2 lr = windowSize - quarterWindowSize;
2867
2868 EXPECT_PIXEL_COLOR_EQ_VEC2(ul, simpleColors[0]);
2869 EXPECT_PIXEL_COLOR_EQ_VEC2(ur, simpleColors[1]);
2870 EXPECT_PIXEL_COLOR_EQ_VEC2(ll, simpleColors[2]);
2871 EXPECT_PIXEL_COLOR_EQ_VEC2(lr, simpleColors[3]);
2872}
2873
Olli Etuaho81629262017-04-19 11:56:01 +03002874// Tests that using a constant declaration as the only statement in a for loop without curly braces
2875// doesn't crash.
2876TEST_P(GLSLTest, ConstantStatementInForLoop)
2877{
2878 const std::string &vertexShader =
2879 "void main()\n"
2880 "{\n"
2881 " for (int i = 0; i < 10; ++i)\n"
2882 " const int b = 0;\n"
2883 "}\n";
2884
2885 GLuint shader = CompileShader(GL_VERTEX_SHADER, vertexShader);
2886 EXPECT_NE(0u, shader);
2887 glDeleteShader(shader);
2888}
2889
2890// Tests that using a constant declaration as a loop init expression doesn't crash. Note that this
2891// test doesn't work on D3D9 due to looping limitations, so it is only run on ES3.
2892TEST_P(GLSLTest_ES3, ConstantStatementAsLoopInit)
2893{
2894 const std::string &vertexShader =
2895 "void main()\n"
2896 "{\n"
2897 " for (const int i = 0; i < 0;) {}\n"
2898 "}\n";
2899
2900 GLuint shader = CompileShader(GL_VERTEX_SHADER, vertexShader);
2901 EXPECT_NE(0u, shader);
2902 glDeleteShader(shader);
2903}
2904
Olli Etuaho9733cee2017-05-11 19:14:35 +03002905// Test that uninitialized local variables are initialized to 0.
2906TEST_P(GLSLTest_ES3, InitUninitializedLocals)
2907{
2908 if (IsAndroid() && IsOpenGLES())
2909 {
2910 // http://anglebug.com/2046
2911 std::cout
2912 << "Test skipped on Android GLES because local variable initialization is disabled."
2913 << std::endl;
2914 return;
2915 }
2916
Olli Etuaho9733cee2017-05-11 19:14:35 +03002917 const std::string &fragmentShader =
2918 "#version 300 es\n"
2919 "precision mediump float;\n"
2920 "out vec4 my_FragColor;\n"
2921 "int result = 0;\n"
2922 "void main()\n"
2923 "{\n"
2924 " int u;\n"
2925 " result += u;\n"
2926 " int k = 0;\n"
2927 " for (int i[2], j = i[0] + 1; k < 2; ++k)\n"
2928 " {\n"
2929 " result += j;\n"
2930 " }\n"
2931 " if (result == 2)\n"
2932 " {\n"
2933 " my_FragColor = vec4(0, 1, 0, 1);\n"
2934 " }\n"
2935 " else\n"
2936 " {\n"
2937 " my_FragColor = vec4(1, 0, 0, 1);\n"
2938 " }\n"
2939 "}\n";
2940
2941 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2942 drawQuad(program.get(), "inputAttribute", 0.5f);
2943 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2944}
2945
2946// Test that uninitialized structs containing arrays of structs are initialized to 0. This
2947// specifically tests with two different struct variables declared in the same block.
2948TEST_P(GLSLTest, InitUninitializedStructContainingArrays)
2949{
2950 if (IsAndroid() && IsOpenGLES())
2951 {
2952 // http://anglebug.com/2046
2953 std::cout
2954 << "Test skipped on Android GLES because local variable initialization is disabled."
2955 << std::endl;
2956 return;
2957 }
2958
2959 if (IsOSX() && IsOpenGL())
2960 {
2961 // http://anglebug.com/2041
2962 std::cout << "Test skipped on Mac OpenGL because local variable initialization is disabled."
2963 << std::endl;
2964 return;
2965 }
2966
2967 const std::string &fragmentShader =
2968 "precision mediump float;\n"
2969 "struct T\n"
2970 "{\n"
2971 " int a[2];\n"
2972 "};\n"
2973 "struct S\n"
2974 "{\n"
2975 " T t[2];\n"
2976 "};\n"
2977 "void main()\n"
2978 "{\n"
2979 " S s;\n"
2980 " S s2;\n"
2981 " if (s.t[1].a[1] == 0 && s2.t[1].a[1] == 0)\n"
2982 " {\n"
2983 " gl_FragColor = vec4(0, 1, 0, 1);\n"
2984 " }\n"
2985 " else\n"
2986 " {\n"
2987 " gl_FragColor = vec4(1, 0, 0, 1);\n"
2988 " }\n"
2989 "}\n";
2990
2991 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2992 drawQuad(program.get(), "inputAttribute", 0.5f);
2993 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2994}
2995
Geoff Langbb1e7502017-06-05 16:40:09 -04002996// Verify that two shaders with the same uniform name and members but different structure names will
2997// not link.
2998TEST_P(GLSLTest, StructureNameMatchingTest)
2999{
3000 const char *vsSource =
3001 "// Structures must have the same name, sequence of type names, and\n"
3002 "// type definitions, and field names to be considered the same type.\n"
3003 "// GLSL 1.017 4.2.4\n"
3004 "precision mediump float;\n"
3005 "struct info {\n"
3006 " vec4 pos;\n"
3007 " vec4 color;\n"
3008 "};\n"
3009 "\n"
3010 "uniform info uni;\n"
3011 "void main()\n"
3012 "{\n"
3013 " gl_Position = uni.pos;\n"
3014 "}\n";
3015
3016 GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
3017 ASSERT_NE(0u, vs);
3018 glDeleteShader(vs);
3019
3020 const char *fsSource =
3021 "// Structures must have the same name, sequence of type names, and\n"
3022 "// type definitions, and field names to be considered the same type.\n"
3023 "// GLSL 1.017 4.2.4\n"
3024 "precision mediump float;\n"
3025 "struct info1 {\n"
3026 " vec4 pos;\n"
3027 " vec4 color;\n"
3028 "};\n"
3029 "\n"
3030 "uniform info1 uni;\n"
3031 "void main()\n"
3032 "{\n"
3033 " gl_FragColor = uni.color;\n"
3034 "}\n";
3035
3036 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
3037 ASSERT_NE(0u, fs);
3038 glDeleteShader(fs);
3039
3040 GLuint program = CompileProgram(vsSource, fsSource);
3041 EXPECT_EQ(0u, program);
3042}
3043
Olli Etuaho9733cee2017-05-11 19:14:35 +03003044// Test that an uninitialized nameless struct inside a for loop init statement works.
3045TEST_P(GLSLTest_ES3, UninitializedNamelessStructInForInitStatement)
3046{
3047 if (IsAndroid() && IsOpenGLES())
3048 {
3049 // http://anglebug.com/2046
3050 std::cout
3051 << "Test skipped on Android GLES because local variable initialization is disabled."
3052 << std::endl;
3053 return;
3054 }
3055
3056 if (IsOSX() && IsOpenGL())
3057 {
3058 // http://anglebug.com/2041
3059 std::cout << "Test skipped on Mac OpenGL because local variable initialization is disabled."
3060 << std::endl;
3061 return;
3062 }
3063
3064 const std::string &fragmentShader =
3065 "#version 300 es\n"
3066 "precision highp float;\n"
3067 "out vec4 my_FragColor;\n"
3068 "void main()\n"
3069 "{\n"
3070 " my_FragColor = vec4(1, 0, 0, 1);\n"
3071 " for (struct { float q; } b; b.q < 2.0; b.q++) {\n"
3072 " my_FragColor = vec4(0, 1, 0, 1);\n"
3073 " }\n"
3074 "}\n";
3075
3076 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3077 drawQuad(program.get(), "inputAttribute", 0.5f);
3078 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3079}
3080
Olli Etuaho0ffc4412017-05-19 14:18:55 +03003081// Test that uninitialized global variables are initialized to 0.
3082TEST_P(WebGLGLSLTest, InitUninitializedGlobals)
3083{
3084 const std::string &fragmentShader =
3085 "precision mediump float;\n"
3086 "int result;\n"
3087 "int i[2], j = i[0] + 1;\n"
3088 "void main()\n"
3089 "{\n"
3090 " result += j;\n"
3091 " if (result == 1)\n"
3092 " {\n"
3093 " gl_FragColor = vec4(0, 1, 0, 1);\n"
3094 " }\n"
3095 " else\n"
3096 " {\n"
3097 " gl_FragColor = vec4(1, 0, 0, 1);\n"
3098 " }\n"
3099 "}\n";
3100
3101 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3102 drawQuad(program.get(), "inputAttribute", 0.5f, 1.0f, true);
3103 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3104}
3105
3106// Test that an uninitialized nameless struct in the global scope works.
3107TEST_P(WebGLGLSLTest, UninitializedNamelessStructInGlobalScope)
3108{
3109 const std::string &fragmentShader =
3110 "precision mediump float;\n"
3111 "struct { float q; } b;\n"
3112 "void main()\n"
3113 "{\n"
3114 " gl_FragColor = vec4(1, 0, 0, 1);\n"
3115 " if (b.q == 0.0)\n"
3116 " {\n"
3117 " gl_FragColor = vec4(0, 1, 0, 1);\n"
3118 " }\n"
3119 "}\n";
3120
3121 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3122 drawQuad(program.get(), "inputAttribute", 0.5f, 1.0f, true);
3123 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3124}
3125
Olli Etuaho914b79a2017-06-19 16:03:19 +03003126// Test that a loop condition that has an initializer declares a variable.
3127TEST_P(GLSLTest_ES3, ConditionInitializerDeclaresVariable)
3128{
3129 const std::string &fragmentShader =
3130 "#version 300 es\n"
3131 "precision highp float;\n"
3132 "out vec4 my_FragColor;\n"
3133 "void main()\n"
3134 "{\n"
3135 " float i = 0.0;\n"
3136 " while (bool foo = (i < 1.5))\n"
3137 " {\n"
3138 " if (!foo)\n"
3139 " {\n"
3140 " ++i;\n"
3141 " }\n"
3142 " if (i > 3.5)\n"
3143 " {\n"
3144 " break;\n"
3145 " }\n"
3146 " ++i;\n"
3147 " }\n"
3148 " my_FragColor = vec4(i * 0.5 - 1.0, i * 0.5, 0.0, 1.0);\n"
3149 "}\n";
3150
3151 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3152 drawQuad(program.get(), "inputAttribute", 0.5f);
3153 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3154}
3155
Olli Etuahoff526f12017-06-30 12:26:54 +03003156// Test that a variable hides a user-defined function with the same name after its initializer.
3157// GLSL ES 1.00.17 section 4.2.2: "A variable declaration is visible immediately following the
3158// initializer if present, otherwise immediately following the identifier"
3159TEST_P(GLSLTest, VariableHidesUserDefinedFunctionAfterInitializer)
3160{
3161 const std::string &fragmentShader =
3162 "precision mediump float;\n"
3163 "uniform vec4 u;\n"
3164 "vec4 foo()\n"
3165 "{\n"
3166 " return u;\n"
3167 "}\n"
3168 "void main()\n"
3169 "{\n"
3170 " vec4 foo = foo();\n"
3171 " gl_FragColor = foo + vec4(0, 1, 0, 1);\n"
3172 "}\n";
3173
3174 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3175 drawQuad(program.get(), "inputAttribute", 0.5f);
3176 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3177}
3178
Olli Etuaho088031e2017-07-03 15:59:33 +03003179// Test that structs with identical members are not ambiguous as function arguments.
3180TEST_P(GLSLTest, StructsWithSameMembersDisambiguatedByName)
3181{
3182 const std::string &fragmentShader =
3183 "precision mediump float;\n"
3184 "uniform float u_zero;\n"
3185 "struct S { float foo; };\n"
3186 "struct S2 { float foo; };\n"
3187 "float get(S s) { return s.foo + u_zero; }\n"
3188 "float get(S2 s2) { return 0.25 + s2.foo + u_zero; }\n"
3189 "void main()\n"
3190 "{\n"
3191 " S s;\n"
3192 " s.foo = 0.5;\n"
3193 " S2 s2;\n"
3194 " s2.foo = 0.25;\n"
3195 " gl_FragColor = vec4(0.0, get(s) + get(s2), 0.0, 1.0);\n"
3196 "}\n";
3197
3198 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3199 drawQuad(program.get(), "inputAttribute", 0.5f);
3200 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3201}
3202
Olli Etuaho06a06f52017-07-12 12:22:15 +03003203// Test that a varying struct that's not statically used in the fragment shader works.
3204// GLSL ES 3.00.6 section 4.3.10.
3205TEST_P(GLSLTest_ES3, VaryingStructNotStaticallyUsedInFragmentShader)
3206{
3207 const std::string &vertexShader =
3208 "#version 300 es\n"
3209 "struct S {\n"
3210 " vec4 field;\n"
3211 "};\n"
3212 "out S varStruct;\n"
3213 "void main()\n"
3214 "{\n"
3215 " gl_Position = vec4(1.0);\n"
3216 " varStruct.field = vec4(0.0, 0.5, 0.0, 0.0);\n"
3217 "}\n";
3218
3219 const std::string &fragmentShader =
3220 "#version 300 es\n"
3221 "precision mediump float;\n"
3222 "struct S {\n"
3223 " vec4 field;\n"
3224 "};\n"
3225 "in S varStruct;\n"
3226 "out vec4 col;\n"
3227 "void main()\n"
3228 "{\n"
3229 " col = vec4(1.0);\n"
3230 "}\n";
3231
3232 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3233}
3234
3235// Test that a varying struct that's not declared in the fragment shader links successfully.
3236// GLSL ES 3.00.6 section 4.3.10.
3237TEST_P(GLSLTest_ES3, VaryingStructNotDeclaredInFragmentShader)
3238{
3239 const std::string &vertexShader =
3240 "#version 300 es\n"
3241 "struct S {\n"
3242 " vec4 field;\n"
3243 "};\n"
3244 "out S varStruct;\n"
3245 "void main()\n"
3246 "{\n"
3247 " gl_Position = vec4(1.0);\n"
3248 " varStruct.field = vec4(0.0, 0.5, 0.0, 0.0);\n"
3249 "}\n";
3250
3251 const std::string &fragmentShader =
3252 "#version 300 es\n"
3253 "precision mediump float;\n"
3254 "out vec4 col;\n"
3255 "void main()\n"
3256 "{\n"
3257 " col = vec4(1.0);\n"
3258 "}\n";
3259
3260 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3261}
3262
3263// Test that a varying struct that gets used in the fragment shader works.
3264TEST_P(GLSLTest_ES3, VaryingStructUsedInFragmentShader)
3265{
3266 const std::string &vertexShader =
3267 "#version 300 es\n"
3268 "in vec4 inputAttribute;\n"
3269 "struct S {\n"
3270 " vec4 field;\n"
3271 "};\n"
3272 "out S varStruct;\n"
3273 "void main()\n"
3274 "{\n"
3275 " gl_Position = inputAttribute;\n"
3276 " varStruct.field = vec4(0.0, 1.0, 0.0, 1.0);\n"
3277 "}\n";
3278
3279 const std::string &fragmentShader =
3280 "#version 300 es\n"
3281 "precision mediump float;\n"
3282 "out vec4 col;\n"
3283 "struct S {\n"
3284 " vec4 field;\n"
3285 "};\n"
3286 "in S varStruct;\n"
3287 "void main()\n"
3288 "{\n"
3289 " col = varStruct.field;\n"
3290 "}\n";
3291
3292 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3293 drawQuad(program.get(), "inputAttribute", 0.5f);
3294 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3295}
3296
Olli Etuaho3860b6c2017-07-19 16:17:24 +03003297// This test covers passing an array of structs containing samplers as a function argument.
3298TEST_P(GLSLTest, ArrayOfStructsWithSamplersAsFunctionArg)
3299{
3300 if (IsAndroid() && IsAdreno() && IsOpenGLES())
3301 {
3302 // Shader failed to compile on Android. http://anglebug.com/2114
3303 std::cout << "Test skipped on Adreno OpenGLES on Android." << std::endl;
3304 return;
3305 }
3306
3307 const std::string &vertexShader =
3308 "attribute vec2 position;\n"
3309 "void main()\n"
3310 "{\n"
3311 " gl_Position = vec4(position, 0, 1);\n"
3312 "}\n";
3313
3314 const std::string &fragmentShader =
3315 "precision mediump float;\n"
3316 "struct S\n"
3317 "{\n"
3318 " sampler2D samplerMember; \n"
3319 "};\n"
3320 "uniform S uStructs[2];\n"
3321 "uniform vec2 uTexCoord;\n"
3322 "\n"
3323 "vec4 foo(S[2] structs)\n"
3324 "{\n"
3325 " return texture2D(structs[0].samplerMember, uTexCoord);\n"
3326 "}\n"
3327 "void main()\n"
3328 "{\n"
3329 " gl_FragColor = foo(uStructs);\n"
3330 "}\n";
3331
3332 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3333
3334 // Initialize the texture with green.
3335 GLTexture tex;
3336 glActiveTexture(GL_TEXTURE0);
3337 glBindTexture(GL_TEXTURE_2D, tex);
3338 GLubyte texData[] = {0u, 255u, 0u, 255u};
3339 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
3340 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3341 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3342 ASSERT_GL_NO_ERROR();
3343
3344 // Draw
3345 glUseProgram(program);
3346 GLint samplerMemberLoc = glGetUniformLocation(program, "uStructs[0].samplerMember");
3347 ASSERT_NE(-1, samplerMemberLoc);
3348 glUniform1i(samplerMemberLoc, 0);
3349 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
3350 ASSERT_NE(-1, texCoordLoc);
3351 glUniform2f(texCoordLoc, 0.5f, 0.5f);
3352
3353 drawQuad(program, "position", 0.5f);
3354 ASSERT_GL_NO_ERROR();
3355
3356 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
3357}
3358
Olli Etuaho28839f02017-08-15 11:38:16 +03003359// This test covers passing a struct containing an array of samplers as a function argument.
3360TEST_P(GLSLTest, StructWithSamplerArrayAsFunctionArg)
3361{
3362 if (IsAndroid() && IsAdreno() && IsOpenGLES())
3363 {
3364 // Shader failed to compile on Android. http://anglebug.com/2114
3365 std::cout << "Test skipped on Adreno OpenGLES on Android." << std::endl;
3366 return;
3367 }
3368
3369 const std::string &vertexShader =
3370 "attribute vec2 position;\n"
3371 "void main()\n"
3372 "{\n"
3373 " gl_Position = vec4(position, 0, 1);\n"
3374 "}\n";
3375
3376 const std::string &fragmentShader =
3377 "precision mediump float;\n"
3378 "struct S\n"
3379 "{\n"
3380 " sampler2D samplerMembers[2];\n"
3381 "};\n"
3382 "uniform S uStruct;\n"
3383 "uniform vec2 uTexCoord;\n"
3384 "\n"
3385 "vec4 foo(S str)\n"
3386 "{\n"
3387 " return texture2D(str.samplerMembers[0], uTexCoord);\n"
3388 "}\n"
3389 "void main()\n"
3390 "{\n"
3391 " gl_FragColor = foo(uStruct);\n"
3392 "}\n";
3393
3394 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3395
3396 // Initialize the texture with green.
3397 GLTexture tex;
3398 glActiveTexture(GL_TEXTURE0);
3399 glBindTexture(GL_TEXTURE_2D, tex);
3400 GLubyte texData[] = {0u, 255u, 0u, 255u};
3401 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
3402 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3403 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3404 ASSERT_GL_NO_ERROR();
3405
3406 // Draw
3407 glUseProgram(program);
3408 GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMembers[0]");
3409 ASSERT_NE(-1, samplerMemberLoc);
3410 glUniform1i(samplerMemberLoc, 0);
3411 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
3412 ASSERT_NE(-1, texCoordLoc);
3413 glUniform2f(texCoordLoc, 0.5f, 0.5f);
3414
3415 drawQuad(program, "position", 0.5f);
3416 ASSERT_GL_NO_ERROR();
3417
3418 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
3419}
3420
Olli Etuahoa16a84f2017-09-12 13:49:18 +03003421// Test that a global variable declared after main() works. This is a regression test for an issue
3422// in global variable initialization.
3423TEST_P(WebGLGLSLTest, GlobalVariableDeclaredAfterMain)
3424{
3425 const std::string &fragmentShader =
3426 "precision mediump float;\n"
3427 "int getFoo();\n"
3428 "uniform int u_zero;\n"
3429 "void main()\n"
3430 "{\n"
3431 " gl_FragColor = vec4(1, 0, 0, 1);\n"
3432 " if (getFoo() == 0)\n"
3433 " {\n"
3434 " gl_FragColor = vec4(0, 1, 0, 1);\n"
3435 " }\n"
3436 "}\n"
3437 "int foo;\n"
3438 "int getFoo()\n"
3439 "{\n"
3440 " foo = u_zero;\n"
3441 " return foo;\n"
3442 "}\n";
3443
3444 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3445 drawQuad(program.get(), "inputAttribute", 0.5f, 1.0f, true);
3446 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3447}
3448
Olli Etuahobb5a7e22017-08-30 13:03:12 +03003449// Test calling array length() with a "this" expression having side effects inside a loop condition.
3450// The spec says that sequence operator operands need to run in sequence.
3451TEST_P(GLSLTest_ES3, ArrayLengthOnExpressionWithSideEffectsInLoopCondition)
3452{
3453 // "a" gets doubled three times in the below program.
3454 const std::string &fragmentShader =
3455 R"(#version 300 es
3456 precision highp float;
3457 out vec4 my_FragColor;
3458 uniform int u_zero;
3459 int a;
3460 int[2] doubleA()
3461 {
3462 a *= 2;
3463 return int[2](a, a);
3464 }
3465 void main()
3466 {
3467 a = u_zero + 1;
3468 for (int i = 0; i < doubleA().length(); ++i)
3469 {}
3470 if (a == 8)
3471 {
3472 my_FragColor = vec4(0, 1, 0, 1);
3473 }
3474 else
3475 {
3476 my_FragColor = vec4(1, 0, 0, 1);
3477 }
3478 })";
3479
3480 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3481 drawQuad(program.get(), "inputAttribute", 0.5f);
3482 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3483}
3484
3485// Test calling array length() with a "this" expression having side effects that interact with side
3486// effects of another operand of the same sequence operator. The spec says that sequence operator
3487// operands need to run in order from left to right (ESSL 3.00.6 section 5.9).
3488TEST_P(GLSLTest_ES3, ArrayLengthOnExpressionWithSideEffectsInSequence)
3489{
3490 const std::string &fragmentShader =
3491 R"(#version 300 es
3492 precision highp float;
3493 out vec4 my_FragColor;
3494 uniform int u_zero;
3495 int a;
3496 int[3] doubleA()
3497 {
3498 a *= 2;
3499 return int[3](a, a, a);
3500 }
3501 void main()
3502 {
3503 a = u_zero;
3504 int b = (a++, doubleA().length());
3505 if (b == 3 && a == 2)
3506 {
3507 my_FragColor = vec4(0, 1, 0, 1);
3508 }
3509 else
3510 {
3511 my_FragColor = vec4(1, 0, 0, 1);
3512 }
3513 })";
3514
3515 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3516 drawQuad(program.get(), "inputAttribute", 0.5f);
3517 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3518}
3519
3520// Test calling array length() with a "this" expression that also contains a call of array length().
3521// Both "this" expressions also have side effects.
3522TEST_P(GLSLTest_ES3, NestedArrayLengthMethodsWithSideEffects)
3523{
3524 const std::string &fragmentShader =
3525 R"(#version 300 es
3526 precision highp float;
3527 out vec4 my_FragColor;
3528 uniform int u_zero;
3529 int a;
3530 int[3] multiplyA(int multiplier)
3531 {
3532 a *= multiplier;
3533 return int[3](a, a, a);
3534 }
3535 void main()
3536 {
3537 a = u_zero + 1;
3538 int b = multiplyA(multiplyA(2).length()).length();
3539 if (b == 3 && a == 6)
3540 {
3541 my_FragColor = vec4(0, 1, 0, 1);
3542 }
3543 else
3544 {
3545 my_FragColor = vec4(1, 0, 0, 1);
3546 }
3547 })";
3548
3549 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3550 drawQuad(program.get(), "inputAttribute", 0.5f);
3551 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3552}
3553
Olli Etuaho78507c62017-10-10 15:06:45 +03003554// Test that statements inside switch() get translated to correct HLSL.
3555TEST_P(GLSLTest_ES3, DifferentStatementsInsideSwitch)
3556{
3557 const std::string &fragmentShader =
3558 R"(#version 300 es
3559
3560 precision highp float;
3561
3562 uniform int u;
3563
3564 void main()
3565 {
3566 switch (u)
3567 {
3568 case 0:
3569 ivec2 i;
3570 i.yx;
3571 }
3572 })";
3573 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3574}
3575
Olli Etuaho852fe872017-10-10 15:13:59 +03003576// Test that switch fall-through works correctly.
3577// This is a regression test for http://anglebug.com/2178
3578TEST_P(GLSLTest_ES3, SwitchFallThroughCodeDuplication)
3579{
3580 const std::string &fragmentShader =
3581 R"(#version 300 es
3582
3583 precision highp float;
3584
3585 out vec4 my_FragColor;
3586
3587 uniform int u_zero;
3588
3589 void main()
3590 {
3591 int i = 0;
3592 // switch should fall through both cases.
3593 switch(u_zero)
3594 {
3595 case 0:
3596 i += 1;
3597 case 1:
3598 i += 2;
3599 }
3600 if (i == 3)
3601 {
3602 my_FragColor = vec4(0, 1, 0, 1);
3603 }
3604 else
3605 {
3606 my_FragColor = vec4(1, 0, 0, 1);
3607 }
3608 })";
3609
3610 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3611 drawQuad(program.get(), "inputAttribute", 0.5f);
3612 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3613}
3614
Olli Etuaho923ecef2017-10-11 12:01:38 +03003615// Test that a switch statement with an empty block inside as a final statement compiles.
3616TEST_P(GLSLTest_ES3, SwitchFinalCaseHasEmptyBlock)
3617{
3618 const std::string &fragmentShader =
3619 R"(#version 300 es
3620
3621 precision mediump float;
3622 uniform int i;
3623 void main()
3624 {
3625 switch (i)
3626 {
3627 case 0:
3628 break;
3629 default:
3630 {}
3631 }
3632 })";
3633 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3634}
3635
3636// Test that a switch statement with an empty declaration inside as a final statement compiles.
3637TEST_P(GLSLTest_ES3, SwitchFinalCaseHasEmptyDeclaration)
3638{
3639 const std::string &fragmentShader =
3640 R"(#version 300 es
3641
3642 precision mediump float;
3643 uniform int i;
3644 void main()
3645 {
3646 switch (i)
3647 {
3648 case 0:
3649 break;
3650 default:
3651 float;
3652 }
3653 })";
3654 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3655}
3656
Olli Etuaho4bd730c2017-10-10 14:14:19 +03003657// Test switch/case where break/return statements are within blocks.
3658TEST_P(GLSLTest_ES3, SwitchBreakOrReturnInsideBlocks)
3659{
3660 const std::string &fragmentShader =
3661 R"(#version 300 es
3662
3663 precision highp float;
3664
3665 uniform int u_zero;
3666 out vec4 my_FragColor;
3667
3668 bool test(int n)
3669 {
3670 switch(n) {
3671 case 0:
3672 {
3673 {
3674 break;
3675 }
3676 }
3677 case 1:
3678 {
3679 return true;
3680 }
3681 case 2:
3682 {
3683 n++;
3684 }
3685 }
3686 return false;
3687 }
3688
3689 void main()
3690 {
3691 my_FragColor = test(u_zero + 1) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
3692 })";
3693
3694 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3695 drawQuad(program.get(), "inputAttribute", 0.5f);
3696 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3697}
3698
Olli Etuahof6d242e2017-10-12 17:21:06 +03003699// Test switch/case where a variable is declared inside one of the cases and is accessed by a
3700// subsequent case.
3701TEST_P(GLSLTest_ES3, SwitchWithVariableDeclarationInside)
3702{
3703 const std::string &fragmentShader =
3704 R"(#version 300 es
3705
3706 precision highp float;
3707 out vec4 my_FragColor;
3708
3709 uniform int u_zero;
3710
3711 void main()
3712 {
3713 my_FragColor = vec4(1, 0, 0, 1);
3714 switch (u_zero)
3715 {
3716 case 0:
3717 ivec2 i;
3718 i = ivec2(1, 0);
3719 default:
3720 my_FragColor = vec4(0, i[0], 0, 1);
3721 }
3722 })";
3723
3724 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3725 drawQuad(program.get(), "inputAttribute", 0.5f);
3726 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3727}
3728
3729// Test nested switch/case where a variable is declared inside one of the cases and is accessed by a
3730// subsequent case.
3731TEST_P(GLSLTest_ES3, NestedSwitchWithVariableDeclarationInside)
3732{
3733 const std::string &fragmentShader =
3734 R"(#version 300 es
3735
3736 precision highp float;
3737 out vec4 my_FragColor;
3738
3739 uniform int u_zero;
3740 uniform int u_zero2;
3741
3742 void main()
3743 {
3744 my_FragColor = vec4(1, 0, 0, 1);
3745 switch (u_zero)
3746 {
3747 case 0:
3748 ivec2 i;
3749 i = ivec2(1, 0);
3750 switch (u_zero2)
3751 {
3752 case 0:
3753 int j;
3754 default:
3755 j = 1;
3756 i *= j;
3757 }
3758 default:
3759 my_FragColor = vec4(0, i[0], 0, 1);
3760 }
3761 })";
3762
3763 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3764 drawQuad(program.get(), "inputAttribute", 0.5f);
3765 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3766}
3767
Olli Etuahoc1f14fb2017-10-28 19:17:23 +03003768// Test that an empty switch/case statement is translated in a way that compiles and executes the
3769// init-statement.
3770TEST_P(GLSLTest_ES3, EmptySwitch)
3771{
3772 const std::string &fragmentShader =
3773 R"(#version 300 es
3774
3775 precision highp float;
3776
3777 uniform int u_zero;
3778 out vec4 my_FragColor;
3779
3780 void main()
3781 {
3782 int i = u_zero;
3783 switch(++i) {}
3784 my_FragColor = (i == 1) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
3785 })";
3786
3787 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3788 drawQuad(program.get(), "inputAttribute", 0.5f);
3789 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3790}
3791
Olli Etuahobd3cd502017-11-03 15:48:52 +02003792// Test that a constant struct inside an expression is handled correctly.
3793TEST_P(GLSLTest_ES3, ConstStructInsideExpression)
3794{
3795 // Incorrect output color was seen on Android. http://anglebug.com/2226
3796 ANGLE_SKIP_TEST_IF(IsAndroid() && !IsNVIDIA() && IsOpenGLES());
3797
3798 const std::string &fragmentShader =
3799 R"(#version 300 es
3800
3801 precision highp float;
3802 out vec4 my_FragColor;
3803
3804 uniform float u_zero;
3805
3806 struct S
3807 {
3808 float field;
3809 };
3810
3811 void main()
3812 {
3813 const S constS = S(1.0);
3814 S nonConstS = constS;
3815 nonConstS.field = u_zero;
3816 bool fail = (constS == nonConstS);
3817 my_FragColor = vec4(0, 1, 0, 1);
3818 if (fail)
3819 {
3820 my_FragColor = vec4(1, 0, 0, 1);
3821 }
3822 })";
3823
3824 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3825 drawQuad(program.get(), "inputAttribute", 0.5f);
3826 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3827}
3828
3829// Test that a varying struct that's defined as a part of the declaration is handled correctly.
3830TEST_P(GLSLTest_ES3, VaryingStructWithInlineDefinition)
3831{
3832 const std::string &vertexShader =
3833 R"(#version 300 es
3834 in vec4 inputAttribute;
3835
3836 flat out struct S
3837 {
3838 int field;
3839 } v_s;
3840
3841 void main()
3842 {
3843 v_s.field = 1;
3844 gl_Position = inputAttribute;
3845 })";
3846
3847 const std::string &fragmentShader =
3848 R"(#version 300 es
3849
3850 precision highp float;
3851 out vec4 my_FragColor;
3852
3853 flat in struct S
3854 {
3855 int field;
3856 } v_s;
3857
3858 void main()
3859 {
3860 bool success = (v_s.field == 1);
3861 my_FragColor = vec4(1, 0, 0, 1);
3862 if (success)
3863 {
3864 my_FragColor = vec4(0, 1, 0, 1);
3865 }
3866 })";
3867
3868 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3869 drawQuad(program.get(), "inputAttribute", 0.5f);
3870 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3871}
3872
Olli Etuaho661fc482017-10-16 12:17:05 +03003873// Test vector/scalar arithmetic (in this case multiplication and addition). Meant to reproduce a
3874// bug that appeared in NVIDIA OpenGL drivers and that is worked around by
3875// VectorizeVectorScalarArithmetic AST transform.
3876TEST_P(GLSLTest, VectorScalarMultiplyAndAddInLoop)
3877{
3878 const std::string &fragmentShader =
3879 R"(
3880
3881 precision mediump float;
3882
3883 void main() {
3884 gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
3885 for (int i = 0; i < 2; i++)
3886 {
3887 gl_FragColor += (2.0 * gl_FragCoord.x);
3888 }
3889 if (gl_FragColor.g == gl_FragColor.r &&
3890 gl_FragColor.b == gl_FragColor.r &&
3891 gl_FragColor.a == gl_FragColor.r)
3892 {
3893 gl_FragColor = vec4(0, 1, 0, 1);
3894 }
3895 })";
3896
3897 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3898 drawQuad(program.get(), "inputAttribute", 0.5f);
3899 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3900}
3901
3902// Test vector/scalar arithmetic (in this case compound division and addition). Meant to reproduce a
3903// bug that appeared in NVIDIA OpenGL drivers and that is worked around by
3904// VectorizeVectorScalarArithmetic AST transform.
3905TEST_P(GLSLTest, VectorScalarDivideAndAddInLoop)
3906{
3907 const std::string &fragmentShader =
3908 R"(
3909
3910 precision mediump float;
3911
3912 void main() {
3913 gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
3914 for (int i = 0; i < 2; i++)
3915 {
3916 float x = gl_FragCoord.x;
3917 gl_FragColor = gl_FragColor + (x /= 2.0);
3918 }
3919 if (gl_FragColor.g == gl_FragColor.r &&
3920 gl_FragColor.b == gl_FragColor.r &&
3921 gl_FragColor.a == gl_FragColor.r)
3922 {
3923 gl_FragColor = vec4(0, 1, 0, 1);
3924 }
3925 })";
3926
3927 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3928 drawQuad(program.get(), "inputAttribute", 0.5f);
3929 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3930}
3931
Olli Etuahob8cb9392017-12-20 14:23:19 +02003932// Test that a varying with a flat qualifier that is used as an operand of a folded ternary operator
3933// is handled correctly.
3934TEST_P(GLSLTest_ES3, FlatVaryingUsedInFoldedTernary)
3935{
3936 const std::string &vertexShader =
3937 R"(#version 300 es
3938
3939 in vec4 inputAttribute;
3940
3941 flat out int v;
3942
3943 void main()
3944 {
3945 v = 1;
3946 gl_Position = inputAttribute;
3947 })";
3948
3949 const std::string &fragmentShader =
3950 R"(#version 300 es
3951
3952 precision highp float;
3953 out vec4 my_FragColor;
3954
3955 flat in int v;
3956
3957 void main()
3958 {
3959 my_FragColor = vec4(0, (true ? v : 0), 0, 1);
3960 })";
3961
3962 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3963 drawQuad(program.get(), "inputAttribute", 0.5f);
3964 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3965}
3966
Jiawei Shao02f15232017-12-27 10:10:28 +08003967// Verify that the link error message from last link failure is cleared when the new link is
3968// finished.
3969TEST_P(GLSLTest, ClearLinkErrorLog)
3970{
3971 const std::string &vertexShader =
3972 R"(
3973
3974 attribute vec4 vert_in;
3975 varying vec4 vert_out;
3976 void main()
3977 {
3978 gl_Position = vert_in;
3979 vert_out = vert_in;
3980 })";
3981
3982 const std::string &fragmentShader =
3983 R"(
3984
3985 precision mediump float;
3986 varying vec4 frag_in;
3987 void main()
3988 {
3989 gl_FragColor = frag_in;
3990 })";
3991
3992 GLuint vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
3993 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);
3994
3995 GLuint program = glCreateProgram();
3996
3997 // The first time the program link fails because of lack of fragment shader.
3998 glAttachShader(program, vs);
3999 glLinkProgram(program);
4000 GLint linkStatus = GL_TRUE;
4001 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
4002 ASSERT_FALSE(linkStatus);
4003
4004 const std::string &lackOfFragmentShader = QueryErrorMessage(program);
4005
4006 // The second time the program link fails because of the mismatch of the varying types.
4007 glAttachShader(program, fs);
4008 glLinkProgram(program);
4009 linkStatus = GL_TRUE;
4010 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
4011 ASSERT_FALSE(linkStatus);
4012
4013 const std::string &varyingTypeMismatch = QueryErrorMessage(program);
4014
4015 EXPECT_EQ(std::string::npos, varyingTypeMismatch.find(lackOfFragmentShader));
4016
4017 glDetachShader(program, vs);
4018 glDetachShader(program, fs);
4019 glDeleteShader(vs);
4020 glDeleteShader(fs);
4021 glDeleteProgram(program);
4022
4023 ASSERT_GL_NO_ERROR();
4024}
4025
Jiawei Shao881b7bf2017-12-25 11:18:37 +08004026// Validate error messages when the link mismatch occurs on the type of a non-struct varying.
4027TEST_P(GLSLTest, ErrorMessageOfVaryingMismatch)
4028{
4029 const std::string &vertexShader =
4030 R"(
4031
4032 attribute vec4 inputAttribute;
4033 varying vec4 vertex_out;
4034 void main()
4035 {
4036 vertex_out = inputAttribute;
4037 gl_Position = inputAttribute;
4038 })";
4039
4040 const std::string &fragmentShader =
4041 R"(
4042
4043 precision mediump float;
4044 varying float vertex_out;
4045 void main()
4046 {
4047 gl_FragColor = vec4(vertex_out, 0.0, 0.0, 1.0);
4048 })";
4049
4050 validateComponentsInErrorMessage(vertexShader, fragmentShader, "Types", "varying 'vertex_out'");
4051}
4052
4053// Validate error messages when the link mismatch occurs on the name of a varying field.
4054TEST_P(GLSLTest_ES3, ErrorMessageOfVaryingStructFieldNameMismatch)
4055{
4056 const std::string &vertexShader =
4057 R"(#version 300 es
4058
4059 in vec4 inputAttribute;
4060 struct S {
4061 float val1;
4062 vec4 val2;
4063 };
4064 out S vertex_out;
4065 void main()
4066 {
4067 vertex_out.val2 = inputAttribute;
4068 vertex_out.val1 = inputAttribute[0];
4069 gl_Position = inputAttribute;
4070 })";
4071
4072 const std::string &fragmentShader =
4073 R"(#version 300 es
4074
4075 precision mediump float;
4076 struct S {
4077 float val1;
4078 vec4 val3;
4079 };
4080 in S vertex_out;
4081 layout (location = 0) out vec4 frag_out;
4082 void main()
4083 {
4084 frag_out = vec4(vertex_out.val1, 0.0, 0.0, 1.0);
4085 })";
4086
4087 validateComponentsInErrorMessage(vertexShader, fragmentShader, "Field names",
4088 "varying 'vertex_out'");
4089}
4090
4091// Validate error messages when the link mismatch occurs on the type of a varying field.
4092TEST_P(GLSLTest_ES3, ErrorMessageOfVaryingStructFieldMismatch)
4093{
4094 const std::string &vertexShader =
4095 R"(#version 300 es
4096
4097 in vec4 inputAttribute;
4098 struct S {
4099 float val1;
4100 vec4 val2;
4101 };
4102 out S vertex_out;
4103 void main()
4104 {
4105 vertex_out.val2 = inputAttribute;
4106 vertex_out.val1 = inputAttribute[0];
4107 gl_Position = inputAttribute;
4108 })";
4109
4110 const std::string &fragmentShader =
4111 R"(#version 300 es
4112
4113 precision mediump float;
4114 struct S {
4115 float val1;
4116 vec2 val2;
4117 };
4118 in S vertex_out;
4119 layout (location = 0) out vec4 frag_out;
4120 void main()
4121 {
4122 frag_out = vec4(vertex_out.val1, 0.0, 0.0, 1.0);
4123 })";
4124
4125 validateComponentsInErrorMessage(vertexShader, fragmentShader, "Types",
4126 "varying 'vertex_out' member 'vertex_out.val2'");
4127}
4128
4129// Validate error messages when the link mismatch occurs on the name of a struct member of a uniform
4130// field.
4131TEST_P(GLSLTest, ErrorMessageOfLinkUniformStructFieldNameMismatch)
4132{
4133 const std::string &vertexShader =
4134 R"(
4135
4136 struct T
4137 {
4138 vec2 t1;
4139 vec3 t2;
4140 };
4141 struct S {
4142 T val1;
4143 vec4 val2;
4144 };
4145 uniform S uni;
4146
4147 attribute vec4 inputAttribute;
4148 varying vec4 vertex_out;
4149 void main()
4150 {
4151 vertex_out = uni.val2;
4152 gl_Position = inputAttribute;
4153 })";
4154
4155 const std::string &fragmentShader =
4156 R"(
4157
4158 precision highp float;
4159 struct T
4160 {
4161 vec2 t1;
4162 vec3 t3;
4163 };
4164 struct S {
4165 T val1;
4166 vec4 val2;
4167 };
4168 uniform S uni;
4169
4170 varying vec4 vertex_out;
4171 void main()
4172 {
4173 gl_FragColor = vec4(uni.val1.t1[0], 0.0, 0.0, 1.0);
4174 })";
4175
4176 validateComponentsInErrorMessage(vertexShader, fragmentShader, "Field names",
4177 "uniform 'uni' member 'uni.val1'");
4178}
4179
4180// Validate error messages when the link mismatch occurs on the type of a non-struct uniform block
4181// field.
4182TEST_P(GLSLTest_ES3, ErrorMessageOfLinkInterfaceBlockFieldMismatch)
4183{
4184 const std::string &vertexShader =
4185 R"(#version 300 es
4186
4187 uniform S {
4188 vec2 val1;
4189 vec4 val2;
4190 } uni;
4191
4192 in vec4 inputAttribute;
4193 out vec4 vertex_out;
4194 void main()
4195 {
4196 vertex_out = uni.val2;
4197 gl_Position = inputAttribute;
4198 })";
4199
4200 const std::string &fragmentShader =
4201 R"(#version 300 es
4202
4203 precision highp float;
4204 uniform S {
4205 vec2 val1;
4206 vec3 val2;
4207 } uni;
4208
4209 in vec4 vertex_out;
4210 layout (location = 0) out vec4 frag_out;
4211 void main()
4212 {
4213 frag_out = vec4(uni.val1[0], 0.0, 0.0, 1.0);
4214 })";
4215
4216 validateComponentsInErrorMessage(vertexShader, fragmentShader, "Types",
4217 "interface block 'S' member 'S.val2'");
4218}
4219
4220// Validate error messages when the link mismatch occurs on the type of a member of a uniform block
4221// struct field.
4222TEST_P(GLSLTest_ES3, ErrorMessageOfLinkInterfaceBlockStructFieldMismatch)
4223{
4224 const std::string &vertexShader =
4225 R"(#version 300 es
4226
4227 struct T
4228 {
4229 vec2 t1;
4230 vec3 t2;
4231 };
4232 uniform S {
4233 T val1;
4234 vec4 val2;
4235 } uni;
4236
4237 in vec4 inputAttribute;
4238 out vec4 vertex_out;
4239 void main()
4240 {
4241 vertex_out = uni.val2;
4242 gl_Position = inputAttribute;
4243 })";
4244
4245 const std::string &fragmentShader =
4246 R"(#version 300 es
4247
4248 precision highp float;
4249 struct T
4250 {
4251 vec2 t1;
4252 vec4 t2;
4253 };
4254 uniform S {
4255 T val1;
4256 vec4 val2;
4257 } uni;
4258
4259 in vec4 vertex_out;
4260 layout (location = 0) out vec4 frag_out;
4261 void main()
4262 {
4263 frag_out = vec4(uni.val1.t1[0], 0.0, 0.0, 1.0);
4264 })";
4265
4266 validateComponentsInErrorMessage(vertexShader, fragmentShader, "Types",
4267 "interface block 'S' member 'S.val1.t2'");
4268}
4269
Jamie Madillfa05f602015-05-07 13:47:11 -04004270// 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 -05004271ANGLE_INSTANTIATE_TEST(GLSLTest,
4272 ES2_D3D9(),
4273 ES2_D3D11(),
4274 ES2_D3D11_FL9_3(),
4275 ES2_OPENGL(),
4276 ES3_OPENGL(),
4277 ES2_OPENGLES(),
4278 ES3_OPENGLES());
Jamie Madillfa05f602015-05-07 13:47:11 -04004279
4280// 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 -05004281ANGLE_INSTANTIATE_TEST(GLSLTest_ES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
Jamie Madill192745a2016-12-22 15:58:21 -05004282
4283ANGLE_INSTANTIATE_TEST(WebGLGLSLTest, ES2_D3D11(), ES2_OPENGL(), ES2_OPENGLES());
Olli Etuaho9250cb22017-01-21 10:51:27 +00004284
4285ANGLE_INSTANTIATE_TEST(GLSLTest_ES31, ES31_D3D11(), ES31_OPENGL(), ES31_OPENGLES());