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