blob: 45ef2d565e07073b327f0a12c9dbc99199032790 [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)
Yunchao He9550c602018-02-13 14:47:05 +0800545 ANGLE_SKIP_TEST_IF(IsDesktopOpenGL() && (IsOSX() || !IsNVIDIA()));
Geoff Lange0cc2a42016-01-20 10:58:17 -0500546
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300547 const std::string fragmentShaderSource =
548 R"(precision mediump float;
Jamie Madillbfa91f42014-06-05 15:45:18 -0400549
550 struct T
551 {
552 float f;
553 };
554
555 void main()
556 {
557 T a;
558
559 struct T
560 {
561 float q;
562 };
563
564 T b;
565
566 gl_FragColor = vec4(1, 0, 0, 1);
567 gl_FragColor.a += a.f;
568 gl_FragColor.a += b.q;
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300569 })";
Jamie Madillbfa91f42014-06-05 15:45:18 -0400570
Jamie Madill5599c8f2014-08-26 13:16:39 -0400571 GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
Jamie Madillbfa91f42014-06-05 15:45:18 -0400572 EXPECT_NE(0u, program);
573}
574
Jamie Madillfa05f602015-05-07 13:47:11 -0400575TEST_P(GLSLTest, ScopedStructsBug)
Jamie Madillbfa91f42014-06-05 15:45:18 -0400576{
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300577 const std::string fragmentShaderSource =
578 R"(precision mediump float;
Jamie Madill96509e42014-05-29 14:33:27 -0400579
580 struct T_0
581 {
582 float f;
583 };
584
585 void main()
586 {
587 gl_FragColor = vec4(1, 0, 0, 1);
588
589 struct T
590 {
591 vec2 v;
592 };
593
594 T_0 a;
595 T b;
596
597 gl_FragColor.a += a.f;
598 gl_FragColor.a += b.v.x;
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300599 })";
Jamie Madill96509e42014-05-29 14:33:27 -0400600
Jamie Madill5599c8f2014-08-26 13:16:39 -0400601 GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
Jamie Madill2bf8b372014-06-16 17:18:51 -0400602 EXPECT_NE(0u, program);
603}
604
Jamie Madillfa05f602015-05-07 13:47:11 -0400605TEST_P(GLSLTest, DxPositionBug)
Jamie Madill2bf8b372014-06-16 17:18:51 -0400606{
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300607 const std::string &vertexShaderSource =
608 R"(attribute vec4 inputAttribute;
Jamie Madill2bf8b372014-06-16 17:18:51 -0400609 varying float dx_Position;
610 void main()
611 {
612 gl_Position = vec4(inputAttribute);
613 dx_Position = 0.0;
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300614 })";
Jamie Madill2bf8b372014-06-16 17:18:51 -0400615
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300616 const std::string &fragmentShaderSource =
617 R"(precision mediump float;
Jamie Madill2bf8b372014-06-16 17:18:51 -0400618
619 varying float dx_Position;
620
621 void main()
622 {
623 gl_FragColor = vec4(dx_Position, 0, 0, 1);
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300624 })";
Jamie Madill2bf8b372014-06-16 17:18:51 -0400625
Jamie Madill5599c8f2014-08-26 13:16:39 -0400626 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
Jamie Madill96509e42014-05-29 14:33:27 -0400627 EXPECT_NE(0u, program);
628}
Jamie Madill4836d222014-07-24 06:55:51 -0400629
Jamie Madillfa05f602015-05-07 13:47:11 -0400630TEST_P(GLSLTest, ElseIfRewriting)
Jamie Madill4836d222014-07-24 06:55:51 -0400631{
632 const std::string &vertexShaderSource =
633 "attribute vec4 a_position;\n"
634 "varying float v;\n"
635 "void main() {\n"
636 " gl_Position = a_position;\n"
637 " v = 1.0;\n"
638 " if (a_position.x <= 0.5) {\n"
639 " v = 0.0;\n"
640 " } else if (a_position.x >= 0.5) {\n"
641 " v = 2.0;\n"
642 " }\n"
643 "}\n";
644
645 const std::string &fragmentShaderSource =
646 "precision highp float;\n"
647 "varying float v;\n"
648 "void main() {\n"
649 " vec4 color = vec4(1.0, 0.0, 0.0, 1.0);\n"
650 " if (v >= 1.0) color = vec4(0.0, 1.0, 0.0, 1.0);\n"
651 " if (v >= 2.0) color = vec4(0.0, 0.0, 1.0, 1.0);\n"
652 " gl_FragColor = color;\n"
653 "}\n";
654
Jamie Madill5599c8f2014-08-26 13:16:39 -0400655 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
Jamie Madill4836d222014-07-24 06:55:51 -0400656 ASSERT_NE(0u, program);
657
658 drawQuad(program, "a_position", 0.5f);
Jamie Madill4836d222014-07-24 06:55:51 -0400659
660 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
661 EXPECT_PIXEL_EQ(getWindowWidth()-1, 0, 0, 255, 0, 255);
662}
663
Jamie Madillfa05f602015-05-07 13:47:11 -0400664TEST_P(GLSLTest, TwoElseIfRewriting)
Jamie Madill4836d222014-07-24 06:55:51 -0400665{
666 const std::string &vertexShaderSource =
667 "attribute vec4 a_position;\n"
668 "varying float v;\n"
669 "void main() {\n"
670 " gl_Position = a_position;\n"
Jamie Madill778d5272014-08-04 13:13:25 -0400671 " if (a_position.x == 0.0) {\n"
Jamie Madill4836d222014-07-24 06:55:51 -0400672 " v = 1.0;\n"
673 " } else if (a_position.x > 0.5) {\n"
674 " v = 0.0;\n"
675 " } else if (a_position.x > 0.75) {\n"
676 " v = 0.5;\n"
677 " }\n"
678 "}\n";
679
680 const std::string &fragmentShaderSource =
681 "precision highp float;\n"
682 "varying float v;\n"
683 "void main() {\n"
684 " gl_FragColor = vec4(v, 0.0, 0.0, 1.0);\n"
685 "}\n";
686
Jamie Madill5599c8f2014-08-26 13:16:39 -0400687 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
Jamie Madill4836d222014-07-24 06:55:51 -0400688 EXPECT_NE(0u, program);
689}
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400690
Jamie Madillfa05f602015-05-07 13:47:11 -0400691TEST_P(GLSLTest, FrontFacingAndVarying)
Jamie Madille6256f82014-09-17 10:31:15 -0400692{
Geoff Langdd323e92015-06-09 15:16:31 -0400693 EGLPlatformParameters platform = GetParam().eglParameters;
Austin Kinross8b695ee2015-03-12 13:12:20 -0700694
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300695 const std::string vertexShaderSource =
696 R"(attribute vec4 a_position;
Jamie Madille6256f82014-09-17 10:31:15 -0400697 varying float v_varying;
698 void main()
699 {
700 v_varying = a_position.x;
701 gl_Position = a_position;
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300702 })";
Jamie Madille6256f82014-09-17 10:31:15 -0400703
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300704 const std::string fragmentShaderSource =
705 R"(precision mediump float;
Jamie Madille6256f82014-09-17 10:31:15 -0400706 varying float v_varying;
707 void main()
708 {
709 vec4 c;
710
711 if (gl_FrontFacing)
712 {
713 c = vec4(v_varying, 0, 0, 1.0);
714 }
715 else
716 {
717 c = vec4(0, v_varying, 0, 1.0);
718 }
719 gl_FragColor = c;
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300720 })";
Jamie Madille6256f82014-09-17 10:31:15 -0400721
722 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
Austin Kinross02df7962015-07-01 10:03:42 -0700723
724 // Compilation should fail on D3D11 feature level 9_3, since gl_FrontFacing isn't supported.
725 if (platform.renderer == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
726 {
727 if (platform.majorVersion == 9 && platform.minorVersion == 3)
728 {
729 EXPECT_EQ(0u, program);
730 return;
731 }
732 }
733
734 // Otherwise, compilation should succeed
Jamie Madille6256f82014-09-17 10:31:15 -0400735 EXPECT_NE(0u, program);
736}
737
Jamie Madill2f348d22017-06-05 10:50:59 -0400738// Test that we can release the shader compiler and still compile things properly.
739TEST_P(GLSLTest, ReleaseCompilerThenCompile)
740{
741 const std::string &simpleVS =
742 "attribute vec4 position; void main() { gl_Position = position; }";
743 const std::string &simpleFS = "void main() { gl_FragColor = vec4(1, 0, 0, 1); }";
744
745 // Draw with the first program.
746 ANGLE_GL_PROGRAM(program1, simpleVS, simpleFS);
747 drawQuad(program1, "position", 0.5f);
748 ASSERT_GL_NO_ERROR();
749 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
750
751 // Clear and release shader compiler.
752 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
753 glClear(GL_COLOR_BUFFER_BIT);
754 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
755 glReleaseShaderCompiler();
756 ASSERT_GL_NO_ERROR();
757
758 // Draw with a second program.
759 ANGLE_GL_PROGRAM(program2, simpleVS, simpleFS);
760 drawQuad(program2, "position", 0.5f);
761 ASSERT_GL_NO_ERROR();
762 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
763}
764
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400765// Verify that linking shaders declaring different shading language versions fails.
766TEST_P(GLSLTest_ES3, VersionMismatch)
767{
768 const std::string fragmentShaderSource100 =
769 "precision mediump float;\n"
770 "varying float v_varying;\n"
771 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
772
773 const std::string vertexShaderSource100 =
774 "attribute vec4 a_position;\n"
775 "varying float v_varying;\n"
776 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
777
778 const std::string fragmentShaderSource300 =
779 "#version 300 es\n"
780 "precision mediump float;\n"
781 "in float v_varying;\n"
782 "out vec4 my_FragColor;\n"
783 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
784
785 const std::string vertexShaderSource300 =
786 "#version 300 es\n"
787 "in vec4 a_position;\n"
788 "out float v_varying;\n"
789 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
790
791 GLuint program = CompileProgram(vertexShaderSource300, fragmentShaderSource100);
792 EXPECT_EQ(0u, program);
793
794 program = CompileProgram(vertexShaderSource100, fragmentShaderSource300);
795 EXPECT_EQ(0u, program);
796}
797
798// Verify that declaring varying as invariant only in vertex shader fails in ESSL 1.00.
799TEST_P(GLSLTest, InvariantVaryingOut)
800{
801 const std::string fragmentShaderSource =
802 "precision mediump float;\n"
803 "varying float v_varying;\n"
804 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
805
806 const std::string vertexShaderSource =
807 "attribute vec4 a_position;\n"
808 "invariant varying float v_varying;\n"
809 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
810
811 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
812 EXPECT_EQ(0u, program);
813}
814
815// Verify that declaring varying as invariant only in vertex shader succeeds in ESSL 3.00.
816TEST_P(GLSLTest_ES3, InvariantVaryingOut)
817{
818 // TODO: ESSL 3.00 -> GLSL 1.20 translation should add "invariant" in fragment shader
819 // for varyings which are invariant in vertex shader (http://anglebug.com/1293)
Yunchao He9550c602018-02-13 14:47:05 +0800820 ANGLE_SKIP_TEST_IF(IsDesktopOpenGL());
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400821
822 const std::string fragmentShaderSource =
823 "#version 300 es\n"
824 "precision mediump float;\n"
825 "in float v_varying;\n"
826 "out vec4 my_FragColor;\n"
827 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
828
829 const std::string vertexShaderSource =
830 "#version 300 es\n"
831 "in vec4 a_position;\n"
832 "invariant out float v_varying;\n"
833 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
834
835 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
836 EXPECT_NE(0u, program);
837}
838
839// Verify that declaring varying as invariant only in fragment shader fails in ESSL 1.00.
Jamie Madillfa05f602015-05-07 13:47:11 -0400840TEST_P(GLSLTest, InvariantVaryingIn)
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400841{
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400842 const std::string fragmentShaderSource =
843 "precision mediump float;\n"
844 "invariant varying float v_varying;\n"
845 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
Geoff Lange0cc2a42016-01-20 10:58:17 -0500846
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400847 const std::string vertexShaderSource =
848 "attribute vec4 a_position;\n"
849 "varying float v_varying;\n"
850 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400851
Jamie Madill5599c8f2014-08-26 13:16:39 -0400852 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400853 EXPECT_EQ(0u, program);
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400854}
855
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400856// Verify that declaring varying as invariant only in fragment shader fails in ESSL 3.00.
857TEST_P(GLSLTest_ES3, InvariantVaryingIn)
858{
859 const std::string fragmentShaderSource =
860 "#version 300 es\n"
861 "precision mediump float;\n"
862 "invariant in float v_varying;\n"
863 "out vec4 my_FragColor;\n"
864 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
865
866 const std::string vertexShaderSource =
867 "#version 300 es\n"
868 "in vec4 a_position;\n"
869 "out float v_varying;\n"
870 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
871
872 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
873 EXPECT_EQ(0u, program);
874}
875
876// Verify that declaring varying as invariant in both shaders succeeds in ESSL 1.00.
Jamie Madillfa05f602015-05-07 13:47:11 -0400877TEST_P(GLSLTest, InvariantVaryingBoth)
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400878{
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400879 const std::string fragmentShaderSource =
880 "precision mediump float;\n"
881 "invariant varying float v_varying;\n"
882 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400883
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400884 const std::string vertexShaderSource =
885 "attribute vec4 a_position;\n"
886 "invariant varying float v_varying;\n"
887 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400888
Jamie Madill5599c8f2014-08-26 13:16:39 -0400889 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400890 EXPECT_NE(0u, program);
891}
892
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400893// Verify that declaring varying as invariant in both shaders fails in ESSL 3.00.
894TEST_P(GLSLTest_ES3, InvariantVaryingBoth)
895{
896 const std::string fragmentShaderSource =
897 "#version 300 es\n"
898 "precision mediump float;\n"
899 "invariant in float v_varying;\n"
900 "out vec4 my_FragColor;\n"
901 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
902
903 const std::string vertexShaderSource =
904 "#version 300 es\n"
905 "in vec4 a_position;\n"
906 "invariant out float v_varying;\n"
907 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
908
909 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
910 EXPECT_EQ(0u, program);
911}
912
913// Verify that declaring gl_Position as invariant succeeds in ESSL 1.00.
Jamie Madillfa05f602015-05-07 13:47:11 -0400914TEST_P(GLSLTest, InvariantGLPosition)
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400915{
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400916 const std::string fragmentShaderSource =
917 "precision mediump float;\n"
918 "varying float v_varying;\n"
919 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400920
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400921 const std::string vertexShaderSource =
922 "attribute vec4 a_position;\n"
923 "invariant gl_Position;\n"
924 "varying float v_varying;\n"
925 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400926
Jamie Madill5599c8f2014-08-26 13:16:39 -0400927 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400928 EXPECT_NE(0u, program);
929}
930
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400931// Verify that declaring gl_Position as invariant succeeds in ESSL 3.00.
932TEST_P(GLSLTest_ES3, InvariantGLPosition)
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400933{
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400934 const std::string fragmentShaderSource =
935 "#version 300 es\n"
936 "precision mediump float;\n"
937 "in float v_varying;\n"
938 "out vec4 my_FragColor;\n"
939 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
940
941 const std::string vertexShaderSource =
942 "#version 300 es\n"
943 "in vec4 a_position;\n"
944 "invariant gl_Position;\n"
945 "out float v_varying;\n"
946 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
947
948 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
949 EXPECT_NE(0u, program);
950}
951
952// Verify that using invariant(all) in both shaders succeeds in ESSL 1.00.
953TEST_P(GLSLTest, InvariantAllBoth)
954{
955 // TODO: ESSL 1.00 -> GLSL 1.20 translation should add "invariant" in fragment shader
956 // for varyings which are invariant in vertex shader individually,
957 // and remove invariant(all) from fragment shader (http://anglebug.com/1293)
Yunchao He9550c602018-02-13 14:47:05 +0800958 ANGLE_SKIP_TEST_IF(IsDesktopOpenGL());
Geoff Lange0cc2a42016-01-20 10:58:17 -0500959
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400960 const std::string fragmentShaderSource =
961 "#pragma STDGL invariant(all)\n"
962 "precision mediump float;\n"
963 "varying float v_varying;\n"
964 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400965
966 const std::string vertexShaderSource =
967 "#pragma STDGL invariant(all)\n"
968 "attribute vec4 a_position;\n"
969 "varying float v_varying;\n"
970 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
971
Jamie Madill5599c8f2014-08-26 13:16:39 -0400972 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400973 EXPECT_NE(0u, program);
974}
Austin Kinrossaf875522014-08-25 21:06:07 -0700975
Geoff Lang156d7192016-07-21 16:11:00 -0400976// Verify that functions without return statements still compile
977TEST_P(GLSLTest, MissingReturnFloat)
978{
979 const std::string vertexShaderSource =
980 "varying float v_varying;\n"
981 "float f() { if (v_varying > 0.0) return 1.0; }\n"
982 "void main() { gl_Position = vec4(f(), 0, 0, 1); }\n";
983
984 const std::string fragmentShaderSource =
985 "precision mediump float;\n"
986 "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
987
988 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
989 EXPECT_NE(0u, program);
990}
991
992// Verify that functions without return statements still compile
993TEST_P(GLSLTest, MissingReturnVec2)
994{
995 const std::string vertexShaderSource =
996 "varying float v_varying;\n"
997 "vec2 f() { if (v_varying > 0.0) return vec2(1.0, 1.0); }\n"
998 "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
999
1000 const std::string fragmentShaderSource =
1001 "precision mediump float;\n"
1002 "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
1003
1004 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1005 EXPECT_NE(0u, program);
1006}
1007
1008// Verify that functions without return statements still compile
1009TEST_P(GLSLTest, MissingReturnVec3)
1010{
1011 const std::string vertexShaderSource =
1012 "varying float v_varying;\n"
1013 "vec3 f() { if (v_varying > 0.0) return vec3(1.0, 1.0, 1.0); }\n"
1014 "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
1015
1016 const std::string fragmentShaderSource =
1017 "precision mediump float;\n"
1018 "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
1019
1020 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1021 EXPECT_NE(0u, program);
1022}
1023
1024// Verify that functions without return statements still compile
1025TEST_P(GLSLTest, MissingReturnVec4)
1026{
1027 const std::string vertexShaderSource =
1028 "varying float v_varying;\n"
1029 "vec4 f() { if (v_varying > 0.0) return vec4(1.0, 1.0, 1.0, 1.0); }\n"
1030 "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
1031
1032 const std::string fragmentShaderSource =
1033 "precision mediump float;\n"
1034 "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
1035
1036 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1037 EXPECT_NE(0u, program);
1038}
1039
1040// Verify that functions without return statements still compile
1041TEST_P(GLSLTest, MissingReturnIVec4)
1042{
1043 const std::string vertexShaderSource =
1044 "varying float v_varying;\n"
1045 "ivec4 f() { if (v_varying > 0.0) return ivec4(1, 1, 1, 1); }\n"
1046 "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
1047
1048 const std::string fragmentShaderSource =
1049 "precision mediump float;\n"
1050 "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
1051
1052 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1053 EXPECT_NE(0u, program);
1054}
1055
1056// Verify that functions without return statements still compile
1057TEST_P(GLSLTest, MissingReturnMat4)
1058{
1059 const std::string vertexShaderSource =
1060 "varying float v_varying;\n"
1061 "mat4 f() { if (v_varying > 0.0) return mat4(1.0); }\n"
1062 "void main() { gl_Position = vec4(f()[0][0], 0, 0, 1); }\n";
1063
1064 const std::string fragmentShaderSource =
1065 "precision mediump float;\n"
1066 "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
1067
1068 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1069 EXPECT_NE(0u, program);
1070}
1071
1072// Verify that functions without return statements still compile
1073TEST_P(GLSLTest, MissingReturnStruct)
1074{
1075 const std::string vertexShaderSource =
1076 "varying float v_varying;\n"
1077 "struct s { float a; int b; vec2 c; };\n"
1078 "s f() { if (v_varying > 0.0) return s(1.0, 1, vec2(1.0, 1.0)); }\n"
1079 "void main() { gl_Position = vec4(f().a, 0, 0, 1); }\n";
1080
1081 const std::string fragmentShaderSource =
1082 "precision mediump float;\n"
1083 "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
1084
1085 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1086 EXPECT_NE(0u, program);
1087}
1088
1089// Verify that functions without return statements still compile
1090TEST_P(GLSLTest_ES3, MissingReturnArray)
1091{
1092 const std::string vertexShaderSource =
1093 "#version 300 es\n"
1094 "in float v_varying;\n"
1095 "vec2[2] f() { if (v_varying > 0.0) { return vec2[2](vec2(1.0, 1.0), vec2(1.0, 1.0)); } }\n"
1096 "void main() { gl_Position = vec4(f()[0].x, 0, 0, 1); }\n";
1097
1098 const std::string fragmentShaderSource =
1099 "#version 300 es\n"
1100 "precision mediump float;\n"
1101 "out vec4 my_FragColor;\n"
1102 "void main() { my_FragColor = vec4(0, 0, 0, 1); }\n";
1103
1104 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1105 EXPECT_NE(0u, program);
1106}
1107
1108// Verify that functions without return statements still compile
1109TEST_P(GLSLTest_ES3, MissingReturnArrayOfStructs)
1110{
1111 const std::string vertexShaderSource =
1112 "#version 300 es\n"
1113 "in float v_varying;\n"
1114 "struct s { float a; int b; vec2 c; };\n"
1115 "s[2] f() { if (v_varying > 0.0) { return s[2](s(1.0, 1, vec2(1.0, 1.0)), s(1.0, 1, "
1116 "vec2(1.0, 1.0))); } }\n"
1117 "void main() { gl_Position = vec4(f()[0].a, 0, 0, 1); }\n";
1118
1119 const std::string fragmentShaderSource =
1120 "#version 300 es\n"
1121 "precision mediump float;\n"
1122 "out vec4 my_FragColor;\n"
1123 "void main() { my_FragColor = vec4(0, 0, 0, 1); }\n";
1124
1125 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1126 EXPECT_NE(0u, program);
1127}
1128
Corentin Wallez509e4562016-08-25 14:55:44 -04001129// Verify that functions without return statements still compile
1130TEST_P(GLSLTest_ES3, MissingReturnStructOfArrays)
1131{
Olli Etuahodf7d13e2017-05-30 13:53:45 +03001132 // TODO(cwallez) remove the suppression once NVIDIA drivers are updated across trybots, drivers
1133 // since late 2016 should have the fix. Last check on 2017-05-30 revealed that the Windows
1134 // Server 2008 bots still had the old, failing drivers.
Yunchao He9550c602018-02-13 14:47:05 +08001135 // It disallows returning structure of arrays on NVIDIA OpenGL ES.
1136 ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGLES());
Corentin Wallez509e4562016-08-25 14:55:44 -04001137
1138 const std::string vertexShaderSource =
1139 "#version 300 es\n"
1140 "in float v_varying;\n"
1141 "struct s { float a[2]; int b[2]; vec2 c[2]; };\n"
1142 "s f() { if (v_varying > 0.0) { return s(float[2](1.0, 1.0), int[2](1, 1),"
1143 "vec2[2](vec2(1.0, 1.0), vec2(1.0, 1.0))); } }\n"
1144 "void main() { gl_Position = vec4(f().a[0], 0, 0, 1); }\n";
1145
1146 const std::string fragmentShaderSource =
1147 "#version 300 es\n"
1148 "precision mediump float;\n"
1149 "out vec4 my_FragColor;\n"
1150 "void main() { my_FragColor = vec4(0, 0, 0, 1); }\n";
1151
1152 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1153 EXPECT_NE(0u, program);
1154}
1155
Yuly Novikova1f6dc92016-06-15 23:27:04 -04001156// Verify that using invariant(all) in both shaders fails in ESSL 3.00.
1157TEST_P(GLSLTest_ES3, InvariantAllBoth)
1158{
1159 const std::string fragmentShaderSource =
1160 "#version 300 es\n"
1161 "#pragma STDGL invariant(all)\n"
1162 "precision mediump float;\n"
1163 "in float v_varying;\n"
1164 "out vec4 my_FragColor;\n"
1165 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1166
1167 const std::string vertexShaderSource =
1168 "#version 300 es\n"
1169 "#pragma STDGL invariant(all)\n"
1170 "in vec4 a_position;\n"
1171 "out float v_varying;\n"
1172 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1173
1174 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1175 EXPECT_EQ(0u, program);
1176}
1177
1178// Verify that using invariant(all) only in fragment shader fails in ESSL 1.00.
1179TEST_P(GLSLTest, InvariantAllIn)
1180{
1181 const std::string fragmentShaderSource =
1182 "#pragma STDGL invariant(all)\n"
1183 "precision mediump float;\n"
1184 "varying float v_varying;\n"
1185 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1186
1187 const std::string vertexShaderSource =
1188 "attribute vec4 a_position;\n"
1189 "varying float v_varying;\n"
1190 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1191
1192 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1193 EXPECT_EQ(0u, program);
1194}
1195
1196// Verify that using invariant(all) only in fragment shader fails in ESSL 3.00.
1197TEST_P(GLSLTest_ES3, InvariantAllIn)
1198{
1199 const std::string fragmentShaderSource =
1200 "#version 300 es\n"
1201 "#pragma STDGL invariant(all)\n"
1202 "precision mediump float;\n"
1203 "in float v_varying;\n"
1204 "out vec4 my_FragColor;\n"
1205 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1206
1207 const std::string vertexShaderSource =
1208 "#version 300 es\n"
1209 "in vec4 a_position;\n"
1210 "out float v_varying;\n"
1211 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1212
1213 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1214 EXPECT_EQ(0u, program);
1215}
1216
1217// Verify that using invariant(all) only in vertex shader fails in ESSL 1.00.
1218TEST_P(GLSLTest, InvariantAllOut)
1219{
1220 const std::string fragmentShaderSource =
1221 "precision mediump float;\n"
1222 "varying float v_varying;\n"
1223 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1224
1225 const std::string vertexShaderSource =
1226 "#pragma STDGL invariant(all)\n"
1227 "attribute vec4 a_position;\n"
1228 "varying float v_varying;\n"
1229 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1230
1231 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1232 EXPECT_EQ(0u, program);
1233}
1234
1235// Verify that using invariant(all) only in vertex shader succeeds in ESSL 3.00.
1236TEST_P(GLSLTest_ES3, InvariantAllOut)
1237{
1238 // TODO: ESSL 3.00 -> GLSL 1.20 translation should add "invariant" in fragment shader
1239 // for varyings which are invariant in vertex shader,
1240 // because of invariant(all) being used in vertex shader (http://anglebug.com/1293)
Yunchao He9550c602018-02-13 14:47:05 +08001241 ANGLE_SKIP_TEST_IF(IsDesktopOpenGL());
Yuly Novikova1f6dc92016-06-15 23:27:04 -04001242
1243 const std::string fragmentShaderSource =
1244 "#version 300 es\n"
1245 "precision mediump float;\n"
1246 "in float v_varying;\n"
1247 "out vec4 my_FragColor;\n"
1248 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1249
1250 const std::string vertexShaderSource =
1251 "#version 300 es\n"
1252 "#pragma STDGL invariant(all)\n"
1253 "in vec4 a_position;\n"
1254 "out float v_varying;\n"
1255 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1256
1257 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1258 EXPECT_NE(0u, program);
1259}
1260
Jamie Madillfa05f602015-05-07 13:47:11 -04001261TEST_P(GLSLTest, MaxVaryingVec4)
Austin Kinross8b695ee2015-03-12 13:12:20 -07001262{
Yunchao He9550c602018-02-13 14:47:05 +08001263 // TODO(geofflang): Find out why this doesn't compile on Apple AMD OpenGL drivers
Geoff Lang69accbd2016-01-25 16:22:32 -05001264 // (http://anglebug.com/1291)
Yunchao He9550c602018-02-13 14:47:05 +08001265 ANGLE_SKIP_TEST_IF(IsOSX() && IsAMD() && IsOpenGL());
Geoff Lang69accbd2016-01-25 16:22:32 -05001266
Austin Kinross8b695ee2015-03-12 13:12:20 -07001267 GLint maxVaryings = 0;
1268 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1269
1270 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, false, false, false, true);
1271}
1272
Jamie Madill61d53252018-01-31 14:49:24 -05001273// Verify we can pack registers with one builtin varying.
1274TEST_P(GLSLTest, MaxVaryingVec4_OneBuiltin)
Austin Kinross8b695ee2015-03-12 13:12:20 -07001275{
1276 GLint maxVaryings = 0;
1277 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1278
Jamie Madill61d53252018-01-31 14:49:24 -05001279 // Generate shader code that uses gl_FragCoord.
1280 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 1, 0, true, false, false, true);
1281}
1282
1283// Verify we can pack registers with two builtin varyings.
1284TEST_P(GLSLTest, MaxVaryingVec4_TwoBuiltins)
1285{
1286 GLint maxVaryings = 0;
1287 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1288
1289 // Generate shader code that uses gl_FragCoord and gl_PointCoord.
Austin Kinross8b695ee2015-03-12 13:12:20 -07001290 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 2, 0, true, true, false, true);
1291}
1292
Jamie Madill61d53252018-01-31 14:49:24 -05001293// Verify we can pack registers with three builtin varyings.
1294TEST_P(GLSLTest, MaxVaryingVec4_ThreeBuiltins)
Austin Kinross8b695ee2015-03-12 13:12:20 -07001295{
1296 GLint maxVaryings = 0;
1297 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1298
1299 // Generate shader code that uses gl_FragCoord, gl_PointCoord and gl_PointSize.
Jamie Madill61d53252018-01-31 14:49:24 -05001300 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 3, 0, true, true, true, true);
1301}
1302
1303// This covers a problematic case in D3D9 - we are limited by the number of available semantics,
1304// rather than total register use.
1305TEST_P(GLSLTest, MaxVaryingsSpecialCases)
1306{
1307 ANGLE_SKIP_TEST_IF(!IsD3D9());
1308
1309 GLint maxVaryings = 0;
1310 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1311
1312 VaryingTestBase(maxVaryings, 0, 0, 0, 0, 0, 0, 0, true, false, false, false);
1313 VaryingTestBase(maxVaryings - 1, 0, 0, 0, 0, 0, 0, 0, true, true, false, false);
1314 VaryingTestBase(maxVaryings - 2, 0, 0, 0, 0, 0, 0, 0, true, true, false, true);
1315
1316 // Special case for gl_PointSize: we get it for free on D3D9.
1317 VaryingTestBase(maxVaryings - 2, 0, 0, 0, 0, 0, 0, 0, true, true, true, true);
1318}
1319
1320// This covers a problematic case in D3D9 - we are limited by the number of available semantics,
1321// rather than total register use.
1322TEST_P(GLSLTest, MaxMinusTwoVaryingVec2PlusOneSpecialVariable)
1323{
1324 GLint maxVaryings = 0;
1325 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1326
1327 // Generate shader code that uses gl_FragCoord.
1328 VaryingTestBase(0, 0, maxVaryings, 0, 0, 0, 0, 0, true, false, false, !IsD3D9());
Austin Kinross8b695ee2015-03-12 13:12:20 -07001329}
1330
Jamie Madillfa05f602015-05-07 13:47:11 -04001331TEST_P(GLSLTest, MaxVaryingVec3)
Austin Kinrossaf875522014-08-25 21:06:07 -07001332{
1333 GLint maxVaryings = 0;
1334 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1335
Austin Kinross8b695ee2015-03-12 13:12:20 -07001336 VaryingTestBase(0, 0, 0, 0, maxVaryings, 0, 0, 0, false, false, false, true);
Austin Kinrossaf875522014-08-25 21:06:07 -07001337}
1338
Jamie Madillfa05f602015-05-07 13:47:11 -04001339TEST_P(GLSLTest, MaxVaryingVec3Array)
Austin Kinrossaf875522014-08-25 21:06:07 -07001340{
1341 GLint maxVaryings = 0;
1342 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1343
Austin Kinross8b695ee2015-03-12 13:12:20 -07001344 VaryingTestBase(0, 0, 0, 0, 0, maxVaryings / 2, 0, 0, false, false, false, true);
Austin Kinrossaf875522014-08-25 21:06:07 -07001345}
1346
Jamie Madill61d53252018-01-31 14:49:24 -05001347// Only fails on D3D9 because of packing limitations.
Jamie Madill9fc36822015-11-18 13:08:07 -05001348TEST_P(GLSLTest, MaxVaryingVec3AndOneFloat)
Austin Kinrossaf875522014-08-25 21:06:07 -07001349{
1350 GLint maxVaryings = 0;
1351 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1352
Jamie Madill61d53252018-01-31 14:49:24 -05001353 VaryingTestBase(1, 0, 0, 0, maxVaryings, 0, 0, 0, false, false, false, !IsD3D9());
Austin Kinrossaf875522014-08-25 21:06:07 -07001354}
1355
Jamie Madill61d53252018-01-31 14:49:24 -05001356// Only fails on D3D9 because of packing limitations.
Jamie Madill9fc36822015-11-18 13:08:07 -05001357TEST_P(GLSLTest, MaxVaryingVec3ArrayAndOneFloatArray)
Austin Kinrossaf875522014-08-25 21:06:07 -07001358{
1359 GLint maxVaryings = 0;
1360 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1361
Jamie Madill61d53252018-01-31 14:49:24 -05001362 VaryingTestBase(0, 1, 0, 0, 0, maxVaryings / 2, 0, 0, false, false, false, !IsD3D9());
Austin Kinrossaf875522014-08-25 21:06:07 -07001363}
1364
Jamie Madill61d53252018-01-31 14:49:24 -05001365// Only fails on D3D9 because of packing limitations.
Jamie Madill9fc36822015-11-18 13:08:07 -05001366TEST_P(GLSLTest, TwiceMaxVaryingVec2)
Austin Kinrossaf875522014-08-25 21:06:07 -07001367{
Yunchao He9550c602018-02-13 14:47:05 +08001368 // TODO(geofflang): Figure out why this fails on NVIDIA's GLES driver
1369 ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGLES());
Geoff Lange0cc2a42016-01-20 10:58:17 -05001370
Yunchao He9550c602018-02-13 14:47:05 +08001371 // TODO(geofflang): Find out why this doesn't compile on Apple AMD OpenGL drivers
Geoff Lang69accbd2016-01-25 16:22:32 -05001372 // (http://anglebug.com/1291)
Yunchao He9550c602018-02-13 14:47:05 +08001373 ANGLE_SKIP_TEST_IF(IsOSX() && IsAMD() && IsOpenGL());
Geoff Lang69accbd2016-01-25 16:22:32 -05001374
Austin Kinrossaf875522014-08-25 21:06:07 -07001375 GLint maxVaryings = 0;
1376 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1377
Jamie Madill61d53252018-01-31 14:49:24 -05001378 VaryingTestBase(0, 0, 2 * maxVaryings, 0, 0, 0, 0, 0, false, false, false, !IsD3D9());
Austin Kinrossaf875522014-08-25 21:06:07 -07001379}
1380
Jamie Madillbee59e02014-10-02 10:44:18 -04001381// Disabled because of a failure in D3D9
Jamie Madill9fc36822015-11-18 13:08:07 -05001382TEST_P(GLSLTest, MaxVaryingVec2Arrays)
Austin Kinrossaf875522014-08-25 21:06:07 -07001383{
Yunchao He9550c602018-02-13 14:47:05 +08001384 ANGLE_SKIP_TEST_IF(IsD3DSM3());
Jamie Madill9fc36822015-11-18 13:08:07 -05001385
Yunchao He9550c602018-02-13 14:47:05 +08001386 // TODO(geofflang): Figure out why this fails on NVIDIA's GLES driver
1387 ANGLE_SKIP_TEST_IF(IsOpenGLES());
Geoff Lange0cc2a42016-01-20 10:58:17 -05001388
Yunchao He9550c602018-02-13 14:47:05 +08001389 // TODO(geofflang): Find out why this doesn't compile on Apple AMD OpenGL drivers
Geoff Lang69accbd2016-01-25 16:22:32 -05001390 // (http://anglebug.com/1291)
Yunchao He9550c602018-02-13 14:47:05 +08001391 ANGLE_SKIP_TEST_IF(IsOSX() && IsAMD() && IsOpenGL());
Geoff Lang69accbd2016-01-25 16:22:32 -05001392
Austin Kinrossaf875522014-08-25 21:06:07 -07001393 GLint maxVaryings = 0;
1394 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1395
Jamie Madill192745a2016-12-22 15:58:21 -05001396 // Special case: because arrays of mat2 are packed as small grids of two rows by two columns,
1397 // we should be aware that when we're packing into an odd number of varying registers the
1398 // last row will be empty and can not fit the final vec2 arrary.
1399 GLint maxVec2Arrays = (maxVaryings >> 1) << 1;
1400
1401 VaryingTestBase(0, 0, 0, maxVec2Arrays, 0, 0, 0, 0, false, false, false, true);
Austin Kinrossaf875522014-08-25 21:06:07 -07001402}
1403
Geoff Langf60fab62014-11-24 11:21:20 -05001404// Verify shader source with a fixed length that is less than the null-terminated length will compile.
Jamie Madillfa05f602015-05-07 13:47:11 -04001405TEST_P(GLSLTest, FixedShaderLength)
Geoff Langf60fab62014-11-24 11:21:20 -05001406{
1407 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1408
1409 const std::string appendGarbage = "abcasdfasdfasdfasdfasdf";
1410 const std::string source = "void main() { gl_FragColor = vec4(0, 0, 0, 0); }" + appendGarbage;
1411 const char *sourceArray[1] = { source.c_str() };
Corentin Wallez973402f2015-05-11 13:42:22 -04001412 GLint lengths[1] = { static_cast<GLint>(source.length() - appendGarbage.length()) };
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001413 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
Geoff Langf60fab62014-11-24 11:21:20 -05001414 glCompileShader(shader);
1415
1416 GLint compileResult;
1417 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1418 EXPECT_NE(compileResult, 0);
1419}
1420
1421// Verify that a negative shader source length is treated as a null-terminated length.
Jamie Madillfa05f602015-05-07 13:47:11 -04001422TEST_P(GLSLTest, NegativeShaderLength)
Geoff Langf60fab62014-11-24 11:21:20 -05001423{
1424 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1425
1426 const char *sourceArray[1] = { "void main() { gl_FragColor = vec4(0, 0, 0, 0); }" };
1427 GLint lengths[1] = { -10 };
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001428 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
Geoff Langf60fab62014-11-24 11:21:20 -05001429 glCompileShader(shader);
1430
1431 GLint compileResult;
1432 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1433 EXPECT_NE(compileResult, 0);
1434}
1435
Corentin Wallez9a9c0482016-04-12 10:36:25 -04001436// Check that having an invalid char after the "." doesn't cause an assert.
1437TEST_P(GLSLTest, InvalidFieldFirstChar)
1438{
1439 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
1440 const char *source = "void main() {vec4 x; x.}";
1441 glShaderSource(shader, 1, &source, 0);
1442 glCompileShader(shader);
1443
1444 GLint compileResult;
1445 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1446 EXPECT_EQ(0, compileResult);
1447}
1448
Geoff Langf60fab62014-11-24 11:21:20 -05001449// Verify that a length array with mixed positive and negative values compiles.
Jamie Madillfa05f602015-05-07 13:47:11 -04001450TEST_P(GLSLTest, MixedShaderLengths)
Geoff Langf60fab62014-11-24 11:21:20 -05001451{
1452 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1453
1454 const char *sourceArray[] =
1455 {
1456 "void main()",
1457 "{",
1458 " gl_FragColor = vec4(0, 0, 0, 0);",
1459 "}",
1460 };
1461 GLint lengths[] =
1462 {
1463 -10,
1464 1,
Corentin Wallez973402f2015-05-11 13:42:22 -04001465 static_cast<GLint>(strlen(sourceArray[2])),
Geoff Langf60fab62014-11-24 11:21:20 -05001466 -1,
1467 };
1468 ASSERT_EQ(ArraySize(sourceArray), ArraySize(lengths));
1469
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001470 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
Geoff Langf60fab62014-11-24 11:21:20 -05001471 glCompileShader(shader);
1472
1473 GLint compileResult;
1474 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1475 EXPECT_NE(compileResult, 0);
1476}
1477
1478// Verify that zero-length shader source does not affect shader compilation.
Jamie Madillfa05f602015-05-07 13:47:11 -04001479TEST_P(GLSLTest, ZeroShaderLength)
Geoff Langf60fab62014-11-24 11:21:20 -05001480{
1481 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1482
1483 const char *sourceArray[] =
1484 {
1485 "adfasdf",
1486 "34534",
1487 "void main() { gl_FragColor = vec4(0, 0, 0, 0); }",
1488 "",
1489 "asdfasdfsdsdf",
1490 };
1491 GLint lengths[] =
1492 {
1493 0,
1494 0,
1495 -1,
1496 0,
1497 0,
1498 };
1499 ASSERT_EQ(ArraySize(sourceArray), ArraySize(lengths));
1500
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001501 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
Geoff Langf60fab62014-11-24 11:21:20 -05001502 glCompileShader(shader);
1503
1504 GLint compileResult;
1505 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1506 EXPECT_NE(compileResult, 0);
1507}
Jamie Madill21c1e452014-12-29 11:33:41 -05001508
1509// Tests that bad index expressions don't crash ANGLE's translator.
1510// https://code.google.com/p/angleproject/issues/detail?id=857
Jamie Madillfa05f602015-05-07 13:47:11 -04001511TEST_P(GLSLTest, BadIndexBug)
Jamie Madill21c1e452014-12-29 11:33:41 -05001512{
1513 const std::string &fragmentShaderSourceVec =
1514 "precision mediump float;\n"
1515 "uniform vec4 uniformVec;\n"
1516 "void main()\n"
1517 "{\n"
1518 " gl_FragColor = vec4(uniformVec[int()]);\n"
1519 "}";
1520
1521 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, fragmentShaderSourceVec);
1522 EXPECT_EQ(0u, shader);
1523
1524 if (shader != 0)
1525 {
1526 glDeleteShader(shader);
1527 }
1528
1529 const std::string &fragmentShaderSourceMat =
1530 "precision mediump float;\n"
1531 "uniform mat4 uniformMat;\n"
1532 "void main()\n"
1533 "{\n"
1534 " gl_FragColor = vec4(uniformMat[int()]);\n"
1535 "}";
1536
1537 shader = CompileShader(GL_FRAGMENT_SHADER, fragmentShaderSourceMat);
1538 EXPECT_EQ(0u, shader);
1539
1540 if (shader != 0)
1541 {
1542 glDeleteShader(shader);
1543 }
1544
1545 const std::string &fragmentShaderSourceArray =
1546 "precision mediump float;\n"
1547 "uniform vec4 uniformArray;\n"
1548 "void main()\n"
1549 "{\n"
1550 " gl_FragColor = vec4(uniformArray[int()]);\n"
1551 "}";
1552
1553 shader = CompileShader(GL_FRAGMENT_SHADER, fragmentShaderSourceArray);
1554 EXPECT_EQ(0u, shader);
1555
1556 if (shader != 0)
1557 {
1558 glDeleteShader(shader);
1559 }
Jamie Madill37997142015-01-28 10:06:34 -05001560}
1561
Jamie Madill2e295e22015-04-29 10:41:33 -04001562// Test that structs defined in uniforms are translated correctly.
Jamie Madillfa05f602015-05-07 13:47:11 -04001563TEST_P(GLSLTest, StructSpecifiersUniforms)
Jamie Madill2e295e22015-04-29 10:41:33 -04001564{
Olli Etuahoa20af6d2017-09-18 13:32:29 +03001565 const std::string fragmentShaderSource =
1566 R"(precision mediump float;
Jamie Madill2e295e22015-04-29 10:41:33 -04001567
1568 uniform struct S { float field;} s;
1569
1570 void main()
1571 {
1572 gl_FragColor = vec4(1, 0, 0, 1);
1573 gl_FragColor.a += s.field;
Olli Etuahoa20af6d2017-09-18 13:32:29 +03001574 })";
Jamie Madill2e295e22015-04-29 10:41:33 -04001575
1576 GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
1577 EXPECT_NE(0u, program);
1578}
Jamie Madill55def582015-05-04 11:24:57 -04001579
1580// Test that gl_DepthRange is not stored as a uniform location. Since uniforms
1581// beginning with "gl_" are filtered out by our validation logic, we must
1582// bypass the validation to test the behaviour of the implementation.
1583// (note this test is still Impl-independent)
Jamie Madille1faacb2016-12-13 12:42:14 -05001584TEST_P(GLSLTestNoValidation, DepthRangeUniforms)
Jamie Madill55def582015-05-04 11:24:57 -04001585{
Olli Etuahoa20af6d2017-09-18 13:32:29 +03001586 const std::string fragmentShaderSource =
1587 R"(precision mediump float;
Jamie Madill55def582015-05-04 11:24:57 -04001588
1589 void main()
1590 {
1591 gl_FragColor = vec4(gl_DepthRange.near, gl_DepthRange.far, gl_DepthRange.diff, 1);
Olli Etuahoa20af6d2017-09-18 13:32:29 +03001592 })";
Jamie Madill55def582015-05-04 11:24:57 -04001593
Jamie Madille1faacb2016-12-13 12:42:14 -05001594 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShaderSource);
Jamie Madill55def582015-05-04 11:24:57 -04001595
Jamie Madille1faacb2016-12-13 12:42:14 -05001596 // We need to bypass validation for this call.
1597 GLint nearIndex = glGetUniformLocation(program.get(), "gl_DepthRange.near");
Jamie Madill55def582015-05-04 11:24:57 -04001598 EXPECT_EQ(-1, nearIndex);
1599
1600 // Test drawing does not throw an exception.
Jamie Madille1faacb2016-12-13 12:42:14 -05001601 drawQuad(program.get(), "inputAttribute", 0.5f);
Jamie Madill55def582015-05-04 11:24:57 -04001602
1603 EXPECT_GL_NO_ERROR();
Jamie Madill55def582015-05-04 11:24:57 -04001604}
Jamie Madill4052dfc2015-05-06 15:18:49 -04001605
Jamie Madill6c9503e2016-08-16 14:06:32 -04001606std::string GenerateSmallPowShader(double base, double exponent)
1607{
1608 std::stringstream stream;
1609
1610 stream.precision(8);
1611
1612 double result = pow(base, exponent);
1613
1614 stream << "precision highp float;\n"
1615 << "float fun(float arg)\n"
1616 << "{\n"
1617 << " return pow(arg, " << std::fixed << exponent << ");\n"
1618 << "}\n"
1619 << "\n"
1620 << "void main()\n"
1621 << "{\n"
1622 << " const float a = " << std::scientific << base << ";\n"
1623 << " float b = fun(a);\n"
1624 << " if (abs(" << result << " - b) < " << std::abs(result * 0.001) << ")\n"
1625 << " {\n"
1626 << " gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
1627 << " }\n"
1628 << " else\n"
1629 << " {\n"
1630 << " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
1631 << " }\n"
1632 << "}\n";
1633
1634 return stream.str();
1635}
1636
Jamie Madill4052dfc2015-05-06 15:18:49 -04001637// Covers the WebGL test 'glsl/bugs/pow-of-small-constant-in-user-defined-function'
Jamie Madill1048e432016-07-23 18:51:28 -04001638// See http://anglebug.com/851
1639TEST_P(GLSLTest, PowOfSmallConstant)
Jamie Madill4052dfc2015-05-06 15:18:49 -04001640{
Olli Etuaho629a6442017-12-11 10:55:43 +02001641 // Test with problematic exponents that are close to an integer.
1642 std::vector<double> testExponents;
1643 std::array<double, 5> epsilonMultipliers = {-100.0, -1.0, 0.0, 1.0, 100.0};
1644 for (double epsilonMultiplier : epsilonMultipliers)
Jamie Madill6c9503e2016-08-16 14:06:32 -04001645 {
1646 for (int i = -4; i <= 5; ++i)
Jamie Madill4052dfc2015-05-06 15:18:49 -04001647 {
Jamie Madill6c9503e2016-08-16 14:06:32 -04001648 if (i >= -1 && i <= 1)
1649 continue;
1650 const double epsilon = 1.0e-8;
Olli Etuaho629a6442017-12-11 10:55:43 +02001651 double bad = static_cast<double>(i) + epsilonMultiplier * epsilon;
1652 testExponents.push_back(bad);
Jamie Madill4052dfc2015-05-06 15:18:49 -04001653 }
Jamie Madill6c9503e2016-08-16 14:06:32 -04001654 }
Jamie Madill4052dfc2015-05-06 15:18:49 -04001655
Olli Etuaho629a6442017-12-11 10:55:43 +02001656 // Also test with a few exponents that are not close to an integer.
1657 testExponents.push_back(3.6);
1658 testExponents.push_back(3.4);
1659
1660 for (double testExponent : testExponents)
Jamie Madill6c9503e2016-08-16 14:06:32 -04001661 {
Olli Etuaho629a6442017-12-11 10:55:43 +02001662 const std::string &fragmentShaderSource = GenerateSmallPowShader(1.0e-6, testExponent);
Jamie Madill4052dfc2015-05-06 15:18:49 -04001663
Jamie Madill6c9503e2016-08-16 14:06:32 -04001664 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShaderSource);
Jamie Madill4052dfc2015-05-06 15:18:49 -04001665
Jamie Madill6c9503e2016-08-16 14:06:32 -04001666 drawQuad(program.get(), "inputAttribute", 0.5f);
1667
1668 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1669 EXPECT_GL_NO_ERROR();
1670 }
Jamie Madill4052dfc2015-05-06 15:18:49 -04001671}
Jamie Madillfa05f602015-05-07 13:47:11 -04001672
Cooper Partina5ef8d82015-08-19 14:52:21 -07001673// Test that fragment shaders which contain non-constant loop indexers and compiled for FL9_3 and
1674// below
1675// fail with a specific error message.
1676// Additionally test that the same fragment shader compiles successfully with feature levels greater
1677// than FL9_3.
1678TEST_P(GLSLTest, LoopIndexingValidation)
1679{
Olli Etuahoa20af6d2017-09-18 13:32:29 +03001680 const std::string fragmentShaderSource =
1681 R"(precision mediump float;
Cooper Partina5ef8d82015-08-19 14:52:21 -07001682
1683 uniform float loopMax;
1684
1685 void main()
1686 {
1687 gl_FragColor = vec4(1, 0, 0, 1);
1688 for (float l = 0.0; l < loopMax; l++)
1689 {
1690 if (loopMax > 3.0)
1691 {
1692 gl_FragColor.a += 0.1;
1693 }
1694 }
Olli Etuahoa20af6d2017-09-18 13:32:29 +03001695 })";
Cooper Partina5ef8d82015-08-19 14:52:21 -07001696
1697 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1698
1699 const char *sourceArray[1] = {fragmentShaderSource.c_str()};
1700 glShaderSource(shader, 1, sourceArray, nullptr);
1701 glCompileShader(shader);
1702
1703 GLint compileResult;
1704 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1705
1706 // If the test is configured to run limited to Feature Level 9_3, then it is
1707 // assumed that shader compilation will fail with an expected error message containing
1708 // "Loop index cannot be compared with non-constant expression"
Olli Etuaho814a54d2015-08-27 16:23:09 +03001709 if ((GetParam() == ES2_D3D11_FL9_3() || GetParam() == ES2_D3D9()))
Cooper Partina5ef8d82015-08-19 14:52:21 -07001710 {
1711 if (compileResult != 0)
1712 {
1713 FAIL() << "Shader compilation succeeded, expected failure";
1714 }
1715 else
1716 {
1717 GLint infoLogLength;
1718 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
1719
1720 std::string infoLog;
1721 infoLog.resize(infoLogLength);
Yunchao Hef81ce4a2017-04-24 10:49:17 +08001722 glGetShaderInfoLog(shader, static_cast<GLsizei>(infoLog.size()), nullptr, &infoLog[0]);
Cooper Partina5ef8d82015-08-19 14:52:21 -07001723
1724 if (infoLog.find("Loop index cannot be compared with non-constant expression") ==
1725 std::string::npos)
1726 {
1727 FAIL() << "Shader compilation failed with unexpected error message";
1728 }
1729 }
1730 }
1731 else
1732 {
1733 EXPECT_NE(0, compileResult);
1734 }
1735
1736 if (shader != 0)
1737 {
1738 glDeleteShader(shader);
1739 }
1740}
1741
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001742// Tests that the maximum uniforms count returned from querying GL_MAX_VERTEX_UNIFORM_VECTORS
1743// can actually be used.
1744TEST_P(GLSLTest, VerifyMaxVertexUniformVectors)
1745{
Geoff Langed046192018-02-08 14:57:14 -05001746 // crbug.com/680631
Geoff Lang06b95582018-02-08 13:48:44 -05001747 ANGLE_SKIP_TEST_IF(IsOzone() && IsIntel());
1748
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001749 int maxUniforms = 10000;
1750 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
1751 EXPECT_GL_NO_ERROR();
1752 std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS = " << maxUniforms << std::endl;
1753
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001754 CompileGLSLWithUniformsAndSamplers(maxUniforms, 0, 0, 0, true);
1755}
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001756
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001757// Tests that the maximum uniforms count returned from querying GL_MAX_VERTEX_UNIFORM_VECTORS
1758// can actually be used along with the maximum number of texture samplers.
1759TEST_P(GLSLTest, VerifyMaxVertexUniformVectorsWithSamplers)
1760{
Yunchao He9550c602018-02-13 14:47:05 +08001761 ANGLE_SKIP_TEST_IF(IsOpenGL() || IsOpenGLES());
Geoff Lange0cc2a42016-01-20 10:58:17 -05001762
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001763 int maxUniforms = 10000;
1764 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
1765 EXPECT_GL_NO_ERROR();
1766 std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS = " << maxUniforms << std::endl;
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001767
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001768 int maxTextureImageUnits = 0;
1769 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001770
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001771 CompileGLSLWithUniformsAndSamplers(maxUniforms, 0, maxTextureImageUnits, 0, true);
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001772}
1773
1774// Tests that the maximum uniforms count + 1 from querying GL_MAX_VERTEX_UNIFORM_VECTORS
1775// fails shader compilation.
1776TEST_P(GLSLTest, VerifyMaxVertexUniformVectorsExceeded)
1777{
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001778 int maxUniforms = 10000;
1779 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
1780 EXPECT_GL_NO_ERROR();
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001781 std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS + 1 = " << maxUniforms + 1 << std::endl;
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001782
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001783 CompileGLSLWithUniformsAndSamplers(maxUniforms + 1, 0, 0, 0, false);
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001784}
1785
1786// Tests that the maximum uniforms count returned from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
1787// can actually be used.
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001788TEST_P(GLSLTest, VerifyMaxFragmentUniformVectors)
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001789{
Geoff Langed046192018-02-08 14:57:14 -05001790 // crbug.com/680631
Geoff Lang06b95582018-02-08 13:48:44 -05001791 ANGLE_SKIP_TEST_IF(IsOzone() && IsIntel());
1792
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001793 int maxUniforms = 10000;
1794 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
1795 EXPECT_GL_NO_ERROR();
1796 std::cout << "Validating GL_MAX_FRAGMENT_UNIFORM_VECTORS = " << maxUniforms << std::endl;
1797
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001798 CompileGLSLWithUniformsAndSamplers(0, maxUniforms, 0, 0, true);
1799}
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001800
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001801// Tests that the maximum uniforms count returned from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
1802// can actually be used along with the maximum number of texture samplers.
1803TEST_P(GLSLTest, VerifyMaxFragmentUniformVectorsWithSamplers)
1804{
Yunchao He9550c602018-02-13 14:47:05 +08001805 ANGLE_SKIP_TEST_IF(IsOpenGL() || IsOpenGLES());
Geoff Lange0cc2a42016-01-20 10:58:17 -05001806
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001807 int maxUniforms = 10000;
1808 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
1809 EXPECT_GL_NO_ERROR();
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001810
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001811 int maxTextureImageUnits = 0;
1812 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001813
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001814 CompileGLSLWithUniformsAndSamplers(0, maxUniforms, 0, maxTextureImageUnits, true);
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001815}
1816
1817// Tests that the maximum uniforms count + 1 from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
1818// fails shader compilation.
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001819TEST_P(GLSLTest, VerifyMaxFragmentUniformVectorsExceeded)
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001820{
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001821 int maxUniforms = 10000;
1822 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
1823 EXPECT_GL_NO_ERROR();
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001824 std::cout << "Validating GL_MAX_FRAGMENT_UNIFORM_VECTORS + 1 = " << maxUniforms + 1
1825 << std::endl;
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001826
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001827 CompileGLSLWithUniformsAndSamplers(0, maxUniforms + 1, 0, 0, false);
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001828}
1829
Geoff Langba992ab2017-04-19 11:18:14 -04001830// Test compiling shaders using the GL_EXT_shader_texture_lod extension
1831TEST_P(GLSLTest, TextureLOD)
1832{
Yunchao He9550c602018-02-13 14:47:05 +08001833 ANGLE_SKIP_TEST_IF(!extensionEnabled("GL_EXT_shader_texture_lod"));
Geoff Langba992ab2017-04-19 11:18:14 -04001834
1835 const std::string source =
1836 "#extension GL_EXT_shader_texture_lod : require\n"
1837 "uniform sampler2D u_texture;\n"
1838 "void main() {\n"
1839 " gl_FragColor = texture2DGradEXT(u_texture, vec2(0.0, 0.0), vec2(0.0, 0.0), vec2(0.0, "
1840 "0.0));\n"
1841 "}\n";
1842
1843 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, source);
1844 ASSERT_NE(0u, shader);
1845 glDeleteShader(shader);
1846}
1847
Olli Etuahobe59c2f2016-03-07 11:32:34 +02001848// Test that two constructors which have vec4 and mat2 parameters get disambiguated (issue in
1849// HLSL).
1850TEST_P(GLSLTest_ES3, AmbiguousConstructorCall2x2)
1851{
1852 const std::string fragmentShaderSource =
1853 "#version 300 es\n"
1854 "precision highp float;\n"
1855 "out vec4 my_FragColor;\n"
1856 "void main()\n"
1857 "{\n"
1858 " my_FragColor = vec4(0.0);\n"
1859 "}";
1860
1861 const std::string vertexShaderSource =
1862 "#version 300 es\n"
1863 "precision highp float;\n"
1864 "in vec4 a_vec;\n"
1865 "in mat2 a_mat;\n"
1866 "void main()\n"
1867 "{\n"
1868 " gl_Position = vec4(a_vec) + vec4(a_mat);\n"
1869 "}";
1870
1871 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1872 EXPECT_NE(0u, program);
1873}
1874
1875// Test that two constructors which have mat2x3 and mat3x2 parameters get disambiguated.
1876// This was suspected to be an issue in HLSL, but HLSL seems to be able to natively choose between
1877// the function signatures in this case.
1878TEST_P(GLSLTest_ES3, AmbiguousConstructorCall2x3)
1879{
1880 const std::string fragmentShaderSource =
1881 "#version 300 es\n"
1882 "precision highp float;\n"
1883 "out vec4 my_FragColor;\n"
1884 "void main()\n"
1885 "{\n"
1886 " my_FragColor = vec4(0.0);\n"
1887 "}";
1888
1889 const std::string vertexShaderSource =
1890 "#version 300 es\n"
1891 "precision highp float;\n"
1892 "in mat3x2 a_matA;\n"
1893 "in mat2x3 a_matB;\n"
1894 "void main()\n"
1895 "{\n"
1896 " gl_Position = vec4(a_matA) + vec4(a_matB);\n"
1897 "}";
1898
1899 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1900 EXPECT_NE(0u, program);
1901}
1902
1903// Test that two functions which have vec4 and mat2 parameters get disambiguated (issue in HLSL).
1904TEST_P(GLSLTest_ES3, AmbiguousFunctionCall2x2)
1905{
1906 const std::string fragmentShaderSource =
1907 "#version 300 es\n"
1908 "precision highp float;\n"
1909 "out vec4 my_FragColor;\n"
1910 "void main()\n"
1911 "{\n"
1912 " my_FragColor = vec4(0.0);\n"
1913 "}";
1914
1915 const std::string vertexShaderSource =
1916 "#version 300 es\n"
1917 "precision highp float;\n"
1918 "in vec4 a_vec;\n"
1919 "in mat2 a_mat;\n"
1920 "vec4 foo(vec4 a)\n"
1921 "{\n"
1922 " return a;\n"
1923 "}\n"
1924 "vec4 foo(mat2 a)\n"
1925 "{\n"
1926 " return vec4(a[0][0]);\n"
1927 "}\n"
1928 "void main()\n"
1929 "{\n"
1930 " gl_Position = foo(a_vec) + foo(a_mat);\n"
1931 "}";
1932
1933 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1934 EXPECT_NE(0u, program);
1935}
1936
1937// Test that an user-defined function with a large number of float4 parameters doesn't fail due to
1938// the function name being too long.
1939TEST_P(GLSLTest_ES3, LargeNumberOfFloat4Parameters)
1940{
1941 const std::string fragmentShaderSource =
1942 "#version 300 es\n"
1943 "precision highp float;\n"
1944 "out vec4 my_FragColor;\n"
1945 "void main()\n"
1946 "{\n"
1947 " my_FragColor = vec4(0.0);\n"
1948 "}";
1949
1950 std::stringstream vertexShaderStream;
1951 const unsigned int paramCount = 1024u;
1952
1953 vertexShaderStream << "#version 300 es\n"
1954 "precision highp float;\n"
1955 "in vec4 a_vec;\n"
1956 "vec4 lotsOfVec4Parameters(";
1957 for (unsigned int i = 0; i < paramCount; ++i)
1958 {
1959 vertexShaderStream << "vec4 a" << i << ", ";
1960 }
1961 vertexShaderStream << "vec4 aLast)\n"
1962 "{\n"
1963 " return ";
1964 for (unsigned int i = 0; i < paramCount; ++i)
1965 {
1966 vertexShaderStream << "a" << i << " + ";
1967 }
1968 vertexShaderStream << "aLast;\n"
1969 "}\n"
1970 "void main()\n"
1971 "{\n"
1972 " gl_Position = lotsOfVec4Parameters(";
1973 for (unsigned int i = 0; i < paramCount; ++i)
1974 {
1975 vertexShaderStream << "a_vec, ";
1976 }
1977 vertexShaderStream << "a_vec);\n"
1978 "}";
1979
1980 GLuint program = CompileProgram(vertexShaderStream.str(), fragmentShaderSource);
1981 EXPECT_NE(0u, program);
1982}
1983
Olli Etuahod4f4c112016-04-15 15:11:24 +03001984// This test was written specifically to stress DeferGlobalInitializers AST transformation.
1985// Test a shader where a global constant array is initialized with an expression containing array
1986// indexing. This initializer is tricky to constant fold, so if it's not constant folded it needs to
1987// be handled in a way that doesn't generate statements in the global scope in HLSL output.
1988// Also includes multiple array initializers in one declaration, where only the second one has
1989// array indexing. This makes sure that the qualifier for the declaration is set correctly if
1990// transformations are applied to the declaration also in the case of ESSL output.
1991TEST_P(GLSLTest_ES3, InitGlobalArrayWithArrayIndexing)
1992{
Yuly Novikov41db2242016-06-25 00:14:28 -04001993 // TODO(ynovikov): re-enable once root cause of http://anglebug.com/1428 is fixed
Yunchao He9550c602018-02-13 14:47:05 +08001994 ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
Yuly Novikov41db2242016-06-25 00:14:28 -04001995
Olli Etuahod4f4c112016-04-15 15:11:24 +03001996 const std::string vertexShaderSource =
1997 "#version 300 es\n"
1998 "precision highp float;\n"
1999 "in vec4 a_vec;\n"
2000 "void main()\n"
2001 "{\n"
2002 " gl_Position = vec4(a_vec);\n"
2003 "}";
2004
2005 const std::string fragmentShaderSource =
2006 "#version 300 es\n"
2007 "precision highp float;\n"
2008 "out vec4 my_FragColor;\n"
2009 "const highp float f[2] = float[2](0.1, 0.2);\n"
2010 "const highp float[2] g = float[2](0.3, 0.4), h = float[2](0.5, f[1]);\n"
2011 "void main()\n"
2012 "{\n"
2013 " my_FragColor = vec4(h[1]);\n"
2014 "}";
2015
2016 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
2017 EXPECT_NE(0u, program);
2018}
2019
Corentin Wallez419bfc92016-06-28 10:54:45 -07002020// Test that index-constant sampler array indexing is supported.
2021TEST_P(GLSLTest, IndexConstantSamplerArrayIndexing)
2022{
Yunchao He9550c602018-02-13 14:47:05 +08002023 ANGLE_SKIP_TEST_IF(IsD3D11_FL93());
Corentin Wallez419bfc92016-06-28 10:54:45 -07002024
2025 const std::string vertexShaderSource =
2026 "attribute vec4 vPosition;\n"
2027 "void main()\n"
2028 "{\n"
2029 " gl_Position = vPosition;\n"
2030 "}";
2031
2032 const std::string fragmentShaderSource =
2033 "precision mediump float;\n"
2034 "uniform sampler2D uni[2];\n"
2035 "\n"
2036 "float zero(int x)\n"
2037 "{\n"
2038 " return float(x) - float(x);\n"
2039 "}\n"
2040 "\n"
2041 "void main()\n"
2042 "{\n"
2043 " vec4 c = vec4(0,0,0,0);\n"
2044 " for (int ii = 1; ii < 3; ++ii) {\n"
2045 " if (c.x > 255.0) {\n"
2046 " c.x = 255.0 + zero(ii);\n"
2047 " break;\n"
2048 " }\n"
2049 // Index the sampler array with a predictable loop index (index-constant) as opposed to
2050 // a true constant. This is valid in OpenGL ES but isn't in many Desktop OpenGL versions,
2051 // without an extension.
2052 " c += texture2D(uni[ii - 1], vec2(0.5, 0.5));\n"
2053 " }\n"
2054 " gl_FragColor = c;\n"
2055 "}";
2056
2057 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
2058 EXPECT_NE(0u, program);
2059}
2060
Corentin Wallezb00dcee2016-07-11 17:42:58 -04002061// Test that the #pragma directive is supported and doesn't trigger a compilation failure on the
2062// native driver. The only pragma that gets passed to the OpenGL driver is "invariant" but we don't
2063// want to test its behavior, so don't use any varyings.
2064TEST_P(GLSLTest, PragmaDirective)
2065{
2066 const std::string vertexShaderSource =
2067 "#pragma STDGL invariant(all)\n"
2068 "void main()\n"
2069 "{\n"
2070 " gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
2071 "}\n";
2072
2073 const std::string fragmentShaderSource =
2074 "precision mediump float;\n"
2075 "void main()\n"
2076 "{\n"
2077 " gl_FragColor = vec4(1.0);\n"
2078 "}\n";
2079
2080 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
2081 EXPECT_NE(0u, program);
2082}
2083
Olli Etuahoe1d199b2016-07-19 17:14:27 +03002084// Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
2085// The function call that returns the array needs to be evaluated after ++j for the expression to
2086// return the correct value (true).
2087TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderArray)
2088{
2089 const std::string &fragmentShaderSource =
2090 "#version 300 es\n"
2091 "precision mediump float;\n"
2092 "out vec4 my_FragColor; \n"
2093 "int[2] func(int param) {\n"
2094 " return int[2](param, param);\n"
2095 "}\n"
2096 "void main() {\n"
2097 " int a[2]; \n"
2098 " for (int i = 0; i < 2; ++i) {\n"
2099 " a[i] = 1;\n"
2100 " }\n"
2101 " int j = 0; \n"
2102 " bool result = ((++j), (a == func(j)));\n"
2103 " my_FragColor = vec4(0.0, (result ? 1.0 : 0.0), 0.0, 1.0);\n"
2104 "}\n";
2105
2106 GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
2107 ASSERT_NE(0u, program);
2108
2109 drawQuad(program, "inputAttribute", 0.5f);
2110
2111 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2112}
2113
2114// Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
2115// The short-circuiting expression needs to be evaluated after ++j for the expression to return the
2116// correct value (true).
2117TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderShortCircuit)
2118{
2119 const std::string &fragmentShaderSource =
2120 "#version 300 es\n"
2121 "precision mediump float;\n"
2122 "out vec4 my_FragColor; \n"
2123 "void main() {\n"
2124 " int j = 0; \n"
2125 " bool result = ((++j), (j == 1 ? true : (++j == 3)));\n"
2126 " my_FragColor = vec4(0.0, ((result && j == 1) ? 1.0 : 0.0), 0.0, 1.0);\n"
2127 "}\n";
2128
2129 GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
2130 ASSERT_NE(0u, program);
2131
2132 drawQuad(program, "inputAttribute", 0.5f);
2133
2134 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2135}
2136
Jamie Madill666f65a2016-08-26 01:34:37 +00002137// Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
2138// Indexing the vector needs to be evaluated after func() for the right result.
2139TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderDynamicVectorIndexingInLValue)
2140{
2141 const std::string &fragmentShaderSource =
2142 "#version 300 es\n"
2143 "precision mediump float;\n"
2144 "out vec4 my_FragColor;\n"
2145 "uniform int u_zero;\n"
2146 "int sideEffectCount = 0;\n"
2147 "float func() {\n"
2148 " ++sideEffectCount;\n"
2149 " return -1.0;\n"
2150 "}\n"
2151 "void main() {\n"
2152 " vec4 v = vec4(0.0, 2.0, 4.0, 6.0); \n"
2153 " float f = (func(), (++v[u_zero + sideEffectCount]));\n"
2154 " bool green = abs(f - 3.0) < 0.01 && abs(v[1] - 3.0) < 0.01 && sideEffectCount == 1;\n"
2155 " my_FragColor = vec4(0.0, (green ? 1.0 : 0.0), 0.0, 1.0);\n"
2156 "}\n";
2157
2158 GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
2159 ASSERT_NE(0u, program);
2160
2161 drawQuad(program, "inputAttribute", 0.5f);
2162
2163 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2164}
2165
Jamie Madillc9bde922016-07-24 17:58:50 -04002166// Test that using gl_PointCoord with GL_TRIANGLES doesn't produce a link error.
2167// From WebGL test conformance/rendering/point-specific-shader-variables.html
2168// See http://anglebug.com/1380
2169TEST_P(GLSLTest, RenderTrisWithPointCoord)
2170{
2171 const std::string &vert =
2172 "attribute vec2 aPosition;\n"
2173 "void main()\n"
2174 "{\n"
2175 " gl_Position = vec4(aPosition, 0, 1);\n"
2176 " gl_PointSize = 1.0;\n"
2177 "}";
2178 const std::string &frag =
2179 "void main()\n"
2180 "{\n"
2181 " gl_FragColor = vec4(gl_PointCoord.xy, 0, 1);\n"
2182 " gl_FragColor = vec4(0, 1, 0, 1);\n"
2183 "}";
2184
2185 ANGLE_GL_PROGRAM(prog, vert, frag);
2186 drawQuad(prog.get(), "aPosition", 0.5f);
2187 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2188}
2189
Jamie Madill5655b842016-08-02 11:00:07 -04002190// Convers a bug with the integer pow statement workaround.
2191TEST_P(GLSLTest, NestedPowStatements)
2192{
2193 const std::string &vert =
2194 "attribute vec2 position;\n"
2195 "void main()\n"
2196 "{\n"
2197 " gl_Position = vec4(position, 0, 1);\n"
2198 "}";
2199 const std::string &frag =
2200 "precision mediump float;\n"
2201 "float func(float v)\n"
2202 "{\n"
2203 " float f1 = pow(v, 2.0);\n"
2204 " return pow(f1 + v, 2.0);\n"
2205 "}\n"
2206 "void main()\n"
2207 "{\n"
2208 " float v = func(2.0);\n"
2209 " gl_FragColor = abs(v - 36.0) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
2210 "}";
2211
2212 ANGLE_GL_PROGRAM(prog, vert, frag);
2213 drawQuad(prog.get(), "position", 0.5f);
2214 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2215}
2216
Qiankun Miaof52fe932016-12-07 13:39:15 +08002217// Test that -float calculation is correct.
2218TEST_P(GLSLTest_ES3, UnaryMinusOperatorFloat)
2219{
Qiankun Miaof52fe932016-12-07 13:39:15 +08002220 const std::string &vert =
2221 "#version 300 es\n"
2222 "in highp vec4 position;\n"
2223 "void main() {\n"
2224 " gl_Position = position;\n"
2225 "}\n";
2226 const std::string &frag =
2227 "#version 300 es\n"
2228 "out highp vec4 o_color;\n"
2229 "void main() {\n"
2230 " highp float f = -1.0;\n"
2231 " // atan(tan(0.5), -f) should be 0.5.\n"
2232 " highp float v = atan(tan(0.5), -f);\n"
2233 " o_color = abs(v - 0.5) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
2234 "}\n";
2235
2236 ANGLE_GL_PROGRAM(prog, vert, frag);
2237 drawQuad(prog.get(), "position", 0.5f);
2238 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2239}
2240
Olli Etuahoda9fb092016-12-09 17:32:29 +00002241// Test that atan(vec2, vec2) calculation is correct.
2242TEST_P(GLSLTest_ES3, AtanVec2)
2243{
2244 const std::string &vert =
2245 "#version 300 es\n"
2246 "in highp vec4 position;\n"
2247 "void main() {\n"
2248 " gl_Position = position;\n"
2249 "}\n";
2250 const std::string &frag =
2251 "#version 300 es\n"
2252 "out highp vec4 o_color;\n"
2253 "void main() {\n"
2254 " highp float f = 1.0;\n"
2255 " // atan(tan(0.5), f) should be 0.5.\n"
2256 " highp vec2 v = atan(vec2(tan(0.5)), vec2(f));\n"
2257 " o_color = (abs(v[0] - 0.5) < 0.001 && abs(v[1] - 0.5) < 0.001) ? vec4(0, 1, 0, 1) : "
2258 "vec4(1, 0, 0, 1);\n"
2259 "}\n";
2260
2261 ANGLE_GL_PROGRAM(prog, vert, frag);
2262 drawQuad(prog.get(), "position", 0.5f);
2263 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2264}
2265
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002266// Convers a bug with the unary minus operator on signed integer workaround.
2267TEST_P(GLSLTest_ES3, UnaryMinusOperatorSignedInt)
2268{
2269 const std::string &vert =
2270 "#version 300 es\n"
2271 "in highp vec4 position;\n"
2272 "out mediump vec4 v_color;\n"
2273 "uniform int ui_one;\n"
2274 "uniform int ui_two;\n"
2275 "uniform int ui_three;\n"
2276 "void main() {\n"
2277 " int s[3];\n"
2278 " s[0] = ui_one;\n"
2279 " s[1] = -(-(-ui_two + 1) + 1);\n" // s[1] = -ui_two
2280 " s[2] = ui_three;\n"
2281 " int result = 0;\n"
2282 " for (int i = 0; i < ui_three; i++) {\n"
2283 " result += s[i];\n"
2284 " }\n"
2285 " v_color = (result == 2) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
2286 " gl_Position = position;\n"
2287 "}\n";
2288 const std::string &frag =
2289 "#version 300 es\n"
2290 "in mediump vec4 v_color;\n"
2291 "layout(location=0) out mediump vec4 o_color;\n"
2292 "void main() {\n"
2293 " o_color = v_color;\n"
2294 "}\n";
2295
2296 ANGLE_GL_PROGRAM(prog, vert, frag);
2297
Jamie Madille1faacb2016-12-13 12:42:14 -05002298 GLint oneIndex = glGetUniformLocation(prog.get(), "ui_one");
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002299 ASSERT_NE(-1, oneIndex);
Jamie Madille1faacb2016-12-13 12:42:14 -05002300 GLint twoIndex = glGetUniformLocation(prog.get(), "ui_two");
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002301 ASSERT_NE(-1, twoIndex);
Jamie Madille1faacb2016-12-13 12:42:14 -05002302 GLint threeIndex = glGetUniformLocation(prog.get(), "ui_three");
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002303 ASSERT_NE(-1, threeIndex);
2304 glUseProgram(prog.get());
2305 glUniform1i(oneIndex, 1);
2306 glUniform1i(twoIndex, 2);
2307 glUniform1i(threeIndex, 3);
2308
2309 drawQuad(prog.get(), "position", 0.5f);
2310 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2311}
2312
2313// Convers a bug with the unary minus operator on unsigned integer workaround.
2314TEST_P(GLSLTest_ES3, UnaryMinusOperatorUnsignedInt)
2315{
2316 const std::string &vert =
2317 "#version 300 es\n"
2318 "in highp vec4 position;\n"
2319 "out mediump vec4 v_color;\n"
2320 "uniform uint ui_one;\n"
2321 "uniform uint ui_two;\n"
2322 "uniform uint ui_three;\n"
2323 "void main() {\n"
2324 " uint s[3];\n"
2325 " s[0] = ui_one;\n"
2326 " s[1] = -(-(-ui_two + 1u) + 1u);\n" // s[1] = -ui_two
2327 " s[2] = ui_three;\n"
2328 " uint result = 0u;\n"
2329 " for (uint i = 0u; i < ui_three; i++) {\n"
2330 " result += s[i];\n"
2331 " }\n"
2332 " v_color = (result == 2u) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
2333 " gl_Position = position;\n"
2334 "}\n";
2335 const std::string &frag =
2336 "#version 300 es\n"
2337 "in mediump vec4 v_color;\n"
2338 "layout(location=0) out mediump vec4 o_color;\n"
2339 "void main() {\n"
2340 " o_color = v_color;\n"
2341 "}\n";
2342
2343 ANGLE_GL_PROGRAM(prog, vert, frag);
2344
Jamie Madille1faacb2016-12-13 12:42:14 -05002345 GLint oneIndex = glGetUniformLocation(prog.get(), "ui_one");
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002346 ASSERT_NE(-1, oneIndex);
Jamie Madille1faacb2016-12-13 12:42:14 -05002347 GLint twoIndex = glGetUniformLocation(prog.get(), "ui_two");
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002348 ASSERT_NE(-1, twoIndex);
Jamie Madille1faacb2016-12-13 12:42:14 -05002349 GLint threeIndex = glGetUniformLocation(prog.get(), "ui_three");
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002350 ASSERT_NE(-1, threeIndex);
2351 glUseProgram(prog.get());
2352 glUniform1ui(oneIndex, 1u);
2353 glUniform1ui(twoIndex, 2u);
2354 glUniform1ui(threeIndex, 3u);
2355
2356 drawQuad(prog.get(), "position", 0.5f);
2357 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2358}
2359
Olli Etuahoab481642016-08-26 12:09:10 +03002360// Test a nested sequence operator with a ternary operator inside. The ternary operator is
2361// intended to be such that it gets converted to an if statement on the HLSL backend.
2362TEST_P(GLSLTest, NestedSequenceOperatorWithTernaryInside)
2363{
2364 const std::string &vert =
2365 "attribute vec2 position;\n"
2366 "void main()\n"
2367 "{\n"
2368 " gl_Position = vec4(position, 0, 1);\n"
2369 "}";
2370
2371 // Note that the uniform keep_flop_positive doesn't need to be set - the test expects it to have
2372 // its default value false.
2373 const std::string &frag =
2374 "precision mediump float;\n"
2375 "uniform bool keep_flop_positive;\n"
2376 "float flop;\n"
2377 "void main() {\n"
2378 " flop = -1.0,\n"
2379 " (flop *= -1.0,\n"
2380 " keep_flop_positive ? 0.0 : flop *= -1.0),\n"
2381 " gl_FragColor = vec4(0, -flop, 0, 1);\n"
2382 "}";
2383
2384 ANGLE_GL_PROGRAM(prog, vert, frag);
2385 drawQuad(prog.get(), "position", 0.5f);
2386 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2387}
2388
Geoff Lang28a97ee2016-09-22 13:01:26 -04002389// Test that using a sampler2D and samplerExternalOES in the same shader works (anglebug.com/1534)
2390TEST_P(GLSLTest, ExternalAnd2DSampler)
2391{
Yunchao He9550c602018-02-13 14:47:05 +08002392 ANGLE_SKIP_TEST_IF(!extensionEnabled("GL_OES_EGL_image_external"));
Geoff Lang28a97ee2016-09-22 13:01:26 -04002393
2394 const std::string fragmentShader =
Olli Etuaho703671e2017-11-08 17:47:18 +02002395 R"(
2396 #extension GL_OES_EGL_image_external : enable
2397 precision mediump float;
2398 uniform samplerExternalOES tex0;
2399 uniform sampler2D tex1;
2400 void main(void)
2401 {
2402 vec2 uv = vec2(0.0, 0.0);
2403 gl_FragColor = texture2D(tex0, uv) + texture2D(tex1, uv);
2404 })";
Geoff Lang28a97ee2016-09-22 13:01:26 -04002405
2406 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2407}
2408
Olli Etuaho56a2f952016-12-08 12:16:27 +00002409// Test that literal infinity can be written out from the shader translator.
2410// A similar test can't be made for NaNs, since ESSL 3.00.6 requirements for NaNs are very loose.
2411TEST_P(GLSLTest_ES3, LiteralInfinityOutput)
2412{
2413 const std::string &fragmentShader =
2414 "#version 300 es\n"
2415 "precision highp float;\n"
2416 "out vec4 out_color;\n"
2417 "uniform float u;\n"
2418 "void main()\n"
2419 "{\n"
2420 " float infVar = 1.0e40 - u;\n"
2421 " bool correct = isinf(infVar) && infVar > 0.0;\n"
2422 " out_color = correct ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
2423 "}\n";
2424
2425 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2426 drawQuad(program.get(), "inputAttribute", 0.5f);
2427 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2428}
2429
2430// Test that literal negative infinity can be written out from the shader translator.
2431// A similar test can't be made for NaNs, since ESSL 3.00.6 requirements for NaNs are very loose.
2432TEST_P(GLSLTest_ES3, LiteralNegativeInfinityOutput)
2433{
2434 const std::string &fragmentShader =
2435 "#version 300 es\n"
2436 "precision highp float;\n"
2437 "out vec4 out_color;\n"
2438 "uniform float u;\n"
2439 "void main()\n"
2440 "{\n"
2441 " float infVar = -1.0e40 + u;\n"
2442 " bool correct = isinf(infVar) && infVar < 0.0;\n"
2443 " out_color = correct ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
2444 "}\n";
2445
2446 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2447 drawQuad(program.get(), "inputAttribute", 0.5f);
2448 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2449}
2450
Corentin Wallez36fd1002016-12-08 11:30:44 -05002451// The following MultipleDeclaration* tests are testing TranslatorHLSL specific simplification
2452// passes. Because the interaction of multiple passes must be tested, it is difficult to write
2453// a unittest for them. Instead we add the tests as end2end so will in particular test
2454// TranslatorHLSL when run on Windows.
2455
2456// Test that passes splitting multiple declarations and comma operators are correctly ordered.
2457TEST_P(GLSLTest_ES3, MultipleDeclarationWithCommaOperator)
2458{
2459 const std::string &fragmentShader =
Olli Etuaho7caa80e2017-11-14 15:03:14 +02002460 R"(#version 300 es
2461 precision mediump float;
2462 out vec4 color;
2463
2464 uniform float u;
2465 float c = 0.0;
2466 float sideEffect()
2467 {
2468 c = u;
2469 return c;
2470 }
2471
2472 void main(void)
2473 {
2474 float a = 0.0, b = ((gl_FragCoord.x < 0.5 ? a : sideEffect()), a);
2475 color = vec4(b + c);
2476 })";
Corentin Wallez36fd1002016-12-08 11:30:44 -05002477
2478 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2479}
2480
2481// Test that passes splitting multiple declarations and comma operators and for loops are
2482// correctly ordered.
2483TEST_P(GLSLTest_ES3, MultipleDeclarationWithCommaOperatorInForLoop)
2484{
2485 const std::string &fragmentShader =
Olli Etuaho7caa80e2017-11-14 15:03:14 +02002486 R"(#version 300 es
2487 precision mediump float;
2488 out vec4 color;
2489
2490 uniform float u;
2491 float c = 0.0;
2492 float sideEffect()
2493 {
2494 c = u;
2495 return c;
2496 }
2497
2498 void main(void)
2499 {
2500 for(float a = 0.0, b = ((gl_FragCoord.x < 0.5 ? a : sideEffect()), a); a < 10.0; a++)
2501 {
2502 b += 1.0;
2503 color = vec4(b);
2504 }
2505 })";
Corentin Wallez36fd1002016-12-08 11:30:44 -05002506
2507 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2508}
2509
2510// Test that splitting multiple declaration in for loops works with no loop condition
2511TEST_P(GLSLTest_ES3, MultipleDeclarationInForLoopEmptyCondition)
2512{
2513 const std::string &fragmentShader =
2514 "#version 300 es\n"
2515 "precision mediump float;\n"
2516 "out vec4 color;\n"
2517 "void main(void)\n"
2518 "{\n"
2519 " for(float a = 0.0, b = 1.0;; a++)\n"
2520 " {\n"
2521 " b += 1.0;\n"
2522 " if (a > 10.0) {break;}\n"
2523 " color = vec4(b);\n"
2524 " }\n"
2525 "}\n";
2526
2527 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2528}
2529
2530// Test that splitting multiple declaration in for loops works with no loop expression
2531TEST_P(GLSLTest_ES3, MultipleDeclarationInForLoopEmptyExpression)
2532{
2533 const std::string &fragmentShader =
2534 "#version 300 es\n"
2535 "precision mediump float;\n"
2536 "out vec4 color;\n"
2537 "void main(void)\n"
2538 "{\n"
2539 " for(float a = 0.0, b = 1.0; a < 10.0;)\n"
2540 " {\n"
2541 " b += 1.0;\n"
2542 " a += 1.0;\n"
2543 " color = vec4(b);\n"
2544 " }\n"
2545 "}\n";
2546
2547 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2548}
2549
Olli Etuaho8f6eb2a2017-01-12 17:04:58 +00002550// Test that dynamic indexing of a matrix inside a dynamic indexing of a vector in an l-value works
2551// correctly.
2552TEST_P(GLSLTest_ES3, NestedDynamicIndexingInLValue)
2553{
2554 const std::string &fragmentShader =
2555 "#version 300 es\n"
2556 "precision mediump float;\n"
2557 "out vec4 my_FragColor;\n"
2558 "uniform int u_zero;\n"
2559 "void main() {\n"
2560 " mat2 m = mat2(0.0, 0.0, 0.0, 0.0);\n"
2561 " m[u_zero + 1][u_zero + 1] = float(u_zero + 1);\n"
2562 " float f = m[1][1];\n"
2563 " my_FragColor = vec4(1.0 - f, f, 0.0, 1.0);\n"
2564 "}\n";
2565
2566 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2567 drawQuad(program.get(), "inputAttribute", 0.5f);
2568 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2569}
2570
Jamie Madill192745a2016-12-22 15:58:21 -05002571class WebGLGLSLTest : public GLSLTest
2572{
2573 protected:
2574 WebGLGLSLTest() { setWebGLCompatibilityEnabled(true); }
2575};
2576
2577TEST_P(WebGLGLSLTest, MaxVaryingVec4PlusFragCoord)
2578{
2579 GLint maxVaryings = 0;
2580 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2581
2582 // Generate shader code that uses gl_FragCoord, a special fragment shader variables.
2583 // This test should fail, since we are really using (maxVaryings + 1) varyings.
2584 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, true, false, false, false);
2585}
2586
2587TEST_P(WebGLGLSLTest, MaxVaryingVec4PlusPointCoord)
2588{
2589 GLint maxVaryings = 0;
2590 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2591
2592 // Generate shader code that uses gl_FragCoord, a special fragment shader variables.
2593 // This test should fail, since we are really using (maxVaryings + 1) varyings.
2594 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, false, true, false, false);
2595}
2596
2597TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec3)
2598{
2599 GLint maxVaryings = 0;
2600 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2601
2602 VaryingTestBase(0, 0, 0, 0, maxVaryings + 1, 0, 0, 0, false, false, false, false);
2603}
2604
2605TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec3Array)
2606{
2607 GLint maxVaryings = 0;
2608 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2609
2610 VaryingTestBase(0, 0, 0, 0, 0, maxVaryings / 2 + 1, 0, 0, false, false, false, false);
2611}
2612
2613TEST_P(WebGLGLSLTest, MaxVaryingVec3AndOneVec2)
2614{
2615 GLint maxVaryings = 0;
2616 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2617
2618 VaryingTestBase(0, 0, 1, 0, maxVaryings, 0, 0, 0, false, false, false, false);
2619}
2620
2621TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec2)
2622{
2623 GLint maxVaryings = 0;
2624 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2625
2626 VaryingTestBase(0, 0, 2 * maxVaryings + 1, 0, 0, 0, 0, 0, false, false, false, false);
2627}
2628
2629TEST_P(WebGLGLSLTest, MaxVaryingVec3ArrayAndMaxPlusOneFloatArray)
2630{
2631 GLint maxVaryings = 0;
2632 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2633
2634 VaryingTestBase(0, maxVaryings / 2 + 1, 0, 0, 0, 0, 0, maxVaryings / 2, false, false, false,
2635 false);
2636}
2637
Jamie Madill6c9503e2016-08-16 14:06:32 -04002638} // anonymous namespace
2639
Olli Etuaho9250cb22017-01-21 10:51:27 +00002640// Test that FindLSB and FindMSB return correct values in their corner cases.
2641TEST_P(GLSLTest_ES31, FindMSBAndFindLSBCornerCases)
2642{
Olli Etuaho61bd9fe2017-01-27 14:20:34 -08002643 // Suspecting AMD driver bug - failure seen on bots running on AMD R5 230.
Yunchao He9550c602018-02-13 14:47:05 +08002644 ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL() && IsLinux());
Olli Etuaho61bd9fe2017-01-27 14:20:34 -08002645
Yuly Novikov4e36db82018-01-19 17:35:33 -05002646 // Failing on N5X Oreo http://anglebug.com/2304
2647 ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
2648
Olli Etuaho9250cb22017-01-21 10:51:27 +00002649 const std::string &fragmentShader =
2650 "#version 310 es\n"
2651 "precision mediump float;\n"
2652 "out vec4 my_FragColor;\n"
2653 "uniform int u_zero;\n"
2654 "void main() {\n"
2655 " if (findLSB(u_zero) == -1 && findMSB(u_zero) == -1 && findMSB(u_zero - 1) == -1)\n"
2656 " {\n"
2657 " my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
2658 " }\n"
2659 " else\n"
2660 " {\n"
2661 " my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
2662 " }\n"
2663 "}\n";
2664
2665 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2666 drawQuad(program.get(), "inputAttribute", 0.5f);
2667 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2668}
2669
Olli Etuahoc9da71f2017-03-06 16:28:54 +00002670// Test that writing into a swizzled vector that is dynamically indexed succeeds.
2671TEST_P(GLSLTest_ES3, WriteIntoDynamicIndexingOfSwizzledVector)
2672{
Yunchao He9550c602018-02-13 14:47:05 +08002673 // http://anglebug.com/1924
2674 ANGLE_SKIP_TEST_IF(IsOpenGL());
Olli Etuahoc9da71f2017-03-06 16:28:54 +00002675
2676 // The shader first assigns v.x to v.z (1.0)
2677 // Then v.y to v.y (2.0)
2678 // Then v.z to v.x (1.0)
2679 const std::string &fragmentShader =
2680 "#version 300 es\n"
2681 "precision highp float;\n"
2682 "out vec4 my_FragColor;\n"
2683 "void main() {\n"
2684 " vec3 v = vec3(1.0, 2.0, 3.0);\n"
2685 " for (int i = 0; i < 3; i++) {\n"
2686 " v.zyx[i] = v[i];\n"
2687 " }\n"
2688 " my_FragColor = distance(v, vec3(1.0, 2.0, 1.0)) < 0.01 ? vec4(0, 1, 0, 1) : vec4(1, "
2689 "0, 0, 1);\n"
2690 "}\n";
2691
2692 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2693 drawQuad(program.get(), "inputAttribute", 0.5f);
2694 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2695}
2696
Jamie Madill8aeeed62017-03-15 18:09:26 -04002697// This test covers a bug (and associated workaround) with nested sampling operations in the HLSL
2698// compiler DLL.
2699TEST_P(GLSLTest_ES3, NestedSamplingOperation)
2700{
2701 // This seems to be bugged on some version of Android. Might not affect the newest versions.
2702 // TODO(jmadill): Lift suppression when Chromium bots are upgraded.
Yunchao He9550c602018-02-13 14:47:05 +08002703 // Test skipped on Android because of bug with Nexus 5X.
2704 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
Jamie Madill8aeeed62017-03-15 18:09:26 -04002705
2706 const std::string &vertexShader =
2707 "#version 300 es\n"
2708 "out vec2 texCoord;\n"
2709 "in vec2 position;\n"
2710 "void main()\n"
2711 "{\n"
2712 " gl_Position = vec4(position, 0, 1);\n"
2713 " texCoord = position * 0.5 + vec2(0.5);\n"
2714 "}\n";
2715
2716 const std::string &simpleFragmentShader =
2717 "#version 300 es\n"
2718 "in mediump vec2 texCoord;\n"
2719 "out mediump vec4 fragColor;\n"
2720 "void main()\n"
2721 "{\n"
2722 " fragColor = vec4(texCoord, 0, 1);\n"
2723 "}\n";
2724
2725 const std::string &nestedFragmentShader =
2726 "#version 300 es\n"
2727 "uniform mediump sampler2D samplerA;\n"
2728 "uniform mediump sampler2D samplerB;\n"
2729 "in mediump vec2 texCoord;\n"
2730 "out mediump vec4 fragColor;\n"
2731 "void main ()\n"
2732 "{\n"
2733 " fragColor = texture(samplerB, texture(samplerA, texCoord).xy);\n"
2734 "}\n";
2735
2736 ANGLE_GL_PROGRAM(initProg, vertexShader, simpleFragmentShader);
2737 ANGLE_GL_PROGRAM(nestedProg, vertexShader, nestedFragmentShader);
2738
2739 // Initialize a first texture with default texCoord data.
2740 GLTexture texA;
2741 glActiveTexture(GL_TEXTURE0);
2742 glBindTexture(GL_TEXTURE_2D, texA);
2743 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
2744 GL_UNSIGNED_BYTE, nullptr);
2745 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2746 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2747
2748 GLFramebuffer fbo;
2749 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2750 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texA, 0);
2751
2752 drawQuad(initProg, "position", 0.5f);
2753 ASSERT_GL_NO_ERROR();
2754
2755 // Initialize a second texture with a simple color pattern.
2756 GLTexture texB;
2757 glActiveTexture(GL_TEXTURE1);
2758 glBindTexture(GL_TEXTURE_2D, texB);
2759
2760 std::array<GLColor, 4> simpleColors = {
2761 {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
2762 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2763 simpleColors.data());
2764 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2765 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2766
2767 // Draw with the nested program, using the first texture to index the second.
2768 glBindFramebuffer(GL_FRAMEBUFFER, 0);
2769 glUseProgram(nestedProg);
2770 GLint samplerALoc = glGetUniformLocation(nestedProg, "samplerA");
2771 ASSERT_NE(-1, samplerALoc);
2772 glUniform1i(samplerALoc, 0);
2773 GLint samplerBLoc = glGetUniformLocation(nestedProg, "samplerB");
2774 ASSERT_NE(-1, samplerBLoc);
2775 glUniform1i(samplerBLoc, 1);
2776
2777 drawQuad(nestedProg, "position", 0.5f);
2778 ASSERT_GL_NO_ERROR();
2779
2780 // Compute four texel centers.
2781 Vector2 windowSize(getWindowWidth(), getWindowHeight());
2782 Vector2 quarterWindowSize = windowSize / 4;
2783 Vector2 ul = quarterWindowSize;
2784 Vector2 ur(windowSize.x() - quarterWindowSize.x(), quarterWindowSize.y());
2785 Vector2 ll(quarterWindowSize.x(), windowSize.y() - quarterWindowSize.y());
2786 Vector2 lr = windowSize - quarterWindowSize;
2787
2788 EXPECT_PIXEL_COLOR_EQ_VEC2(ul, simpleColors[0]);
2789 EXPECT_PIXEL_COLOR_EQ_VEC2(ur, simpleColors[1]);
2790 EXPECT_PIXEL_COLOR_EQ_VEC2(ll, simpleColors[2]);
2791 EXPECT_PIXEL_COLOR_EQ_VEC2(lr, simpleColors[3]);
2792}
2793
Olli Etuaho81629262017-04-19 11:56:01 +03002794// Tests that using a constant declaration as the only statement in a for loop without curly braces
2795// doesn't crash.
2796TEST_P(GLSLTest, ConstantStatementInForLoop)
2797{
2798 const std::string &vertexShader =
2799 "void main()\n"
2800 "{\n"
2801 " for (int i = 0; i < 10; ++i)\n"
2802 " const int b = 0;\n"
2803 "}\n";
2804
2805 GLuint shader = CompileShader(GL_VERTEX_SHADER, vertexShader);
2806 EXPECT_NE(0u, shader);
2807 glDeleteShader(shader);
2808}
2809
2810// Tests that using a constant declaration as a loop init expression doesn't crash. Note that this
2811// test doesn't work on D3D9 due to looping limitations, so it is only run on ES3.
2812TEST_P(GLSLTest_ES3, ConstantStatementAsLoopInit)
2813{
2814 const std::string &vertexShader =
2815 "void main()\n"
2816 "{\n"
2817 " for (const int i = 0; i < 0;) {}\n"
2818 "}\n";
2819
2820 GLuint shader = CompileShader(GL_VERTEX_SHADER, vertexShader);
2821 EXPECT_NE(0u, shader);
2822 glDeleteShader(shader);
2823}
2824
Olli Etuaho9733cee2017-05-11 19:14:35 +03002825// Test that uninitialized local variables are initialized to 0.
2826TEST_P(GLSLTest_ES3, InitUninitializedLocals)
2827{
Yunchao He9550c602018-02-13 14:47:05 +08002828 // Test skipped on Android GLES because local variable initialization is disabled.
2829 // http://anglebug.com/2046
2830 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
Olli Etuaho9733cee2017-05-11 19:14:35 +03002831
Olli Etuaho9733cee2017-05-11 19:14:35 +03002832 const std::string &fragmentShader =
2833 "#version 300 es\n"
2834 "precision mediump float;\n"
2835 "out vec4 my_FragColor;\n"
2836 "int result = 0;\n"
2837 "void main()\n"
2838 "{\n"
2839 " int u;\n"
2840 " result += u;\n"
2841 " int k = 0;\n"
2842 " for (int i[2], j = i[0] + 1; k < 2; ++k)\n"
2843 " {\n"
2844 " result += j;\n"
2845 " }\n"
2846 " if (result == 2)\n"
2847 " {\n"
2848 " my_FragColor = vec4(0, 1, 0, 1);\n"
2849 " }\n"
2850 " else\n"
2851 " {\n"
2852 " my_FragColor = vec4(1, 0, 0, 1);\n"
2853 " }\n"
2854 "}\n";
2855
2856 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2857 drawQuad(program.get(), "inputAttribute", 0.5f);
2858 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2859}
2860
2861// Test that uninitialized structs containing arrays of structs are initialized to 0. This
2862// specifically tests with two different struct variables declared in the same block.
2863TEST_P(GLSLTest, InitUninitializedStructContainingArrays)
2864{
Yunchao He9550c602018-02-13 14:47:05 +08002865 // Test skipped on Android GLES because local variable initialization is disabled.
2866 // http://anglebug.com/2046
2867 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
Olli Etuaho9733cee2017-05-11 19:14:35 +03002868
Olli Etuaho9733cee2017-05-11 19:14:35 +03002869 const std::string &fragmentShader =
2870 "precision mediump float;\n"
2871 "struct T\n"
2872 "{\n"
2873 " int a[2];\n"
2874 "};\n"
2875 "struct S\n"
2876 "{\n"
2877 " T t[2];\n"
2878 "};\n"
2879 "void main()\n"
2880 "{\n"
2881 " S s;\n"
2882 " S s2;\n"
2883 " if (s.t[1].a[1] == 0 && s2.t[1].a[1] == 0)\n"
2884 " {\n"
2885 " gl_FragColor = vec4(0, 1, 0, 1);\n"
2886 " }\n"
2887 " else\n"
2888 " {\n"
2889 " gl_FragColor = vec4(1, 0, 0, 1);\n"
2890 " }\n"
2891 "}\n";
2892
2893 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2894 drawQuad(program.get(), "inputAttribute", 0.5f);
2895 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2896}
2897
Geoff Langbb1e7502017-06-05 16:40:09 -04002898// Verify that two shaders with the same uniform name and members but different structure names will
2899// not link.
2900TEST_P(GLSLTest, StructureNameMatchingTest)
2901{
2902 const char *vsSource =
2903 "// Structures must have the same name, sequence of type names, and\n"
2904 "// type definitions, and field names to be considered the same type.\n"
2905 "// GLSL 1.017 4.2.4\n"
2906 "precision mediump float;\n"
2907 "struct info {\n"
2908 " vec4 pos;\n"
2909 " vec4 color;\n"
2910 "};\n"
2911 "\n"
2912 "uniform info uni;\n"
2913 "void main()\n"
2914 "{\n"
2915 " gl_Position = uni.pos;\n"
2916 "}\n";
2917
2918 GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
2919 ASSERT_NE(0u, vs);
2920 glDeleteShader(vs);
2921
2922 const char *fsSource =
2923 "// Structures must have the same name, sequence of type names, and\n"
2924 "// type definitions, and field names to be considered the same type.\n"
2925 "// GLSL 1.017 4.2.4\n"
2926 "precision mediump float;\n"
2927 "struct info1 {\n"
2928 " vec4 pos;\n"
2929 " vec4 color;\n"
2930 "};\n"
2931 "\n"
2932 "uniform info1 uni;\n"
2933 "void main()\n"
2934 "{\n"
2935 " gl_FragColor = uni.color;\n"
2936 "}\n";
2937
2938 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
2939 ASSERT_NE(0u, fs);
2940 glDeleteShader(fs);
2941
2942 GLuint program = CompileProgram(vsSource, fsSource);
2943 EXPECT_EQ(0u, program);
2944}
2945
Olli Etuaho9733cee2017-05-11 19:14:35 +03002946// Test that an uninitialized nameless struct inside a for loop init statement works.
2947TEST_P(GLSLTest_ES3, UninitializedNamelessStructInForInitStatement)
2948{
Yunchao He9550c602018-02-13 14:47:05 +08002949 // Test skipped on Android GLES because local variable initialization is disabled.
2950 // http://anglebug.com/2046
2951 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
Olli Etuaho9733cee2017-05-11 19:14:35 +03002952
Olli Etuaho9733cee2017-05-11 19:14:35 +03002953 const std::string &fragmentShader =
2954 "#version 300 es\n"
2955 "precision highp float;\n"
2956 "out vec4 my_FragColor;\n"
2957 "void main()\n"
2958 "{\n"
2959 " my_FragColor = vec4(1, 0, 0, 1);\n"
2960 " for (struct { float q; } b; b.q < 2.0; b.q++) {\n"
2961 " my_FragColor = vec4(0, 1, 0, 1);\n"
2962 " }\n"
2963 "}\n";
2964
2965 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2966 drawQuad(program.get(), "inputAttribute", 0.5f);
2967 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2968}
2969
Olli Etuaho0ffc4412017-05-19 14:18:55 +03002970// Test that uninitialized global variables are initialized to 0.
2971TEST_P(WebGLGLSLTest, InitUninitializedGlobals)
2972{
2973 const std::string &fragmentShader =
2974 "precision mediump float;\n"
2975 "int result;\n"
2976 "int i[2], j = i[0] + 1;\n"
2977 "void main()\n"
2978 "{\n"
2979 " result += j;\n"
2980 " if (result == 1)\n"
2981 " {\n"
2982 " gl_FragColor = vec4(0, 1, 0, 1);\n"
2983 " }\n"
2984 " else\n"
2985 " {\n"
2986 " gl_FragColor = vec4(1, 0, 0, 1);\n"
2987 " }\n"
2988 "}\n";
2989
2990 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2991 drawQuad(program.get(), "inputAttribute", 0.5f, 1.0f, true);
2992 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2993}
2994
2995// Test that an uninitialized nameless struct in the global scope works.
2996TEST_P(WebGLGLSLTest, UninitializedNamelessStructInGlobalScope)
2997{
2998 const std::string &fragmentShader =
2999 "precision mediump float;\n"
3000 "struct { float q; } b;\n"
3001 "void main()\n"
3002 "{\n"
3003 " gl_FragColor = vec4(1, 0, 0, 1);\n"
3004 " if (b.q == 0.0)\n"
3005 " {\n"
3006 " gl_FragColor = vec4(0, 1, 0, 1);\n"
3007 " }\n"
3008 "}\n";
3009
3010 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3011 drawQuad(program.get(), "inputAttribute", 0.5f, 1.0f, true);
3012 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3013}
3014
Olli Etuaho914b79a2017-06-19 16:03:19 +03003015// Test that a loop condition that has an initializer declares a variable.
3016TEST_P(GLSLTest_ES3, ConditionInitializerDeclaresVariable)
3017{
3018 const std::string &fragmentShader =
3019 "#version 300 es\n"
3020 "precision highp float;\n"
3021 "out vec4 my_FragColor;\n"
3022 "void main()\n"
3023 "{\n"
3024 " float i = 0.0;\n"
3025 " while (bool foo = (i < 1.5))\n"
3026 " {\n"
3027 " if (!foo)\n"
3028 " {\n"
3029 " ++i;\n"
3030 " }\n"
3031 " if (i > 3.5)\n"
3032 " {\n"
3033 " break;\n"
3034 " }\n"
3035 " ++i;\n"
3036 " }\n"
3037 " my_FragColor = vec4(i * 0.5 - 1.0, i * 0.5, 0.0, 1.0);\n"
3038 "}\n";
3039
3040 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3041 drawQuad(program.get(), "inputAttribute", 0.5f);
3042 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3043}
3044
Olli Etuahoff526f12017-06-30 12:26:54 +03003045// Test that a variable hides a user-defined function with the same name after its initializer.
3046// GLSL ES 1.00.17 section 4.2.2: "A variable declaration is visible immediately following the
3047// initializer if present, otherwise immediately following the identifier"
3048TEST_P(GLSLTest, VariableHidesUserDefinedFunctionAfterInitializer)
3049{
3050 const std::string &fragmentShader =
3051 "precision mediump float;\n"
3052 "uniform vec4 u;\n"
3053 "vec4 foo()\n"
3054 "{\n"
3055 " return u;\n"
3056 "}\n"
3057 "void main()\n"
3058 "{\n"
3059 " vec4 foo = foo();\n"
3060 " gl_FragColor = foo + vec4(0, 1, 0, 1);\n"
3061 "}\n";
3062
3063 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3064 drawQuad(program.get(), "inputAttribute", 0.5f);
3065 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3066}
3067
Olli Etuaho088031e2017-07-03 15:59:33 +03003068// Test that structs with identical members are not ambiguous as function arguments.
3069TEST_P(GLSLTest, StructsWithSameMembersDisambiguatedByName)
3070{
3071 const std::string &fragmentShader =
3072 "precision mediump float;\n"
3073 "uniform float u_zero;\n"
3074 "struct S { float foo; };\n"
3075 "struct S2 { float foo; };\n"
3076 "float get(S s) { return s.foo + u_zero; }\n"
3077 "float get(S2 s2) { return 0.25 + s2.foo + u_zero; }\n"
3078 "void main()\n"
3079 "{\n"
3080 " S s;\n"
3081 " s.foo = 0.5;\n"
3082 " S2 s2;\n"
3083 " s2.foo = 0.25;\n"
3084 " gl_FragColor = vec4(0.0, get(s) + get(s2), 0.0, 1.0);\n"
3085 "}\n";
3086
3087 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3088 drawQuad(program.get(), "inputAttribute", 0.5f);
3089 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3090}
3091
Olli Etuaho06a06f52017-07-12 12:22:15 +03003092// Test that a varying struct that's not statically used in the fragment shader works.
3093// GLSL ES 3.00.6 section 4.3.10.
3094TEST_P(GLSLTest_ES3, VaryingStructNotStaticallyUsedInFragmentShader)
3095{
3096 const std::string &vertexShader =
3097 "#version 300 es\n"
3098 "struct S {\n"
3099 " vec4 field;\n"
3100 "};\n"
3101 "out S varStruct;\n"
3102 "void main()\n"
3103 "{\n"
3104 " gl_Position = vec4(1.0);\n"
3105 " varStruct.field = vec4(0.0, 0.5, 0.0, 0.0);\n"
3106 "}\n";
3107
3108 const std::string &fragmentShader =
3109 "#version 300 es\n"
3110 "precision mediump float;\n"
3111 "struct S {\n"
3112 " vec4 field;\n"
3113 "};\n"
3114 "in S varStruct;\n"
3115 "out vec4 col;\n"
3116 "void main()\n"
3117 "{\n"
3118 " col = vec4(1.0);\n"
3119 "}\n";
3120
3121 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3122}
3123
3124// Test that a varying struct that's not declared in the fragment shader links successfully.
3125// GLSL ES 3.00.6 section 4.3.10.
3126TEST_P(GLSLTest_ES3, VaryingStructNotDeclaredInFragmentShader)
3127{
3128 const std::string &vertexShader =
3129 "#version 300 es\n"
3130 "struct S {\n"
3131 " vec4 field;\n"
3132 "};\n"
3133 "out S varStruct;\n"
3134 "void main()\n"
3135 "{\n"
3136 " gl_Position = vec4(1.0);\n"
3137 " varStruct.field = vec4(0.0, 0.5, 0.0, 0.0);\n"
3138 "}\n";
3139
3140 const std::string &fragmentShader =
3141 "#version 300 es\n"
3142 "precision mediump float;\n"
3143 "out vec4 col;\n"
3144 "void main()\n"
3145 "{\n"
3146 " col = vec4(1.0);\n"
3147 "}\n";
3148
3149 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3150}
3151
3152// Test that a varying struct that gets used in the fragment shader works.
3153TEST_P(GLSLTest_ES3, VaryingStructUsedInFragmentShader)
3154{
3155 const std::string &vertexShader =
3156 "#version 300 es\n"
3157 "in vec4 inputAttribute;\n"
3158 "struct S {\n"
3159 " vec4 field;\n"
3160 "};\n"
3161 "out S varStruct;\n"
3162 "void main()\n"
3163 "{\n"
3164 " gl_Position = inputAttribute;\n"
3165 " varStruct.field = vec4(0.0, 1.0, 0.0, 1.0);\n"
3166 "}\n";
3167
3168 const std::string &fragmentShader =
3169 "#version 300 es\n"
3170 "precision mediump float;\n"
3171 "out vec4 col;\n"
3172 "struct S {\n"
3173 " vec4 field;\n"
3174 "};\n"
3175 "in S varStruct;\n"
3176 "void main()\n"
3177 "{\n"
3178 " col = varStruct.field;\n"
3179 "}\n";
3180
3181 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3182 drawQuad(program.get(), "inputAttribute", 0.5f);
3183 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3184}
3185
Olli Etuaho3860b6c2017-07-19 16:17:24 +03003186// This test covers passing an array of structs containing samplers as a function argument.
3187TEST_P(GLSLTest, ArrayOfStructsWithSamplersAsFunctionArg)
3188{
Yunchao He9550c602018-02-13 14:47:05 +08003189 // Shader failed to compile on Android. http://anglebug.com/2114
3190 ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
Olli Etuaho3860b6c2017-07-19 16:17:24 +03003191
3192 const std::string &vertexShader =
3193 "attribute vec2 position;\n"
3194 "void main()\n"
3195 "{\n"
3196 " gl_Position = vec4(position, 0, 1);\n"
3197 "}\n";
3198
3199 const std::string &fragmentShader =
3200 "precision mediump float;\n"
3201 "struct S\n"
3202 "{\n"
3203 " sampler2D samplerMember; \n"
3204 "};\n"
3205 "uniform S uStructs[2];\n"
3206 "uniform vec2 uTexCoord;\n"
3207 "\n"
3208 "vec4 foo(S[2] structs)\n"
3209 "{\n"
3210 " return texture2D(structs[0].samplerMember, uTexCoord);\n"
3211 "}\n"
3212 "void main()\n"
3213 "{\n"
3214 " gl_FragColor = foo(uStructs);\n"
3215 "}\n";
3216
3217 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3218
3219 // Initialize the texture with green.
3220 GLTexture tex;
3221 glActiveTexture(GL_TEXTURE0);
3222 glBindTexture(GL_TEXTURE_2D, tex);
3223 GLubyte texData[] = {0u, 255u, 0u, 255u};
3224 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
3225 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3226 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3227 ASSERT_GL_NO_ERROR();
3228
3229 // Draw
3230 glUseProgram(program);
3231 GLint samplerMemberLoc = glGetUniformLocation(program, "uStructs[0].samplerMember");
3232 ASSERT_NE(-1, samplerMemberLoc);
3233 glUniform1i(samplerMemberLoc, 0);
3234 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
3235 ASSERT_NE(-1, texCoordLoc);
3236 glUniform2f(texCoordLoc, 0.5f, 0.5f);
3237
3238 drawQuad(program, "position", 0.5f);
3239 ASSERT_GL_NO_ERROR();
3240
3241 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
3242}
3243
Olli Etuaho28839f02017-08-15 11:38:16 +03003244// This test covers passing a struct containing an array of samplers as a function argument.
3245TEST_P(GLSLTest, StructWithSamplerArrayAsFunctionArg)
3246{
Yunchao He9550c602018-02-13 14:47:05 +08003247 // Shader failed to compile on Android. http://anglebug.com/2114
3248 ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
Olli Etuaho28839f02017-08-15 11:38:16 +03003249
3250 const std::string &vertexShader =
3251 "attribute vec2 position;\n"
3252 "void main()\n"
3253 "{\n"
3254 " gl_Position = vec4(position, 0, 1);\n"
3255 "}\n";
3256
3257 const std::string &fragmentShader =
3258 "precision mediump float;\n"
3259 "struct S\n"
3260 "{\n"
3261 " sampler2D samplerMembers[2];\n"
3262 "};\n"
3263 "uniform S uStruct;\n"
3264 "uniform vec2 uTexCoord;\n"
3265 "\n"
3266 "vec4 foo(S str)\n"
3267 "{\n"
3268 " return texture2D(str.samplerMembers[0], uTexCoord);\n"
3269 "}\n"
3270 "void main()\n"
3271 "{\n"
3272 " gl_FragColor = foo(uStruct);\n"
3273 "}\n";
3274
3275 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3276
3277 // Initialize the texture with green.
3278 GLTexture tex;
3279 glActiveTexture(GL_TEXTURE0);
3280 glBindTexture(GL_TEXTURE_2D, tex);
3281 GLubyte texData[] = {0u, 255u, 0u, 255u};
3282 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
3283 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3284 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3285 ASSERT_GL_NO_ERROR();
3286
3287 // Draw
3288 glUseProgram(program);
3289 GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMembers[0]");
3290 ASSERT_NE(-1, samplerMemberLoc);
3291 glUniform1i(samplerMemberLoc, 0);
3292 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
3293 ASSERT_NE(-1, texCoordLoc);
3294 glUniform2f(texCoordLoc, 0.5f, 0.5f);
3295
3296 drawQuad(program, "position", 0.5f);
3297 ASSERT_GL_NO_ERROR();
3298
3299 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
3300}
3301
Olli Etuahoa16a84f2017-09-12 13:49:18 +03003302// Test that a global variable declared after main() works. This is a regression test for an issue
3303// in global variable initialization.
3304TEST_P(WebGLGLSLTest, GlobalVariableDeclaredAfterMain)
3305{
3306 const std::string &fragmentShader =
3307 "precision mediump float;\n"
3308 "int getFoo();\n"
3309 "uniform int u_zero;\n"
3310 "void main()\n"
3311 "{\n"
3312 " gl_FragColor = vec4(1, 0, 0, 1);\n"
3313 " if (getFoo() == 0)\n"
3314 " {\n"
3315 " gl_FragColor = vec4(0, 1, 0, 1);\n"
3316 " }\n"
3317 "}\n"
3318 "int foo;\n"
3319 "int getFoo()\n"
3320 "{\n"
3321 " foo = u_zero;\n"
3322 " return foo;\n"
3323 "}\n";
3324
3325 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3326 drawQuad(program.get(), "inputAttribute", 0.5f, 1.0f, true);
3327 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3328}
3329
Olli Etuahobb5a7e22017-08-30 13:03:12 +03003330// Test calling array length() with a "this" expression having side effects inside a loop condition.
3331// The spec says that sequence operator operands need to run in sequence.
3332TEST_P(GLSLTest_ES3, ArrayLengthOnExpressionWithSideEffectsInLoopCondition)
3333{
3334 // "a" gets doubled three times in the below program.
3335 const std::string &fragmentShader =
3336 R"(#version 300 es
3337 precision highp float;
3338 out vec4 my_FragColor;
3339 uniform int u_zero;
3340 int a;
3341 int[2] doubleA()
3342 {
3343 a *= 2;
3344 return int[2](a, a);
3345 }
3346 void main()
3347 {
3348 a = u_zero + 1;
3349 for (int i = 0; i < doubleA().length(); ++i)
3350 {}
3351 if (a == 8)
3352 {
3353 my_FragColor = vec4(0, 1, 0, 1);
3354 }
3355 else
3356 {
3357 my_FragColor = vec4(1, 0, 0, 1);
3358 }
3359 })";
3360
3361 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3362 drawQuad(program.get(), "inputAttribute", 0.5f);
3363 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3364}
3365
3366// Test calling array length() with a "this" expression having side effects that interact with side
3367// effects of another operand of the same sequence operator. The spec says that sequence operator
3368// operands need to run in order from left to right (ESSL 3.00.6 section 5.9).
3369TEST_P(GLSLTest_ES3, ArrayLengthOnExpressionWithSideEffectsInSequence)
3370{
3371 const std::string &fragmentShader =
3372 R"(#version 300 es
3373 precision highp float;
3374 out vec4 my_FragColor;
3375 uniform int u_zero;
3376 int a;
3377 int[3] doubleA()
3378 {
3379 a *= 2;
3380 return int[3](a, a, a);
3381 }
3382 void main()
3383 {
3384 a = u_zero;
3385 int b = (a++, doubleA().length());
3386 if (b == 3 && a == 2)
3387 {
3388 my_FragColor = vec4(0, 1, 0, 1);
3389 }
3390 else
3391 {
3392 my_FragColor = vec4(1, 0, 0, 1);
3393 }
3394 })";
3395
3396 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3397 drawQuad(program.get(), "inputAttribute", 0.5f);
3398 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3399}
3400
3401// Test calling array length() with a "this" expression that also contains a call of array length().
3402// Both "this" expressions also have side effects.
3403TEST_P(GLSLTest_ES3, NestedArrayLengthMethodsWithSideEffects)
3404{
3405 const std::string &fragmentShader =
3406 R"(#version 300 es
3407 precision highp float;
3408 out vec4 my_FragColor;
3409 uniform int u_zero;
3410 int a;
3411 int[3] multiplyA(int multiplier)
3412 {
3413 a *= multiplier;
3414 return int[3](a, a, a);
3415 }
3416 void main()
3417 {
3418 a = u_zero + 1;
3419 int b = multiplyA(multiplyA(2).length()).length();
3420 if (b == 3 && a == 6)
3421 {
3422 my_FragColor = vec4(0, 1, 0, 1);
3423 }
3424 else
3425 {
3426 my_FragColor = vec4(1, 0, 0, 1);
3427 }
3428 })";
3429
3430 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3431 drawQuad(program.get(), "inputAttribute", 0.5f);
3432 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3433}
3434
Olli Etuaho78507c62017-10-10 15:06:45 +03003435// Test that statements inside switch() get translated to correct HLSL.
3436TEST_P(GLSLTest_ES3, DifferentStatementsInsideSwitch)
3437{
3438 const std::string &fragmentShader =
3439 R"(#version 300 es
3440
3441 precision highp float;
3442
3443 uniform int u;
3444
3445 void main()
3446 {
3447 switch (u)
3448 {
3449 case 0:
3450 ivec2 i;
3451 i.yx;
3452 }
3453 })";
3454 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3455}
3456
Olli Etuaho852fe872017-10-10 15:13:59 +03003457// Test that switch fall-through works correctly.
3458// This is a regression test for http://anglebug.com/2178
3459TEST_P(GLSLTest_ES3, SwitchFallThroughCodeDuplication)
3460{
3461 const std::string &fragmentShader =
3462 R"(#version 300 es
3463
3464 precision highp float;
3465
3466 out vec4 my_FragColor;
3467
3468 uniform int u_zero;
3469
3470 void main()
3471 {
3472 int i = 0;
3473 // switch should fall through both cases.
3474 switch(u_zero)
3475 {
3476 case 0:
3477 i += 1;
3478 case 1:
3479 i += 2;
3480 }
3481 if (i == 3)
3482 {
3483 my_FragColor = vec4(0, 1, 0, 1);
3484 }
3485 else
3486 {
3487 my_FragColor = vec4(1, 0, 0, 1);
3488 }
3489 })";
3490
3491 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3492 drawQuad(program.get(), "inputAttribute", 0.5f);
3493 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3494}
3495
Olli Etuaho923ecef2017-10-11 12:01:38 +03003496// Test that a switch statement with an empty block inside as a final statement compiles.
3497TEST_P(GLSLTest_ES3, SwitchFinalCaseHasEmptyBlock)
3498{
3499 const std::string &fragmentShader =
3500 R"(#version 300 es
3501
3502 precision mediump float;
3503 uniform int i;
3504 void main()
3505 {
3506 switch (i)
3507 {
3508 case 0:
3509 break;
3510 default:
3511 {}
3512 }
3513 })";
3514 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3515}
3516
3517// Test that a switch statement with an empty declaration inside as a final statement compiles.
3518TEST_P(GLSLTest_ES3, SwitchFinalCaseHasEmptyDeclaration)
3519{
3520 const std::string &fragmentShader =
3521 R"(#version 300 es
3522
3523 precision mediump float;
3524 uniform int i;
3525 void main()
3526 {
3527 switch (i)
3528 {
3529 case 0:
3530 break;
3531 default:
3532 float;
3533 }
3534 })";
3535 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3536}
3537
Olli Etuaho4bd730c2017-10-10 14:14:19 +03003538// Test switch/case where break/return statements are within blocks.
3539TEST_P(GLSLTest_ES3, SwitchBreakOrReturnInsideBlocks)
3540{
3541 const std::string &fragmentShader =
3542 R"(#version 300 es
3543
3544 precision highp float;
3545
3546 uniform int u_zero;
3547 out vec4 my_FragColor;
3548
3549 bool test(int n)
3550 {
3551 switch(n) {
3552 case 0:
3553 {
3554 {
3555 break;
3556 }
3557 }
3558 case 1:
3559 {
3560 return true;
3561 }
3562 case 2:
3563 {
3564 n++;
3565 }
3566 }
3567 return false;
3568 }
3569
3570 void main()
3571 {
3572 my_FragColor = test(u_zero + 1) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
3573 })";
3574
3575 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3576 drawQuad(program.get(), "inputAttribute", 0.5f);
3577 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3578}
3579
Olli Etuahof6d242e2017-10-12 17:21:06 +03003580// Test switch/case where a variable is declared inside one of the cases and is accessed by a
3581// subsequent case.
3582TEST_P(GLSLTest_ES3, SwitchWithVariableDeclarationInside)
3583{
3584 const std::string &fragmentShader =
3585 R"(#version 300 es
3586
3587 precision highp float;
3588 out vec4 my_FragColor;
3589
3590 uniform int u_zero;
3591
3592 void main()
3593 {
3594 my_FragColor = vec4(1, 0, 0, 1);
3595 switch (u_zero)
3596 {
3597 case 0:
3598 ivec2 i;
3599 i = ivec2(1, 0);
3600 default:
3601 my_FragColor = vec4(0, i[0], 0, 1);
3602 }
3603 })";
3604
3605 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3606 drawQuad(program.get(), "inputAttribute", 0.5f);
3607 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3608}
3609
3610// Test nested switch/case where a variable is declared inside one of the cases and is accessed by a
3611// subsequent case.
3612TEST_P(GLSLTest_ES3, NestedSwitchWithVariableDeclarationInside)
3613{
3614 const std::string &fragmentShader =
3615 R"(#version 300 es
3616
3617 precision highp float;
3618 out vec4 my_FragColor;
3619
3620 uniform int u_zero;
3621 uniform int u_zero2;
3622
3623 void main()
3624 {
3625 my_FragColor = vec4(1, 0, 0, 1);
3626 switch (u_zero)
3627 {
3628 case 0:
3629 ivec2 i;
3630 i = ivec2(1, 0);
3631 switch (u_zero2)
3632 {
3633 case 0:
3634 int j;
3635 default:
3636 j = 1;
3637 i *= j;
3638 }
3639 default:
3640 my_FragColor = vec4(0, i[0], 0, 1);
3641 }
3642 })";
3643
3644 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3645 drawQuad(program.get(), "inputAttribute", 0.5f);
3646 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3647}
3648
Olli Etuahoc1f14fb2017-10-28 19:17:23 +03003649// Test that an empty switch/case statement is translated in a way that compiles and executes the
3650// init-statement.
3651TEST_P(GLSLTest_ES3, EmptySwitch)
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 void main()
3662 {
3663 int i = u_zero;
3664 switch(++i) {}
3665 my_FragColor = (i == 1) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
3666 })";
3667
3668 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3669 drawQuad(program.get(), "inputAttribute", 0.5f);
3670 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3671}
3672
Olli Etuahobd3cd502017-11-03 15:48:52 +02003673// Test that a constant struct inside an expression is handled correctly.
3674TEST_P(GLSLTest_ES3, ConstStructInsideExpression)
3675{
3676 // Incorrect output color was seen on Android. http://anglebug.com/2226
3677 ANGLE_SKIP_TEST_IF(IsAndroid() && !IsNVIDIA() && IsOpenGLES());
3678
3679 const std::string &fragmentShader =
3680 R"(#version 300 es
3681
3682 precision highp float;
3683 out vec4 my_FragColor;
3684
3685 uniform float u_zero;
3686
3687 struct S
3688 {
3689 float field;
3690 };
3691
3692 void main()
3693 {
3694 const S constS = S(1.0);
3695 S nonConstS = constS;
3696 nonConstS.field = u_zero;
3697 bool fail = (constS == nonConstS);
3698 my_FragColor = vec4(0, 1, 0, 1);
3699 if (fail)
3700 {
3701 my_FragColor = vec4(1, 0, 0, 1);
3702 }
3703 })";
3704
3705 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3706 drawQuad(program.get(), "inputAttribute", 0.5f);
3707 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3708}
3709
3710// Test that a varying struct that's defined as a part of the declaration is handled correctly.
3711TEST_P(GLSLTest_ES3, VaryingStructWithInlineDefinition)
3712{
3713 const std::string &vertexShader =
3714 R"(#version 300 es
3715 in vec4 inputAttribute;
3716
3717 flat out struct S
3718 {
3719 int field;
3720 } v_s;
3721
3722 void main()
3723 {
3724 v_s.field = 1;
3725 gl_Position = inputAttribute;
3726 })";
3727
3728 const std::string &fragmentShader =
3729 R"(#version 300 es
3730
3731 precision highp float;
3732 out vec4 my_FragColor;
3733
3734 flat in struct S
3735 {
3736 int field;
3737 } v_s;
3738
3739 void main()
3740 {
3741 bool success = (v_s.field == 1);
3742 my_FragColor = vec4(1, 0, 0, 1);
3743 if (success)
3744 {
3745 my_FragColor = vec4(0, 1, 0, 1);
3746 }
3747 })";
3748
3749 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3750 drawQuad(program.get(), "inputAttribute", 0.5f);
3751 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3752}
3753
Olli Etuaho661fc482017-10-16 12:17:05 +03003754// Test vector/scalar arithmetic (in this case multiplication and addition). Meant to reproduce a
3755// bug that appeared in NVIDIA OpenGL drivers and that is worked around by
3756// VectorizeVectorScalarArithmetic AST transform.
3757TEST_P(GLSLTest, VectorScalarMultiplyAndAddInLoop)
3758{
3759 const std::string &fragmentShader =
3760 R"(
3761
3762 precision mediump float;
3763
3764 void main() {
3765 gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
3766 for (int i = 0; i < 2; i++)
3767 {
3768 gl_FragColor += (2.0 * gl_FragCoord.x);
3769 }
3770 if (gl_FragColor.g == gl_FragColor.r &&
3771 gl_FragColor.b == gl_FragColor.r &&
3772 gl_FragColor.a == gl_FragColor.r)
3773 {
3774 gl_FragColor = vec4(0, 1, 0, 1);
3775 }
3776 })";
3777
3778 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3779 drawQuad(program.get(), "inputAttribute", 0.5f);
3780 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3781}
3782
3783// Test vector/scalar arithmetic (in this case compound division and addition). Meant to reproduce a
3784// bug that appeared in NVIDIA OpenGL drivers and that is worked around by
3785// VectorizeVectorScalarArithmetic AST transform.
3786TEST_P(GLSLTest, VectorScalarDivideAndAddInLoop)
3787{
3788 const std::string &fragmentShader =
3789 R"(
3790
3791 precision mediump float;
3792
3793 void main() {
3794 gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
3795 for (int i = 0; i < 2; i++)
3796 {
3797 float x = gl_FragCoord.x;
3798 gl_FragColor = gl_FragColor + (x /= 2.0);
3799 }
3800 if (gl_FragColor.g == gl_FragColor.r &&
3801 gl_FragColor.b == gl_FragColor.r &&
3802 gl_FragColor.a == gl_FragColor.r)
3803 {
3804 gl_FragColor = vec4(0, 1, 0, 1);
3805 }
3806 })";
3807
3808 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3809 drawQuad(program.get(), "inputAttribute", 0.5f);
3810 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3811}
3812
Olli Etuahob8cb9392017-12-20 14:23:19 +02003813// Test that a varying with a flat qualifier that is used as an operand of a folded ternary operator
3814// is handled correctly.
3815TEST_P(GLSLTest_ES3, FlatVaryingUsedInFoldedTernary)
3816{
3817 const std::string &vertexShader =
3818 R"(#version 300 es
3819
3820 in vec4 inputAttribute;
3821
3822 flat out int v;
3823
3824 void main()
3825 {
3826 v = 1;
3827 gl_Position = inputAttribute;
3828 })";
3829
3830 const std::string &fragmentShader =
3831 R"(#version 300 es
3832
3833 precision highp float;
3834 out vec4 my_FragColor;
3835
3836 flat in int v;
3837
3838 void main()
3839 {
3840 my_FragColor = vec4(0, (true ? v : 0), 0, 1);
3841 })";
3842
3843 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3844 drawQuad(program.get(), "inputAttribute", 0.5f);
3845 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3846}
3847
Jiawei Shao02f15232017-12-27 10:10:28 +08003848// Verify that the link error message from last link failure is cleared when the new link is
3849// finished.
3850TEST_P(GLSLTest, ClearLinkErrorLog)
3851{
3852 const std::string &vertexShader =
3853 R"(
3854
3855 attribute vec4 vert_in;
3856 varying vec4 vert_out;
3857 void main()
3858 {
3859 gl_Position = vert_in;
3860 vert_out = vert_in;
3861 })";
3862
3863 const std::string &fragmentShader =
3864 R"(
3865
3866 precision mediump float;
3867 varying vec4 frag_in;
3868 void main()
3869 {
3870 gl_FragColor = frag_in;
3871 })";
3872
3873 GLuint vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
3874 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);
3875
3876 GLuint program = glCreateProgram();
3877
3878 // The first time the program link fails because of lack of fragment shader.
3879 glAttachShader(program, vs);
3880 glLinkProgram(program);
3881 GLint linkStatus = GL_TRUE;
3882 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
3883 ASSERT_FALSE(linkStatus);
3884
3885 const std::string &lackOfFragmentShader = QueryErrorMessage(program);
3886
3887 // The second time the program link fails because of the mismatch of the varying types.
3888 glAttachShader(program, fs);
3889 glLinkProgram(program);
3890 linkStatus = GL_TRUE;
3891 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
3892 ASSERT_FALSE(linkStatus);
3893
3894 const std::string &varyingTypeMismatch = QueryErrorMessage(program);
3895
3896 EXPECT_EQ(std::string::npos, varyingTypeMismatch.find(lackOfFragmentShader));
3897
3898 glDetachShader(program, vs);
3899 glDetachShader(program, fs);
3900 glDeleteShader(vs);
3901 glDeleteShader(fs);
3902 glDeleteProgram(program);
3903
3904 ASSERT_GL_NO_ERROR();
3905}
3906
Jiawei Shao881b7bf2017-12-25 11:18:37 +08003907// Validate error messages when the link mismatch occurs on the type of a non-struct varying.
3908TEST_P(GLSLTest, ErrorMessageOfVaryingMismatch)
3909{
3910 const std::string &vertexShader =
3911 R"(
3912
3913 attribute vec4 inputAttribute;
3914 varying vec4 vertex_out;
3915 void main()
3916 {
3917 vertex_out = inputAttribute;
3918 gl_Position = inputAttribute;
3919 })";
3920
3921 const std::string &fragmentShader =
3922 R"(
3923
3924 precision mediump float;
3925 varying float vertex_out;
3926 void main()
3927 {
3928 gl_FragColor = vec4(vertex_out, 0.0, 0.0, 1.0);
3929 })";
3930
3931 validateComponentsInErrorMessage(vertexShader, fragmentShader, "Types", "varying 'vertex_out'");
3932}
3933
3934// Validate error messages when the link mismatch occurs on the name of a varying field.
3935TEST_P(GLSLTest_ES3, ErrorMessageOfVaryingStructFieldNameMismatch)
3936{
3937 const std::string &vertexShader =
3938 R"(#version 300 es
3939
3940 in vec4 inputAttribute;
3941 struct S {
3942 float val1;
3943 vec4 val2;
3944 };
3945 out S vertex_out;
3946 void main()
3947 {
3948 vertex_out.val2 = inputAttribute;
3949 vertex_out.val1 = inputAttribute[0];
3950 gl_Position = inputAttribute;
3951 })";
3952
3953 const std::string &fragmentShader =
3954 R"(#version 300 es
3955
3956 precision mediump float;
3957 struct S {
3958 float val1;
3959 vec4 val3;
3960 };
3961 in S vertex_out;
3962 layout (location = 0) out vec4 frag_out;
3963 void main()
3964 {
3965 frag_out = vec4(vertex_out.val1, 0.0, 0.0, 1.0);
3966 })";
3967
3968 validateComponentsInErrorMessage(vertexShader, fragmentShader, "Field names",
3969 "varying 'vertex_out'");
3970}
3971
3972// Validate error messages when the link mismatch occurs on the type of a varying field.
3973TEST_P(GLSLTest_ES3, ErrorMessageOfVaryingStructFieldMismatch)
3974{
3975 const std::string &vertexShader =
3976 R"(#version 300 es
3977
3978 in vec4 inputAttribute;
3979 struct S {
3980 float val1;
3981 vec4 val2;
3982 };
3983 out S vertex_out;
3984 void main()
3985 {
3986 vertex_out.val2 = inputAttribute;
3987 vertex_out.val1 = inputAttribute[0];
3988 gl_Position = inputAttribute;
3989 })";
3990
3991 const std::string &fragmentShader =
3992 R"(#version 300 es
3993
3994 precision mediump float;
3995 struct S {
3996 float val1;
3997 vec2 val2;
3998 };
3999 in S vertex_out;
4000 layout (location = 0) out vec4 frag_out;
4001 void main()
4002 {
4003 frag_out = vec4(vertex_out.val1, 0.0, 0.0, 1.0);
4004 })";
4005
4006 validateComponentsInErrorMessage(vertexShader, fragmentShader, "Types",
4007 "varying 'vertex_out' member 'vertex_out.val2'");
4008}
4009
4010// Validate error messages when the link mismatch occurs on the name of a struct member of a uniform
4011// field.
4012TEST_P(GLSLTest, ErrorMessageOfLinkUniformStructFieldNameMismatch)
4013{
4014 const std::string &vertexShader =
4015 R"(
4016
4017 struct T
4018 {
4019 vec2 t1;
4020 vec3 t2;
4021 };
4022 struct S {
4023 T val1;
4024 vec4 val2;
4025 };
4026 uniform S uni;
4027
4028 attribute vec4 inputAttribute;
4029 varying vec4 vertex_out;
4030 void main()
4031 {
4032 vertex_out = uni.val2;
4033 gl_Position = inputAttribute;
4034 })";
4035
4036 const std::string &fragmentShader =
4037 R"(
4038
4039 precision highp float;
4040 struct T
4041 {
4042 vec2 t1;
4043 vec3 t3;
4044 };
4045 struct S {
4046 T val1;
4047 vec4 val2;
4048 };
4049 uniform S uni;
4050
4051 varying vec4 vertex_out;
4052 void main()
4053 {
4054 gl_FragColor = vec4(uni.val1.t1[0], 0.0, 0.0, 1.0);
4055 })";
4056
4057 validateComponentsInErrorMessage(vertexShader, fragmentShader, "Field names",
4058 "uniform 'uni' member 'uni.val1'");
4059}
4060
4061// Validate error messages when the link mismatch occurs on the type of a non-struct uniform block
4062// field.
4063TEST_P(GLSLTest_ES3, ErrorMessageOfLinkInterfaceBlockFieldMismatch)
4064{
4065 const std::string &vertexShader =
4066 R"(#version 300 es
4067
4068 uniform S {
4069 vec2 val1;
4070 vec4 val2;
4071 } uni;
4072
4073 in vec4 inputAttribute;
4074 out vec4 vertex_out;
4075 void main()
4076 {
4077 vertex_out = uni.val2;
4078 gl_Position = inputAttribute;
4079 })";
4080
4081 const std::string &fragmentShader =
4082 R"(#version 300 es
4083
4084 precision highp float;
4085 uniform S {
4086 vec2 val1;
4087 vec3 val2;
4088 } uni;
4089
4090 in vec4 vertex_out;
4091 layout (location = 0) out vec4 frag_out;
4092 void main()
4093 {
4094 frag_out = vec4(uni.val1[0], 0.0, 0.0, 1.0);
4095 })";
4096
4097 validateComponentsInErrorMessage(vertexShader, fragmentShader, "Types",
4098 "interface block 'S' member 'S.val2'");
4099}
4100
4101// Validate error messages when the link mismatch occurs on the type of a member of a uniform block
4102// struct field.
4103TEST_P(GLSLTest_ES3, ErrorMessageOfLinkInterfaceBlockStructFieldMismatch)
4104{
4105 const std::string &vertexShader =
4106 R"(#version 300 es
4107
4108 struct T
4109 {
4110 vec2 t1;
4111 vec3 t2;
4112 };
4113 uniform S {
4114 T val1;
4115 vec4 val2;
4116 } uni;
4117
4118 in vec4 inputAttribute;
4119 out vec4 vertex_out;
4120 void main()
4121 {
4122 vertex_out = uni.val2;
4123 gl_Position = inputAttribute;
4124 })";
4125
4126 const std::string &fragmentShader =
4127 R"(#version 300 es
4128
4129 precision highp float;
4130 struct T
4131 {
4132 vec2 t1;
4133 vec4 t2;
4134 };
4135 uniform S {
4136 T val1;
4137 vec4 val2;
4138 } uni;
4139
4140 in vec4 vertex_out;
4141 layout (location = 0) out vec4 frag_out;
4142 void main()
4143 {
4144 frag_out = vec4(uni.val1.t1[0], 0.0, 0.0, 1.0);
4145 })";
4146
4147 validateComponentsInErrorMessage(vertexShader, fragmentShader, "Types",
4148 "interface block 'S' member 'S.val1.t2'");
4149}
4150
Jamie Madillfa05f602015-05-07 13:47:11 -04004151// 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 -05004152ANGLE_INSTANTIATE_TEST(GLSLTest,
4153 ES2_D3D9(),
4154 ES2_D3D11(),
4155 ES2_D3D11_FL9_3(),
4156 ES2_OPENGL(),
4157 ES3_OPENGL(),
4158 ES2_OPENGLES(),
4159 ES3_OPENGLES());
Jamie Madillfa05f602015-05-07 13:47:11 -04004160
4161// 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 -05004162ANGLE_INSTANTIATE_TEST(GLSLTest_ES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
Jamie Madill192745a2016-12-22 15:58:21 -05004163
4164ANGLE_INSTANTIATE_TEST(WebGLGLSLTest, ES2_D3D11(), ES2_OPENGL(), ES2_OPENGLES());
Olli Etuaho9250cb22017-01-21 10:51:27 +00004165
4166ANGLE_INSTANTIATE_TEST(GLSLTest_ES31, ES31_D3D11(), ES31_OPENGL(), ES31_OPENGLES());