blob: f20c511f3f8d0054333570db166b943daffb6bab [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
Jamie Madill2bf8b372014-06-16 17:18:51 -0400452 std::string mSimpleVSSource;
Jamie Madill96509e42014-05-29 14:33:27 -0400453};
454
Jamie Madille1faacb2016-12-13 12:42:14 -0500455class GLSLTestNoValidation : public GLSLTest
456{
457 public:
458 GLSLTestNoValidation() { setNoErrorEnabled(true); }
459};
460
Jamie Madillfa05f602015-05-07 13:47:11 -0400461class GLSLTest_ES3 : public GLSLTest
Gregoire Payen de La Garanderieb3dced22015-01-12 14:54:55 +0000462{
Olli Etuahoe1d199b2016-07-19 17:14:27 +0300463 void SetUp() override
464 {
465 ANGLETest::SetUp();
466
467 mSimpleVSSource =
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300468 R"(#version 300 es
469 in vec4 inputAttribute;
470 void main()
471 {
472 gl_Position = inputAttribute;
473 })";
Olli Etuahoe1d199b2016-07-19 17:14:27 +0300474 }
Gregoire Payen de La Garanderieb3dced22015-01-12 14:54:55 +0000475};
476
Olli Etuaho9250cb22017-01-21 10:51:27 +0000477class GLSLTest_ES31 : public GLSLTest
478{
479 void SetUp() override
480 {
481 ANGLETest::SetUp();
482
483 mSimpleVSSource =
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300484 R"(#version 310 es
485 in vec4 inputAttribute;
486 void main()
487 {
488 gl_Position = inputAttribute;
489 })";
Olli Etuaho9250cb22017-01-21 10:51:27 +0000490 }
491};
492
Jamie Madillfa05f602015-05-07 13:47:11 -0400493TEST_P(GLSLTest, NamelessScopedStructs)
Jamie Madill96509e42014-05-29 14:33:27 -0400494{
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300495 const std::string fragmentShaderSource =
496 R"(precision mediump float;
Jamie Madill96509e42014-05-29 14:33:27 -0400497 void main()
498 {
Jamie Madillbfa91f42014-06-05 15:45:18 -0400499 struct
500 {
501 float q;
502 } b;
503
504 gl_FragColor = vec4(1, 0, 0, 1);
505 gl_FragColor.a += b.q;
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300506 })";
Jamie Madill96509e42014-05-29 14:33:27 -0400507
Jamie Madill5599c8f2014-08-26 13:16:39 -0400508 GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
Jamie Madillbfa91f42014-06-05 15:45:18 -0400509 EXPECT_NE(0u, program);
510}
Austin Kinross18b931d2014-09-29 12:58:31 -0700511
Jamie Madillfa05f602015-05-07 13:47:11 -0400512TEST_P(GLSLTest, ScopedStructsOrderBug)
Jamie Madillbfa91f42014-06-05 15:45:18 -0400513{
Geoff Lange0cc2a42016-01-20 10:58:17 -0500514 // TODO(geofflang): Find out why this doesn't compile on Apple OpenGL drivers
515 // (http://anglebug.com/1292)
Geoff Lang5103f4c2016-01-26 11:40:18 -0500516 // TODO(geofflang): Find out why this doesn't compile on AMD OpenGL drivers
Geoff Lange0cc2a42016-01-20 10:58:17 -0500517 // (http://anglebug.com/1291)
Corentin Wallezc7f59d02016-06-20 10:12:08 -0400518 if (IsDesktopOpenGL() && (IsOSX() || !IsNVIDIA()))
Geoff Lange0cc2a42016-01-20 10:58:17 -0500519 {
Jamie Madill518b9fa2016-03-02 11:26:02 -0500520 std::cout << "Test disabled on this OpenGL configuration." << std::endl;
Geoff Lange0cc2a42016-01-20 10:58:17 -0500521 return;
522 }
Geoff Lange0cc2a42016-01-20 10:58:17 -0500523
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300524 const std::string fragmentShaderSource =
525 R"(precision mediump float;
Jamie Madillbfa91f42014-06-05 15:45:18 -0400526
527 struct T
528 {
529 float f;
530 };
531
532 void main()
533 {
534 T a;
535
536 struct T
537 {
538 float q;
539 };
540
541 T b;
542
543 gl_FragColor = vec4(1, 0, 0, 1);
544 gl_FragColor.a += a.f;
545 gl_FragColor.a += b.q;
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300546 })";
Jamie Madillbfa91f42014-06-05 15:45:18 -0400547
Jamie Madill5599c8f2014-08-26 13:16:39 -0400548 GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
Jamie Madillbfa91f42014-06-05 15:45:18 -0400549 EXPECT_NE(0u, program);
550}
551
Jamie Madillfa05f602015-05-07 13:47:11 -0400552TEST_P(GLSLTest, ScopedStructsBug)
Jamie Madillbfa91f42014-06-05 15:45:18 -0400553{
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300554 const std::string fragmentShaderSource =
555 R"(precision mediump float;
Jamie Madill96509e42014-05-29 14:33:27 -0400556
557 struct T_0
558 {
559 float f;
560 };
561
562 void main()
563 {
564 gl_FragColor = vec4(1, 0, 0, 1);
565
566 struct T
567 {
568 vec2 v;
569 };
570
571 T_0 a;
572 T b;
573
574 gl_FragColor.a += a.f;
575 gl_FragColor.a += b.v.x;
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300576 })";
Jamie Madill96509e42014-05-29 14:33:27 -0400577
Jamie Madill5599c8f2014-08-26 13:16:39 -0400578 GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
Jamie Madill2bf8b372014-06-16 17:18:51 -0400579 EXPECT_NE(0u, program);
580}
581
Jamie Madillfa05f602015-05-07 13:47:11 -0400582TEST_P(GLSLTest, DxPositionBug)
Jamie Madill2bf8b372014-06-16 17:18:51 -0400583{
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300584 const std::string &vertexShaderSource =
585 R"(attribute vec4 inputAttribute;
Jamie Madill2bf8b372014-06-16 17:18:51 -0400586 varying float dx_Position;
587 void main()
588 {
589 gl_Position = vec4(inputAttribute);
590 dx_Position = 0.0;
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300591 })";
Jamie Madill2bf8b372014-06-16 17:18:51 -0400592
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300593 const std::string &fragmentShaderSource =
594 R"(precision mediump float;
Jamie Madill2bf8b372014-06-16 17:18:51 -0400595
596 varying float dx_Position;
597
598 void main()
599 {
600 gl_FragColor = vec4(dx_Position, 0, 0, 1);
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300601 })";
Jamie Madill2bf8b372014-06-16 17:18:51 -0400602
Jamie Madill5599c8f2014-08-26 13:16:39 -0400603 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
Jamie Madill96509e42014-05-29 14:33:27 -0400604 EXPECT_NE(0u, program);
605}
Jamie Madill4836d222014-07-24 06:55:51 -0400606
Jamie Madillfa05f602015-05-07 13:47:11 -0400607TEST_P(GLSLTest, ElseIfRewriting)
Jamie Madill4836d222014-07-24 06:55:51 -0400608{
609 const std::string &vertexShaderSource =
610 "attribute vec4 a_position;\n"
611 "varying float v;\n"
612 "void main() {\n"
613 " gl_Position = a_position;\n"
614 " v = 1.0;\n"
615 " if (a_position.x <= 0.5) {\n"
616 " v = 0.0;\n"
617 " } else if (a_position.x >= 0.5) {\n"
618 " v = 2.0;\n"
619 " }\n"
620 "}\n";
621
622 const std::string &fragmentShaderSource =
623 "precision highp float;\n"
624 "varying float v;\n"
625 "void main() {\n"
626 " vec4 color = vec4(1.0, 0.0, 0.0, 1.0);\n"
627 " if (v >= 1.0) color = vec4(0.0, 1.0, 0.0, 1.0);\n"
628 " if (v >= 2.0) color = vec4(0.0, 0.0, 1.0, 1.0);\n"
629 " gl_FragColor = color;\n"
630 "}\n";
631
Jamie Madill5599c8f2014-08-26 13:16:39 -0400632 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
Jamie Madill4836d222014-07-24 06:55:51 -0400633 ASSERT_NE(0u, program);
634
635 drawQuad(program, "a_position", 0.5f);
Jamie Madill4836d222014-07-24 06:55:51 -0400636
637 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
638 EXPECT_PIXEL_EQ(getWindowWidth()-1, 0, 0, 255, 0, 255);
639}
640
Jamie Madillfa05f602015-05-07 13:47:11 -0400641TEST_P(GLSLTest, TwoElseIfRewriting)
Jamie Madill4836d222014-07-24 06:55:51 -0400642{
643 const std::string &vertexShaderSource =
644 "attribute vec4 a_position;\n"
645 "varying float v;\n"
646 "void main() {\n"
647 " gl_Position = a_position;\n"
Jamie Madill778d5272014-08-04 13:13:25 -0400648 " if (a_position.x == 0.0) {\n"
Jamie Madill4836d222014-07-24 06:55:51 -0400649 " v = 1.0;\n"
650 " } else if (a_position.x > 0.5) {\n"
651 " v = 0.0;\n"
652 " } else if (a_position.x > 0.75) {\n"
653 " v = 0.5;\n"
654 " }\n"
655 "}\n";
656
657 const std::string &fragmentShaderSource =
658 "precision highp float;\n"
659 "varying float v;\n"
660 "void main() {\n"
661 " gl_FragColor = vec4(v, 0.0, 0.0, 1.0);\n"
662 "}\n";
663
Jamie Madill5599c8f2014-08-26 13:16:39 -0400664 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
Jamie Madill4836d222014-07-24 06:55:51 -0400665 EXPECT_NE(0u, program);
666}
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400667
Jamie Madillfa05f602015-05-07 13:47:11 -0400668TEST_P(GLSLTest, FrontFacingAndVarying)
Jamie Madille6256f82014-09-17 10:31:15 -0400669{
Geoff Langdd323e92015-06-09 15:16:31 -0400670 EGLPlatformParameters platform = GetParam().eglParameters;
Austin Kinross8b695ee2015-03-12 13:12:20 -0700671
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300672 const std::string vertexShaderSource =
673 R"(attribute vec4 a_position;
Jamie Madille6256f82014-09-17 10:31:15 -0400674 varying float v_varying;
675 void main()
676 {
677 v_varying = a_position.x;
678 gl_Position = a_position;
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300679 })";
Jamie Madille6256f82014-09-17 10:31:15 -0400680
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300681 const std::string fragmentShaderSource =
682 R"(precision mediump float;
Jamie Madille6256f82014-09-17 10:31:15 -0400683 varying float v_varying;
684 void main()
685 {
686 vec4 c;
687
688 if (gl_FrontFacing)
689 {
690 c = vec4(v_varying, 0, 0, 1.0);
691 }
692 else
693 {
694 c = vec4(0, v_varying, 0, 1.0);
695 }
696 gl_FragColor = c;
Olli Etuahoa20af6d2017-09-18 13:32:29 +0300697 })";
Jamie Madille6256f82014-09-17 10:31:15 -0400698
699 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
Austin Kinross02df7962015-07-01 10:03:42 -0700700
701 // Compilation should fail on D3D11 feature level 9_3, since gl_FrontFacing isn't supported.
702 if (platform.renderer == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
703 {
704 if (platform.majorVersion == 9 && platform.minorVersion == 3)
705 {
706 EXPECT_EQ(0u, program);
707 return;
708 }
709 }
710
711 // Otherwise, compilation should succeed
Jamie Madille6256f82014-09-17 10:31:15 -0400712 EXPECT_NE(0u, program);
713}
714
Jamie Madill2f348d22017-06-05 10:50:59 -0400715// Test that we can release the shader compiler and still compile things properly.
716TEST_P(GLSLTest, ReleaseCompilerThenCompile)
717{
718 const std::string &simpleVS =
719 "attribute vec4 position; void main() { gl_Position = position; }";
720 const std::string &simpleFS = "void main() { gl_FragColor = vec4(1, 0, 0, 1); }";
721
722 // Draw with the first program.
723 ANGLE_GL_PROGRAM(program1, simpleVS, simpleFS);
724 drawQuad(program1, "position", 0.5f);
725 ASSERT_GL_NO_ERROR();
726 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
727
728 // Clear and release shader compiler.
729 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
730 glClear(GL_COLOR_BUFFER_BIT);
731 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
732 glReleaseShaderCompiler();
733 ASSERT_GL_NO_ERROR();
734
735 // Draw with a second program.
736 ANGLE_GL_PROGRAM(program2, simpleVS, simpleFS);
737 drawQuad(program2, "position", 0.5f);
738 ASSERT_GL_NO_ERROR();
739 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
740}
741
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400742// Verify that linking shaders declaring different shading language versions fails.
743TEST_P(GLSLTest_ES3, VersionMismatch)
744{
745 const std::string fragmentShaderSource100 =
746 "precision mediump float;\n"
747 "varying float v_varying;\n"
748 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
749
750 const std::string vertexShaderSource100 =
751 "attribute vec4 a_position;\n"
752 "varying float v_varying;\n"
753 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
754
755 const std::string fragmentShaderSource300 =
756 "#version 300 es\n"
757 "precision mediump float;\n"
758 "in float v_varying;\n"
759 "out vec4 my_FragColor;\n"
760 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
761
762 const std::string vertexShaderSource300 =
763 "#version 300 es\n"
764 "in vec4 a_position;\n"
765 "out float v_varying;\n"
766 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
767
768 GLuint program = CompileProgram(vertexShaderSource300, fragmentShaderSource100);
769 EXPECT_EQ(0u, program);
770
771 program = CompileProgram(vertexShaderSource100, fragmentShaderSource300);
772 EXPECT_EQ(0u, program);
773}
774
775// Verify that declaring varying as invariant only in vertex shader fails in ESSL 1.00.
776TEST_P(GLSLTest, InvariantVaryingOut)
777{
778 const std::string fragmentShaderSource =
779 "precision mediump float;\n"
780 "varying float v_varying;\n"
781 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
782
783 const std::string vertexShaderSource =
784 "attribute vec4 a_position;\n"
785 "invariant varying float v_varying;\n"
786 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
787
788 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
789 EXPECT_EQ(0u, program);
790}
791
792// Verify that declaring varying as invariant only in vertex shader succeeds in ESSL 3.00.
793TEST_P(GLSLTest_ES3, InvariantVaryingOut)
794{
795 // TODO: ESSL 3.00 -> GLSL 1.20 translation should add "invariant" in fragment shader
796 // for varyings which are invariant in vertex shader (http://anglebug.com/1293)
Corentin Wallezc7f59d02016-06-20 10:12:08 -0400797 if (IsDesktopOpenGL())
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400798 {
799 std::cout << "Test disabled on OpenGL." << std::endl;
800 return;
801 }
802
803 const std::string fragmentShaderSource =
804 "#version 300 es\n"
805 "precision mediump float;\n"
806 "in float v_varying;\n"
807 "out vec4 my_FragColor;\n"
808 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
809
810 const std::string vertexShaderSource =
811 "#version 300 es\n"
812 "in vec4 a_position;\n"
813 "invariant out float v_varying;\n"
814 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
815
816 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
817 EXPECT_NE(0u, program);
818}
819
820// Verify that declaring varying as invariant only in fragment shader fails in ESSL 1.00.
Jamie Madillfa05f602015-05-07 13:47:11 -0400821TEST_P(GLSLTest, InvariantVaryingIn)
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400822{
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400823 const std::string fragmentShaderSource =
824 "precision mediump float;\n"
825 "invariant varying float v_varying;\n"
826 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
Geoff Lange0cc2a42016-01-20 10:58:17 -0500827
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400828 const std::string vertexShaderSource =
829 "attribute vec4 a_position;\n"
830 "varying float v_varying;\n"
831 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400832
Jamie Madill5599c8f2014-08-26 13:16:39 -0400833 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400834 EXPECT_EQ(0u, program);
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400835}
836
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400837// Verify that declaring varying as invariant only in fragment shader fails in ESSL 3.00.
838TEST_P(GLSLTest_ES3, InvariantVaryingIn)
839{
840 const std::string fragmentShaderSource =
841 "#version 300 es\n"
842 "precision mediump float;\n"
843 "invariant in float v_varying;\n"
844 "out vec4 my_FragColor;\n"
845 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
846
847 const std::string vertexShaderSource =
848 "#version 300 es\n"
849 "in vec4 a_position;\n"
850 "out float v_varying;\n"
851 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
852
853 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
854 EXPECT_EQ(0u, program);
855}
856
857// Verify that declaring varying as invariant in both shaders succeeds in ESSL 1.00.
Jamie Madillfa05f602015-05-07 13:47:11 -0400858TEST_P(GLSLTest, InvariantVaryingBoth)
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400859{
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400860 const std::string fragmentShaderSource =
861 "precision mediump float;\n"
862 "invariant varying float v_varying;\n"
863 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400864
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400865 const std::string vertexShaderSource =
866 "attribute vec4 a_position;\n"
867 "invariant varying float v_varying;\n"
868 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400869
Jamie Madill5599c8f2014-08-26 13:16:39 -0400870 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400871 EXPECT_NE(0u, program);
872}
873
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400874// Verify that declaring varying as invariant in both shaders fails in ESSL 3.00.
875TEST_P(GLSLTest_ES3, InvariantVaryingBoth)
876{
877 const std::string fragmentShaderSource =
878 "#version 300 es\n"
879 "precision mediump float;\n"
880 "invariant in float v_varying;\n"
881 "out vec4 my_FragColor;\n"
882 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
883
884 const std::string vertexShaderSource =
885 "#version 300 es\n"
886 "in vec4 a_position;\n"
887 "invariant out float v_varying;\n"
888 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
889
890 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
891 EXPECT_EQ(0u, program);
892}
893
894// Verify that declaring gl_Position as invariant succeeds in ESSL 1.00.
Jamie Madillfa05f602015-05-07 13:47:11 -0400895TEST_P(GLSLTest, InvariantGLPosition)
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400896{
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400897 const std::string fragmentShaderSource =
898 "precision mediump float;\n"
899 "varying float v_varying;\n"
900 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400901
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400902 const std::string vertexShaderSource =
903 "attribute vec4 a_position;\n"
904 "invariant gl_Position;\n"
905 "varying float v_varying;\n"
906 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400907
Jamie Madill5599c8f2014-08-26 13:16:39 -0400908 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400909 EXPECT_NE(0u, program);
910}
911
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400912// Verify that declaring gl_Position as invariant succeeds in ESSL 3.00.
913TEST_P(GLSLTest_ES3, InvariantGLPosition)
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400914{
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400915 const std::string fragmentShaderSource =
916 "#version 300 es\n"
917 "precision mediump float;\n"
918 "in float v_varying;\n"
919 "out vec4 my_FragColor;\n"
920 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
921
922 const std::string vertexShaderSource =
923 "#version 300 es\n"
924 "in vec4 a_position;\n"
925 "invariant gl_Position;\n"
926 "out float v_varying;\n"
927 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
928
929 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
930 EXPECT_NE(0u, program);
931}
932
933// Verify that using invariant(all) in both shaders succeeds in ESSL 1.00.
934TEST_P(GLSLTest, InvariantAllBoth)
935{
936 // TODO: ESSL 1.00 -> GLSL 1.20 translation should add "invariant" in fragment shader
937 // for varyings which are invariant in vertex shader individually,
938 // and remove invariant(all) from fragment shader (http://anglebug.com/1293)
Corentin Wallezc7f59d02016-06-20 10:12:08 -0400939 if (IsDesktopOpenGL())
Geoff Lange0cc2a42016-01-20 10:58:17 -0500940 {
941 std::cout << "Test disabled on OpenGL." << std::endl;
942 return;
943 }
944
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400945 const std::string fragmentShaderSource =
946 "#pragma STDGL invariant(all)\n"
947 "precision mediump float;\n"
948 "varying float v_varying;\n"
949 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400950
951 const std::string vertexShaderSource =
952 "#pragma STDGL invariant(all)\n"
953 "attribute vec4 a_position;\n"
954 "varying float v_varying;\n"
955 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
956
Jamie Madill5599c8f2014-08-26 13:16:39 -0400957 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400958 EXPECT_NE(0u, program);
959}
Austin Kinrossaf875522014-08-25 21:06:07 -0700960
Geoff Lang156d7192016-07-21 16:11:00 -0400961// Verify that functions without return statements still compile
962TEST_P(GLSLTest, MissingReturnFloat)
963{
964 const std::string vertexShaderSource =
965 "varying float v_varying;\n"
966 "float f() { if (v_varying > 0.0) return 1.0; }\n"
967 "void main() { gl_Position = vec4(f(), 0, 0, 1); }\n";
968
969 const std::string fragmentShaderSource =
970 "precision mediump float;\n"
971 "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
972
973 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
974 EXPECT_NE(0u, program);
975}
976
977// Verify that functions without return statements still compile
978TEST_P(GLSLTest, MissingReturnVec2)
979{
980 const std::string vertexShaderSource =
981 "varying float v_varying;\n"
982 "vec2 f() { if (v_varying > 0.0) return vec2(1.0, 1.0); }\n"
983 "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
984
985 const std::string fragmentShaderSource =
986 "precision mediump float;\n"
987 "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
988
989 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
990 EXPECT_NE(0u, program);
991}
992
993// Verify that functions without return statements still compile
994TEST_P(GLSLTest, MissingReturnVec3)
995{
996 const std::string vertexShaderSource =
997 "varying float v_varying;\n"
998 "vec3 f() { if (v_varying > 0.0) return vec3(1.0, 1.0, 1.0); }\n"
999 "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
1000
1001 const std::string fragmentShaderSource =
1002 "precision mediump float;\n"
1003 "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
1004
1005 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1006 EXPECT_NE(0u, program);
1007}
1008
1009// Verify that functions without return statements still compile
1010TEST_P(GLSLTest, MissingReturnVec4)
1011{
1012 const std::string vertexShaderSource =
1013 "varying float v_varying;\n"
1014 "vec4 f() { if (v_varying > 0.0) return vec4(1.0, 1.0, 1.0, 1.0); }\n"
1015 "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
1016
1017 const std::string fragmentShaderSource =
1018 "precision mediump float;\n"
1019 "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
1020
1021 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1022 EXPECT_NE(0u, program);
1023}
1024
1025// Verify that functions without return statements still compile
1026TEST_P(GLSLTest, MissingReturnIVec4)
1027{
1028 const std::string vertexShaderSource =
1029 "varying float v_varying;\n"
1030 "ivec4 f() { if (v_varying > 0.0) return ivec4(1, 1, 1, 1); }\n"
1031 "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
1032
1033 const std::string fragmentShaderSource =
1034 "precision mediump float;\n"
1035 "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
1036
1037 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1038 EXPECT_NE(0u, program);
1039}
1040
1041// Verify that functions without return statements still compile
1042TEST_P(GLSLTest, MissingReturnMat4)
1043{
1044 const std::string vertexShaderSource =
1045 "varying float v_varying;\n"
1046 "mat4 f() { if (v_varying > 0.0) return mat4(1.0); }\n"
1047 "void main() { gl_Position = vec4(f()[0][0], 0, 0, 1); }\n";
1048
1049 const std::string fragmentShaderSource =
1050 "precision mediump float;\n"
1051 "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
1052
1053 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1054 EXPECT_NE(0u, program);
1055}
1056
1057// Verify that functions without return statements still compile
1058TEST_P(GLSLTest, MissingReturnStruct)
1059{
1060 const std::string vertexShaderSource =
1061 "varying float v_varying;\n"
1062 "struct s { float a; int b; vec2 c; };\n"
1063 "s f() { if (v_varying > 0.0) return s(1.0, 1, vec2(1.0, 1.0)); }\n"
1064 "void main() { gl_Position = vec4(f().a, 0, 0, 1); }\n";
1065
1066 const std::string fragmentShaderSource =
1067 "precision mediump float;\n"
1068 "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
1069
1070 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1071 EXPECT_NE(0u, program);
1072}
1073
1074// Verify that functions without return statements still compile
1075TEST_P(GLSLTest_ES3, MissingReturnArray)
1076{
1077 const std::string vertexShaderSource =
1078 "#version 300 es\n"
1079 "in float v_varying;\n"
1080 "vec2[2] f() { if (v_varying > 0.0) { return vec2[2](vec2(1.0, 1.0), vec2(1.0, 1.0)); } }\n"
1081 "void main() { gl_Position = vec4(f()[0].x, 0, 0, 1); }\n";
1082
1083 const std::string fragmentShaderSource =
1084 "#version 300 es\n"
1085 "precision mediump float;\n"
1086 "out vec4 my_FragColor;\n"
1087 "void main() { my_FragColor = vec4(0, 0, 0, 1); }\n";
1088
1089 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1090 EXPECT_NE(0u, program);
1091}
1092
1093// Verify that functions without return statements still compile
1094TEST_P(GLSLTest_ES3, MissingReturnArrayOfStructs)
1095{
1096 const std::string vertexShaderSource =
1097 "#version 300 es\n"
1098 "in float v_varying;\n"
1099 "struct s { float a; int b; vec2 c; };\n"
1100 "s[2] f() { if (v_varying > 0.0) { return s[2](s(1.0, 1, vec2(1.0, 1.0)), s(1.0, 1, "
1101 "vec2(1.0, 1.0))); } }\n"
1102 "void main() { gl_Position = vec4(f()[0].a, 0, 0, 1); }\n";
1103
1104 const std::string fragmentShaderSource =
1105 "#version 300 es\n"
1106 "precision mediump float;\n"
1107 "out vec4 my_FragColor;\n"
1108 "void main() { my_FragColor = vec4(0, 0, 0, 1); }\n";
1109
1110 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1111 EXPECT_NE(0u, program);
1112}
1113
Corentin Wallez509e4562016-08-25 14:55:44 -04001114// Verify that functions without return statements still compile
1115TEST_P(GLSLTest_ES3, MissingReturnStructOfArrays)
1116{
Olli Etuahodf7d13e2017-05-30 13:53:45 +03001117 // TODO(cwallez) remove the suppression once NVIDIA drivers are updated across trybots, drivers
1118 // since late 2016 should have the fix. Last check on 2017-05-30 revealed that the Windows
1119 // Server 2008 bots still had the old, failing drivers.
Corentin Wallez509e4562016-08-25 14:55:44 -04001120 if (IsNVIDIA() && IsOpenGLES())
1121 {
1122 std::cout << "Test skipped on NVIDIA OpenGL ES because it disallows returning "
1123 "structure of arrays"
1124 << std::endl;
1125 return;
1126 }
1127
1128 const std::string vertexShaderSource =
1129 "#version 300 es\n"
1130 "in float v_varying;\n"
1131 "struct s { float a[2]; int b[2]; vec2 c[2]; };\n"
1132 "s f() { if (v_varying > 0.0) { return s(float[2](1.0, 1.0), int[2](1, 1),"
1133 "vec2[2](vec2(1.0, 1.0), vec2(1.0, 1.0))); } }\n"
1134 "void main() { gl_Position = vec4(f().a[0], 0, 0, 1); }\n";
1135
1136 const std::string fragmentShaderSource =
1137 "#version 300 es\n"
1138 "precision mediump float;\n"
1139 "out vec4 my_FragColor;\n"
1140 "void main() { my_FragColor = vec4(0, 0, 0, 1); }\n";
1141
1142 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1143 EXPECT_NE(0u, program);
1144}
1145
Yuly Novikova1f6dc92016-06-15 23:27:04 -04001146// Verify that using invariant(all) in both shaders fails in ESSL 3.00.
1147TEST_P(GLSLTest_ES3, InvariantAllBoth)
1148{
1149 const std::string fragmentShaderSource =
1150 "#version 300 es\n"
1151 "#pragma STDGL invariant(all)\n"
1152 "precision mediump float;\n"
1153 "in float v_varying;\n"
1154 "out vec4 my_FragColor;\n"
1155 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1156
1157 const std::string vertexShaderSource =
1158 "#version 300 es\n"
1159 "#pragma STDGL invariant(all)\n"
1160 "in vec4 a_position;\n"
1161 "out float v_varying;\n"
1162 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1163
1164 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1165 EXPECT_EQ(0u, program);
1166}
1167
1168// Verify that using invariant(all) only in fragment shader fails in ESSL 1.00.
1169TEST_P(GLSLTest, InvariantAllIn)
1170{
1171 const std::string fragmentShaderSource =
1172 "#pragma STDGL invariant(all)\n"
1173 "precision mediump float;\n"
1174 "varying float v_varying;\n"
1175 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1176
1177 const std::string vertexShaderSource =
1178 "attribute vec4 a_position;\n"
1179 "varying float v_varying;\n"
1180 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1181
1182 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1183 EXPECT_EQ(0u, program);
1184}
1185
1186// Verify that using invariant(all) only in fragment shader fails in ESSL 3.00.
1187TEST_P(GLSLTest_ES3, InvariantAllIn)
1188{
1189 const std::string fragmentShaderSource =
1190 "#version 300 es\n"
1191 "#pragma STDGL invariant(all)\n"
1192 "precision mediump float;\n"
1193 "in float v_varying;\n"
1194 "out vec4 my_FragColor;\n"
1195 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1196
1197 const std::string vertexShaderSource =
1198 "#version 300 es\n"
1199 "in vec4 a_position;\n"
1200 "out float v_varying;\n"
1201 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1202
1203 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1204 EXPECT_EQ(0u, program);
1205}
1206
1207// Verify that using invariant(all) only in vertex shader fails in ESSL 1.00.
1208TEST_P(GLSLTest, InvariantAllOut)
1209{
1210 const std::string fragmentShaderSource =
1211 "precision mediump float;\n"
1212 "varying float v_varying;\n"
1213 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1214
1215 const std::string vertexShaderSource =
1216 "#pragma STDGL invariant(all)\n"
1217 "attribute vec4 a_position;\n"
1218 "varying float v_varying;\n"
1219 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1220
1221 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1222 EXPECT_EQ(0u, program);
1223}
1224
1225// Verify that using invariant(all) only in vertex shader succeeds in ESSL 3.00.
1226TEST_P(GLSLTest_ES3, InvariantAllOut)
1227{
1228 // TODO: ESSL 3.00 -> GLSL 1.20 translation should add "invariant" in fragment shader
1229 // for varyings which are invariant in vertex shader,
1230 // because of invariant(all) being used in vertex shader (http://anglebug.com/1293)
Corentin Wallezc7f59d02016-06-20 10:12:08 -04001231 if (IsDesktopOpenGL())
Yuly Novikova1f6dc92016-06-15 23:27:04 -04001232 {
1233 std::cout << "Test disabled on OpenGL." << std::endl;
1234 return;
1235 }
1236
1237 const std::string fragmentShaderSource =
1238 "#version 300 es\n"
1239 "precision mediump float;\n"
1240 "in float v_varying;\n"
1241 "out vec4 my_FragColor;\n"
1242 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1243
1244 const std::string vertexShaderSource =
1245 "#version 300 es\n"
1246 "#pragma STDGL invariant(all)\n"
1247 "in vec4 a_position;\n"
1248 "out float v_varying;\n"
1249 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1250
1251 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1252 EXPECT_NE(0u, program);
1253}
1254
Jamie Madillfa05f602015-05-07 13:47:11 -04001255TEST_P(GLSLTest, MaxVaryingVec4)
Austin Kinross8b695ee2015-03-12 13:12:20 -07001256{
Geoff Lang69accbd2016-01-25 16:22:32 -05001257#if defined(__APPLE__)
1258 // TODO(geofflang): Find out why this doesn't compile on Apple AND OpenGL drivers
1259 // (http://anglebug.com/1291)
Jamie Madill518b9fa2016-03-02 11:26:02 -05001260 if (IsAMD() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
Geoff Lang69accbd2016-01-25 16:22:32 -05001261 {
1262 std::cout << "Test disabled on Apple AMD OpenGL." << std::endl;
1263 return;
1264 }
1265#endif
1266
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 Madillfa05f602015-05-07 13:47:11 -04001273TEST_P(GLSLTest, MaxMinusTwoVaryingVec4PlusTwoSpecialVariables)
Austin Kinross8b695ee2015-03-12 13:12:20 -07001274{
1275 GLint maxVaryings = 0;
1276 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1277
1278 // Generate shader code that uses gl_FragCoord and gl_PointCoord, two special fragment shader variables.
1279 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 2, 0, true, true, false, true);
1280}
1281
Jamie Madillfa05f602015-05-07 13:47:11 -04001282TEST_P(GLSLTest, MaxMinusTwoVaryingVec4PlusThreeSpecialVariables)
Austin Kinross8b695ee2015-03-12 13:12:20 -07001283{
Geoff Lange0cc2a42016-01-20 10:58:17 -05001284 // TODO(geofflang): Figure out why this fails on OpenGL AMD (http://anglebug.com/1291)
Jamie Madill518b9fa2016-03-02 11:26:02 -05001285 if (IsAMD() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
Geoff Lange0cc2a42016-01-20 10:58:17 -05001286 {
1287 std::cout << "Test disabled on OpenGL." << std::endl;
1288 return;
1289 }
1290
Austin Kinross8b695ee2015-03-12 13:12:20 -07001291 GLint maxVaryings = 0;
1292 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1293
1294 // Generate shader code that uses gl_FragCoord, gl_PointCoord and gl_PointSize.
1295 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 2, 0, true, true, true, true);
1296}
1297
Jamie Madillfa05f602015-05-07 13:47:11 -04001298TEST_P(GLSLTest, MaxVaryingVec3)
Austin Kinrossaf875522014-08-25 21:06:07 -07001299{
1300 GLint maxVaryings = 0;
1301 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1302
Austin Kinross8b695ee2015-03-12 13:12:20 -07001303 VaryingTestBase(0, 0, 0, 0, maxVaryings, 0, 0, 0, false, false, false, true);
Austin Kinrossaf875522014-08-25 21:06:07 -07001304}
1305
Jamie Madillfa05f602015-05-07 13:47:11 -04001306TEST_P(GLSLTest, MaxVaryingVec3Array)
Austin Kinrossaf875522014-08-25 21:06:07 -07001307{
1308 GLint maxVaryings = 0;
1309 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1310
Austin Kinross8b695ee2015-03-12 13:12:20 -07001311 VaryingTestBase(0, 0, 0, 0, 0, maxVaryings / 2, 0, 0, false, false, false, true);
Austin Kinrossaf875522014-08-25 21:06:07 -07001312}
1313
Jamie Madillbee59e02014-10-02 10:44:18 -04001314// Disabled because of a failure in D3D9
Jamie Madill9fc36822015-11-18 13:08:07 -05001315TEST_P(GLSLTest, MaxVaryingVec3AndOneFloat)
Austin Kinrossaf875522014-08-25 21:06:07 -07001316{
Jamie Madill518b9fa2016-03-02 11:26:02 -05001317 if (IsD3D9())
Jamie Madill9fc36822015-11-18 13:08:07 -05001318 {
1319 std::cout << "Test disabled on D3D9." << std::endl;
1320 return;
1321 }
1322
Austin Kinrossaf875522014-08-25 21:06:07 -07001323 GLint maxVaryings = 0;
1324 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1325
Austin Kinross8b695ee2015-03-12 13:12:20 -07001326 VaryingTestBase(1, 0, 0, 0, maxVaryings, 0, 0, 0, false, false, false, true);
Austin Kinrossaf875522014-08-25 21:06:07 -07001327}
1328
Jamie Madillbee59e02014-10-02 10:44:18 -04001329// Disabled because of a failure in D3D9
Jamie Madill9fc36822015-11-18 13:08:07 -05001330TEST_P(GLSLTest, MaxVaryingVec3ArrayAndOneFloatArray)
Austin Kinrossaf875522014-08-25 21:06:07 -07001331{
Jamie Madill518b9fa2016-03-02 11:26:02 -05001332 if (IsD3D9())
Jamie Madill9fc36822015-11-18 13:08:07 -05001333 {
1334 std::cout << "Test disabled on D3D9." << std::endl;
1335 return;
1336 }
1337
Austin Kinrossaf875522014-08-25 21:06:07 -07001338 GLint maxVaryings = 0;
1339 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1340
Austin Kinross8b695ee2015-03-12 13:12:20 -07001341 VaryingTestBase(0, 1, 0, 0, 0, maxVaryings / 2, 0, 0, false, false, false, true);
Austin Kinrossaf875522014-08-25 21:06:07 -07001342}
1343
Jamie Madillbee59e02014-10-02 10:44:18 -04001344// Disabled because of a failure in D3D9
Jamie Madill9fc36822015-11-18 13:08:07 -05001345TEST_P(GLSLTest, TwiceMaxVaryingVec2)
Austin Kinrossaf875522014-08-25 21:06:07 -07001346{
Jamie Madill518b9fa2016-03-02 11:26:02 -05001347 if (IsD3D9())
Jamie Madill9fc36822015-11-18 13:08:07 -05001348 {
1349 std::cout << "Test disabled on D3D9." << std::endl;
1350 return;
1351 }
1352
Geoff Lange0cc2a42016-01-20 10:58:17 -05001353 if (getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
1354 {
1355 // TODO(geofflang): Figure out why this fails on NVIDIA's GLES driver
1356 std::cout << "Test disabled on OpenGL ES." << std::endl;
1357 return;
1358 }
1359
Geoff Lang69accbd2016-01-25 16:22:32 -05001360#if defined(__APPLE__)
1361 // TODO(geofflang): Find out why this doesn't compile on Apple AND OpenGL drivers
1362 // (http://anglebug.com/1291)
Jamie Madill518b9fa2016-03-02 11:26:02 -05001363 if (IsAMD() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
Geoff Lang69accbd2016-01-25 16:22:32 -05001364 {
1365 std::cout << "Test disabled on Apple AMD OpenGL." << std::endl;
1366 return;
1367 }
1368#endif
1369
Austin Kinrossaf875522014-08-25 21:06:07 -07001370 GLint maxVaryings = 0;
1371 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1372
Austin Kinross8b695ee2015-03-12 13:12:20 -07001373 VaryingTestBase(0, 0, 2 * maxVaryings, 0, 0, 0, 0, 0, false, false, false, true);
Austin Kinrossaf875522014-08-25 21:06:07 -07001374}
1375
Jamie Madillbee59e02014-10-02 10:44:18 -04001376// Disabled because of a failure in D3D9
Jamie Madill9fc36822015-11-18 13:08:07 -05001377TEST_P(GLSLTest, MaxVaryingVec2Arrays)
Austin Kinrossaf875522014-08-25 21:06:07 -07001378{
Jamie Madill518b9fa2016-03-02 11:26:02 -05001379 if (IsD3DSM3())
Jamie Madill9fc36822015-11-18 13:08:07 -05001380 {
1381 std::cout << "Test disabled on SM3." << std::endl;
1382 return;
1383 }
1384
Geoff Lange0cc2a42016-01-20 10:58:17 -05001385 if (getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
1386 {
1387 // TODO(geofflang): Figure out why this fails on NVIDIA's GLES driver
1388 std::cout << "Test disabled on OpenGL ES." << std::endl;
1389 return;
1390 }
1391
Geoff Lang69accbd2016-01-25 16:22:32 -05001392#if defined(__APPLE__)
1393 // TODO(geofflang): Find out why this doesn't compile on Apple AND OpenGL drivers
1394 // (http://anglebug.com/1291)
Jamie Madill518b9fa2016-03-02 11:26:02 -05001395 if (IsAMD() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
Geoff Lang69accbd2016-01-25 16:22:32 -05001396 {
1397 std::cout << "Test disabled on Apple AMD OpenGL." << std::endl;
1398 return;
1399 }
1400#endif
1401
Austin Kinrossaf875522014-08-25 21:06:07 -07001402 GLint maxVaryings = 0;
1403 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1404
Jamie Madill192745a2016-12-22 15:58:21 -05001405 // Special case: because arrays of mat2 are packed as small grids of two rows by two columns,
1406 // we should be aware that when we're packing into an odd number of varying registers the
1407 // last row will be empty and can not fit the final vec2 arrary.
1408 GLint maxVec2Arrays = (maxVaryings >> 1) << 1;
1409
1410 VaryingTestBase(0, 0, 0, maxVec2Arrays, 0, 0, 0, 0, false, false, false, true);
Austin Kinrossaf875522014-08-25 21:06:07 -07001411}
1412
Geoff Langf60fab62014-11-24 11:21:20 -05001413// Verify shader source with a fixed length that is less than the null-terminated length will compile.
Jamie Madillfa05f602015-05-07 13:47:11 -04001414TEST_P(GLSLTest, FixedShaderLength)
Geoff Langf60fab62014-11-24 11:21:20 -05001415{
1416 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1417
1418 const std::string appendGarbage = "abcasdfasdfasdfasdfasdf";
1419 const std::string source = "void main() { gl_FragColor = vec4(0, 0, 0, 0); }" + appendGarbage;
1420 const char *sourceArray[1] = { source.c_str() };
Corentin Wallez973402f2015-05-11 13:42:22 -04001421 GLint lengths[1] = { static_cast<GLint>(source.length() - appendGarbage.length()) };
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001422 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
Geoff Langf60fab62014-11-24 11:21:20 -05001423 glCompileShader(shader);
1424
1425 GLint compileResult;
1426 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1427 EXPECT_NE(compileResult, 0);
1428}
1429
1430// Verify that a negative shader source length is treated as a null-terminated length.
Jamie Madillfa05f602015-05-07 13:47:11 -04001431TEST_P(GLSLTest, NegativeShaderLength)
Geoff Langf60fab62014-11-24 11:21:20 -05001432{
1433 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1434
1435 const char *sourceArray[1] = { "void main() { gl_FragColor = vec4(0, 0, 0, 0); }" };
1436 GLint lengths[1] = { -10 };
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001437 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
Geoff Langf60fab62014-11-24 11:21:20 -05001438 glCompileShader(shader);
1439
1440 GLint compileResult;
1441 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1442 EXPECT_NE(compileResult, 0);
1443}
1444
Corentin Wallez9a9c0482016-04-12 10:36:25 -04001445// Check that having an invalid char after the "." doesn't cause an assert.
1446TEST_P(GLSLTest, InvalidFieldFirstChar)
1447{
1448 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
1449 const char *source = "void main() {vec4 x; x.}";
1450 glShaderSource(shader, 1, &source, 0);
1451 glCompileShader(shader);
1452
1453 GLint compileResult;
1454 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1455 EXPECT_EQ(0, compileResult);
1456}
1457
Geoff Langf60fab62014-11-24 11:21:20 -05001458// Verify that a length array with mixed positive and negative values compiles.
Jamie Madillfa05f602015-05-07 13:47:11 -04001459TEST_P(GLSLTest, MixedShaderLengths)
Geoff Langf60fab62014-11-24 11:21:20 -05001460{
1461 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1462
1463 const char *sourceArray[] =
1464 {
1465 "void main()",
1466 "{",
1467 " gl_FragColor = vec4(0, 0, 0, 0);",
1468 "}",
1469 };
1470 GLint lengths[] =
1471 {
1472 -10,
1473 1,
Corentin Wallez973402f2015-05-11 13:42:22 -04001474 static_cast<GLint>(strlen(sourceArray[2])),
Geoff Langf60fab62014-11-24 11:21:20 -05001475 -1,
1476 };
1477 ASSERT_EQ(ArraySize(sourceArray), ArraySize(lengths));
1478
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001479 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
Geoff Langf60fab62014-11-24 11:21:20 -05001480 glCompileShader(shader);
1481
1482 GLint compileResult;
1483 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1484 EXPECT_NE(compileResult, 0);
1485}
1486
1487// Verify that zero-length shader source does not affect shader compilation.
Jamie Madillfa05f602015-05-07 13:47:11 -04001488TEST_P(GLSLTest, ZeroShaderLength)
Geoff Langf60fab62014-11-24 11:21:20 -05001489{
1490 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1491
1492 const char *sourceArray[] =
1493 {
1494 "adfasdf",
1495 "34534",
1496 "void main() { gl_FragColor = vec4(0, 0, 0, 0); }",
1497 "",
1498 "asdfasdfsdsdf",
1499 };
1500 GLint lengths[] =
1501 {
1502 0,
1503 0,
1504 -1,
1505 0,
1506 0,
1507 };
1508 ASSERT_EQ(ArraySize(sourceArray), ArraySize(lengths));
1509
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001510 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
Geoff Langf60fab62014-11-24 11:21:20 -05001511 glCompileShader(shader);
1512
1513 GLint compileResult;
1514 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1515 EXPECT_NE(compileResult, 0);
1516}
Jamie Madill21c1e452014-12-29 11:33:41 -05001517
1518// Tests that bad index expressions don't crash ANGLE's translator.
1519// https://code.google.com/p/angleproject/issues/detail?id=857
Jamie Madillfa05f602015-05-07 13:47:11 -04001520TEST_P(GLSLTest, BadIndexBug)
Jamie Madill21c1e452014-12-29 11:33:41 -05001521{
1522 const std::string &fragmentShaderSourceVec =
1523 "precision mediump float;\n"
1524 "uniform vec4 uniformVec;\n"
1525 "void main()\n"
1526 "{\n"
1527 " gl_FragColor = vec4(uniformVec[int()]);\n"
1528 "}";
1529
1530 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, fragmentShaderSourceVec);
1531 EXPECT_EQ(0u, shader);
1532
1533 if (shader != 0)
1534 {
1535 glDeleteShader(shader);
1536 }
1537
1538 const std::string &fragmentShaderSourceMat =
1539 "precision mediump float;\n"
1540 "uniform mat4 uniformMat;\n"
1541 "void main()\n"
1542 "{\n"
1543 " gl_FragColor = vec4(uniformMat[int()]);\n"
1544 "}";
1545
1546 shader = CompileShader(GL_FRAGMENT_SHADER, fragmentShaderSourceMat);
1547 EXPECT_EQ(0u, shader);
1548
1549 if (shader != 0)
1550 {
1551 glDeleteShader(shader);
1552 }
1553
1554 const std::string &fragmentShaderSourceArray =
1555 "precision mediump float;\n"
1556 "uniform vec4 uniformArray;\n"
1557 "void main()\n"
1558 "{\n"
1559 " gl_FragColor = vec4(uniformArray[int()]);\n"
1560 "}";
1561
1562 shader = CompileShader(GL_FRAGMENT_SHADER, fragmentShaderSourceArray);
1563 EXPECT_EQ(0u, shader);
1564
1565 if (shader != 0)
1566 {
1567 glDeleteShader(shader);
1568 }
Jamie Madill37997142015-01-28 10:06:34 -05001569}
1570
Jamie Madill2e295e22015-04-29 10:41:33 -04001571// Test that structs defined in uniforms are translated correctly.
Jamie Madillfa05f602015-05-07 13:47:11 -04001572TEST_P(GLSLTest, StructSpecifiersUniforms)
Jamie Madill2e295e22015-04-29 10:41:33 -04001573{
Olli Etuahoa20af6d2017-09-18 13:32:29 +03001574 const std::string fragmentShaderSource =
1575 R"(precision mediump float;
Jamie Madill2e295e22015-04-29 10:41:33 -04001576
1577 uniform struct S { float field;} s;
1578
1579 void main()
1580 {
1581 gl_FragColor = vec4(1, 0, 0, 1);
1582 gl_FragColor.a += s.field;
Olli Etuahoa20af6d2017-09-18 13:32:29 +03001583 })";
Jamie Madill2e295e22015-04-29 10:41:33 -04001584
1585 GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
1586 EXPECT_NE(0u, program);
1587}
Jamie Madill55def582015-05-04 11:24:57 -04001588
1589// Test that gl_DepthRange is not stored as a uniform location. Since uniforms
1590// beginning with "gl_" are filtered out by our validation logic, we must
1591// bypass the validation to test the behaviour of the implementation.
1592// (note this test is still Impl-independent)
Jamie Madille1faacb2016-12-13 12:42:14 -05001593TEST_P(GLSLTestNoValidation, DepthRangeUniforms)
Jamie Madill55def582015-05-04 11:24:57 -04001594{
Olli Etuahoa20af6d2017-09-18 13:32:29 +03001595 const std::string fragmentShaderSource =
1596 R"(precision mediump float;
Jamie Madill55def582015-05-04 11:24:57 -04001597
1598 void main()
1599 {
1600 gl_FragColor = vec4(gl_DepthRange.near, gl_DepthRange.far, gl_DepthRange.diff, 1);
Olli Etuahoa20af6d2017-09-18 13:32:29 +03001601 })";
Jamie Madill55def582015-05-04 11:24:57 -04001602
Jamie Madille1faacb2016-12-13 12:42:14 -05001603 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShaderSource);
Jamie Madill55def582015-05-04 11:24:57 -04001604
Jamie Madille1faacb2016-12-13 12:42:14 -05001605 // We need to bypass validation for this call.
1606 GLint nearIndex = glGetUniformLocation(program.get(), "gl_DepthRange.near");
Jamie Madill55def582015-05-04 11:24:57 -04001607 EXPECT_EQ(-1, nearIndex);
1608
1609 // Test drawing does not throw an exception.
Jamie Madille1faacb2016-12-13 12:42:14 -05001610 drawQuad(program.get(), "inputAttribute", 0.5f);
Jamie Madill55def582015-05-04 11:24:57 -04001611
1612 EXPECT_GL_NO_ERROR();
Jamie Madill55def582015-05-04 11:24:57 -04001613}
Jamie Madill4052dfc2015-05-06 15:18:49 -04001614
Jamie Madill6c9503e2016-08-16 14:06:32 -04001615std::string GenerateSmallPowShader(double base, double exponent)
1616{
1617 std::stringstream stream;
1618
1619 stream.precision(8);
1620
1621 double result = pow(base, exponent);
1622
1623 stream << "precision highp float;\n"
1624 << "float fun(float arg)\n"
1625 << "{\n"
1626 << " return pow(arg, " << std::fixed << exponent << ");\n"
1627 << "}\n"
1628 << "\n"
1629 << "void main()\n"
1630 << "{\n"
1631 << " const float a = " << std::scientific << base << ";\n"
1632 << " float b = fun(a);\n"
1633 << " if (abs(" << result << " - b) < " << std::abs(result * 0.001) << ")\n"
1634 << " {\n"
1635 << " gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
1636 << " }\n"
1637 << " else\n"
1638 << " {\n"
1639 << " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
1640 << " }\n"
1641 << "}\n";
1642
1643 return stream.str();
1644}
1645
Jamie Madill4052dfc2015-05-06 15:18:49 -04001646// Covers the WebGL test 'glsl/bugs/pow-of-small-constant-in-user-defined-function'
Jamie Madill1048e432016-07-23 18:51:28 -04001647// See http://anglebug.com/851
1648TEST_P(GLSLTest, PowOfSmallConstant)
Jamie Madill4052dfc2015-05-06 15:18:49 -04001649{
Olli Etuaho629a6442017-12-11 10:55:43 +02001650 // Test with problematic exponents that are close to an integer.
1651 std::vector<double> testExponents;
1652 std::array<double, 5> epsilonMultipliers = {-100.0, -1.0, 0.0, 1.0, 100.0};
1653 for (double epsilonMultiplier : epsilonMultipliers)
Jamie Madill6c9503e2016-08-16 14:06:32 -04001654 {
1655 for (int i = -4; i <= 5; ++i)
Jamie Madill4052dfc2015-05-06 15:18:49 -04001656 {
Jamie Madill6c9503e2016-08-16 14:06:32 -04001657 if (i >= -1 && i <= 1)
1658 continue;
1659 const double epsilon = 1.0e-8;
Olli Etuaho629a6442017-12-11 10:55:43 +02001660 double bad = static_cast<double>(i) + epsilonMultiplier * epsilon;
1661 testExponents.push_back(bad);
Jamie Madill4052dfc2015-05-06 15:18:49 -04001662 }
Jamie Madill6c9503e2016-08-16 14:06:32 -04001663 }
Jamie Madill4052dfc2015-05-06 15:18:49 -04001664
Olli Etuaho629a6442017-12-11 10:55:43 +02001665 // Also test with a few exponents that are not close to an integer.
1666 testExponents.push_back(3.6);
1667 testExponents.push_back(3.4);
1668
1669 for (double testExponent : testExponents)
Jamie Madill6c9503e2016-08-16 14:06:32 -04001670 {
Olli Etuaho629a6442017-12-11 10:55:43 +02001671 const std::string &fragmentShaderSource = GenerateSmallPowShader(1.0e-6, testExponent);
Jamie Madill4052dfc2015-05-06 15:18:49 -04001672
Jamie Madill6c9503e2016-08-16 14:06:32 -04001673 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShaderSource);
Jamie Madill4052dfc2015-05-06 15:18:49 -04001674
Jamie Madill6c9503e2016-08-16 14:06:32 -04001675 drawQuad(program.get(), "inputAttribute", 0.5f);
1676
1677 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1678 EXPECT_GL_NO_ERROR();
1679 }
Jamie Madill4052dfc2015-05-06 15:18:49 -04001680}
Jamie Madillfa05f602015-05-07 13:47:11 -04001681
Cooper Partina5ef8d82015-08-19 14:52:21 -07001682// Test that fragment shaders which contain non-constant loop indexers and compiled for FL9_3 and
1683// below
1684// fail with a specific error message.
1685// Additionally test that the same fragment shader compiles successfully with feature levels greater
1686// than FL9_3.
1687TEST_P(GLSLTest, LoopIndexingValidation)
1688{
Olli Etuahoa20af6d2017-09-18 13:32:29 +03001689 const std::string fragmentShaderSource =
1690 R"(precision mediump float;
Cooper Partina5ef8d82015-08-19 14:52:21 -07001691
1692 uniform float loopMax;
1693
1694 void main()
1695 {
1696 gl_FragColor = vec4(1, 0, 0, 1);
1697 for (float l = 0.0; l < loopMax; l++)
1698 {
1699 if (loopMax > 3.0)
1700 {
1701 gl_FragColor.a += 0.1;
1702 }
1703 }
Olli Etuahoa20af6d2017-09-18 13:32:29 +03001704 })";
Cooper Partina5ef8d82015-08-19 14:52:21 -07001705
1706 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1707
1708 const char *sourceArray[1] = {fragmentShaderSource.c_str()};
1709 glShaderSource(shader, 1, sourceArray, nullptr);
1710 glCompileShader(shader);
1711
1712 GLint compileResult;
1713 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1714
1715 // If the test is configured to run limited to Feature Level 9_3, then it is
1716 // assumed that shader compilation will fail with an expected error message containing
1717 // "Loop index cannot be compared with non-constant expression"
Olli Etuaho814a54d2015-08-27 16:23:09 +03001718 if ((GetParam() == ES2_D3D11_FL9_3() || GetParam() == ES2_D3D9()))
Cooper Partina5ef8d82015-08-19 14:52:21 -07001719 {
1720 if (compileResult != 0)
1721 {
1722 FAIL() << "Shader compilation succeeded, expected failure";
1723 }
1724 else
1725 {
1726 GLint infoLogLength;
1727 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
1728
1729 std::string infoLog;
1730 infoLog.resize(infoLogLength);
Yunchao Hef81ce4a2017-04-24 10:49:17 +08001731 glGetShaderInfoLog(shader, static_cast<GLsizei>(infoLog.size()), nullptr, &infoLog[0]);
Cooper Partina5ef8d82015-08-19 14:52:21 -07001732
1733 if (infoLog.find("Loop index cannot be compared with non-constant expression") ==
1734 std::string::npos)
1735 {
1736 FAIL() << "Shader compilation failed with unexpected error message";
1737 }
1738 }
1739 }
1740 else
1741 {
1742 EXPECT_NE(0, compileResult);
1743 }
1744
1745 if (shader != 0)
1746 {
1747 glDeleteShader(shader);
1748 }
1749}
1750
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001751// Tests that the maximum uniforms count returned from querying GL_MAX_VERTEX_UNIFORM_VECTORS
1752// can actually be used.
1753TEST_P(GLSLTest, VerifyMaxVertexUniformVectors)
1754{
Zhenyao Mo1a256722017-01-12 11:52:57 -08001755 if (IsLinux() && IsIntel())
1756 {
1757 std::cout << "Test timed out on Linux Intel. See crbug.com/680631." << std::endl;
1758 return;
1759 }
1760
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001761 int maxUniforms = 10000;
1762 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
1763 EXPECT_GL_NO_ERROR();
1764 std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS = " << maxUniforms << std::endl;
1765
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001766 CompileGLSLWithUniformsAndSamplers(maxUniforms, 0, 0, 0, true);
1767}
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001768
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001769// Tests that the maximum uniforms count returned from querying GL_MAX_VERTEX_UNIFORM_VECTORS
1770// can actually be used along with the maximum number of texture samplers.
1771TEST_P(GLSLTest, VerifyMaxVertexUniformVectorsWithSamplers)
1772{
Geoff Lange0cc2a42016-01-20 10:58:17 -05001773 if (GetParam().eglParameters.renderer == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE ||
1774 GetParam().eglParameters.renderer == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
1775 {
1776 std::cout << "Test disabled on OpenGL." << std::endl;
1777 return;
1778 }
1779
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001780 int maxUniforms = 10000;
1781 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
1782 EXPECT_GL_NO_ERROR();
1783 std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS = " << maxUniforms << std::endl;
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001784
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001785 int maxTextureImageUnits = 0;
1786 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001787
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001788 CompileGLSLWithUniformsAndSamplers(maxUniforms, 0, maxTextureImageUnits, 0, true);
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001789}
1790
1791// Tests that the maximum uniforms count + 1 from querying GL_MAX_VERTEX_UNIFORM_VECTORS
1792// fails shader compilation.
1793TEST_P(GLSLTest, VerifyMaxVertexUniformVectorsExceeded)
1794{
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001795 int maxUniforms = 10000;
1796 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
1797 EXPECT_GL_NO_ERROR();
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001798 std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS + 1 = " << maxUniforms + 1 << std::endl;
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001799
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001800 CompileGLSLWithUniformsAndSamplers(maxUniforms + 1, 0, 0, 0, false);
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001801}
1802
1803// Tests that the maximum uniforms count returned from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
1804// can actually be used.
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001805TEST_P(GLSLTest, VerifyMaxFragmentUniformVectors)
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001806{
Zhenyao Mo1a256722017-01-12 11:52:57 -08001807 if (IsLinux() && IsIntel())
1808 {
1809 std::cout << "Test timed out on Linux Intel. See crbug.com/680631." << std::endl;
1810 return;
1811 }
1812
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001813 int maxUniforms = 10000;
1814 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
1815 EXPECT_GL_NO_ERROR();
1816 std::cout << "Validating GL_MAX_FRAGMENT_UNIFORM_VECTORS = " << maxUniforms << std::endl;
1817
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001818 CompileGLSLWithUniformsAndSamplers(0, maxUniforms, 0, 0, true);
1819}
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001820
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001821// Tests that the maximum uniforms count returned from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
1822// can actually be used along with the maximum number of texture samplers.
1823TEST_P(GLSLTest, VerifyMaxFragmentUniformVectorsWithSamplers)
1824{
Geoff Lange0cc2a42016-01-20 10:58:17 -05001825 if (GetParam().eglParameters.renderer == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE ||
1826 GetParam().eglParameters.renderer == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
1827 {
1828 std::cout << "Test disabled on OpenGL." << std::endl;
1829 return;
1830 }
1831
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001832 int maxUniforms = 10000;
1833 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
1834 EXPECT_GL_NO_ERROR();
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001835
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001836 int maxTextureImageUnits = 0;
1837 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001838
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001839 CompileGLSLWithUniformsAndSamplers(0, maxUniforms, 0, maxTextureImageUnits, true);
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001840}
1841
1842// Tests that the maximum uniforms count + 1 from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
1843// fails shader compilation.
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001844TEST_P(GLSLTest, VerifyMaxFragmentUniformVectorsExceeded)
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001845{
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001846 int maxUniforms = 10000;
1847 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
1848 EXPECT_GL_NO_ERROR();
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001849 std::cout << "Validating GL_MAX_FRAGMENT_UNIFORM_VECTORS + 1 = " << maxUniforms + 1
1850 << std::endl;
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001851
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001852 CompileGLSLWithUniformsAndSamplers(0, maxUniforms + 1, 0, 0, false);
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001853}
1854
Geoff Langba992ab2017-04-19 11:18:14 -04001855// Test compiling shaders using the GL_EXT_shader_texture_lod extension
1856TEST_P(GLSLTest, TextureLOD)
1857{
1858 if (!extensionEnabled("GL_EXT_shader_texture_lod"))
1859 {
1860 std::cout << "Test skipped due to missing GL_EXT_shader_texture_lod." << std::endl;
1861 return;
1862 }
1863
1864 const std::string source =
1865 "#extension GL_EXT_shader_texture_lod : require\n"
1866 "uniform sampler2D u_texture;\n"
1867 "void main() {\n"
1868 " gl_FragColor = texture2DGradEXT(u_texture, vec2(0.0, 0.0), vec2(0.0, 0.0), vec2(0.0, "
1869 "0.0));\n"
1870 "}\n";
1871
1872 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, source);
1873 ASSERT_NE(0u, shader);
1874 glDeleteShader(shader);
1875}
1876
Olli Etuahobe59c2f2016-03-07 11:32:34 +02001877// Test that two constructors which have vec4 and mat2 parameters get disambiguated (issue in
1878// HLSL).
1879TEST_P(GLSLTest_ES3, AmbiguousConstructorCall2x2)
1880{
1881 const std::string fragmentShaderSource =
1882 "#version 300 es\n"
1883 "precision highp float;\n"
1884 "out vec4 my_FragColor;\n"
1885 "void main()\n"
1886 "{\n"
1887 " my_FragColor = vec4(0.0);\n"
1888 "}";
1889
1890 const std::string vertexShaderSource =
1891 "#version 300 es\n"
1892 "precision highp float;\n"
1893 "in vec4 a_vec;\n"
1894 "in mat2 a_mat;\n"
1895 "void main()\n"
1896 "{\n"
1897 " gl_Position = vec4(a_vec) + vec4(a_mat);\n"
1898 "}";
1899
1900 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1901 EXPECT_NE(0u, program);
1902}
1903
1904// Test that two constructors which have mat2x3 and mat3x2 parameters get disambiguated.
1905// This was suspected to be an issue in HLSL, but HLSL seems to be able to natively choose between
1906// the function signatures in this case.
1907TEST_P(GLSLTest_ES3, AmbiguousConstructorCall2x3)
1908{
1909 const std::string fragmentShaderSource =
1910 "#version 300 es\n"
1911 "precision highp float;\n"
1912 "out vec4 my_FragColor;\n"
1913 "void main()\n"
1914 "{\n"
1915 " my_FragColor = vec4(0.0);\n"
1916 "}";
1917
1918 const std::string vertexShaderSource =
1919 "#version 300 es\n"
1920 "precision highp float;\n"
1921 "in mat3x2 a_matA;\n"
1922 "in mat2x3 a_matB;\n"
1923 "void main()\n"
1924 "{\n"
1925 " gl_Position = vec4(a_matA) + vec4(a_matB);\n"
1926 "}";
1927
1928 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1929 EXPECT_NE(0u, program);
1930}
1931
1932// Test that two functions which have vec4 and mat2 parameters get disambiguated (issue in HLSL).
1933TEST_P(GLSLTest_ES3, AmbiguousFunctionCall2x2)
1934{
1935 const std::string fragmentShaderSource =
1936 "#version 300 es\n"
1937 "precision highp float;\n"
1938 "out vec4 my_FragColor;\n"
1939 "void main()\n"
1940 "{\n"
1941 " my_FragColor = vec4(0.0);\n"
1942 "}";
1943
1944 const std::string vertexShaderSource =
1945 "#version 300 es\n"
1946 "precision highp float;\n"
1947 "in vec4 a_vec;\n"
1948 "in mat2 a_mat;\n"
1949 "vec4 foo(vec4 a)\n"
1950 "{\n"
1951 " return a;\n"
1952 "}\n"
1953 "vec4 foo(mat2 a)\n"
1954 "{\n"
1955 " return vec4(a[0][0]);\n"
1956 "}\n"
1957 "void main()\n"
1958 "{\n"
1959 " gl_Position = foo(a_vec) + foo(a_mat);\n"
1960 "}";
1961
1962 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1963 EXPECT_NE(0u, program);
1964}
1965
1966// Test that an user-defined function with a large number of float4 parameters doesn't fail due to
1967// the function name being too long.
1968TEST_P(GLSLTest_ES3, LargeNumberOfFloat4Parameters)
1969{
1970 const std::string fragmentShaderSource =
1971 "#version 300 es\n"
1972 "precision highp float;\n"
1973 "out vec4 my_FragColor;\n"
1974 "void main()\n"
1975 "{\n"
1976 " my_FragColor = vec4(0.0);\n"
1977 "}";
1978
1979 std::stringstream vertexShaderStream;
1980 const unsigned int paramCount = 1024u;
1981
1982 vertexShaderStream << "#version 300 es\n"
1983 "precision highp float;\n"
1984 "in vec4 a_vec;\n"
1985 "vec4 lotsOfVec4Parameters(";
1986 for (unsigned int i = 0; i < paramCount; ++i)
1987 {
1988 vertexShaderStream << "vec4 a" << i << ", ";
1989 }
1990 vertexShaderStream << "vec4 aLast)\n"
1991 "{\n"
1992 " return ";
1993 for (unsigned int i = 0; i < paramCount; ++i)
1994 {
1995 vertexShaderStream << "a" << i << " + ";
1996 }
1997 vertexShaderStream << "aLast;\n"
1998 "}\n"
1999 "void main()\n"
2000 "{\n"
2001 " gl_Position = lotsOfVec4Parameters(";
2002 for (unsigned int i = 0; i < paramCount; ++i)
2003 {
2004 vertexShaderStream << "a_vec, ";
2005 }
2006 vertexShaderStream << "a_vec);\n"
2007 "}";
2008
2009 GLuint program = CompileProgram(vertexShaderStream.str(), fragmentShaderSource);
2010 EXPECT_NE(0u, program);
2011}
2012
Olli Etuahod4f4c112016-04-15 15:11:24 +03002013// This test was written specifically to stress DeferGlobalInitializers AST transformation.
2014// Test a shader where a global constant array is initialized with an expression containing array
2015// indexing. This initializer is tricky to constant fold, so if it's not constant folded it needs to
2016// be handled in a way that doesn't generate statements in the global scope in HLSL output.
2017// Also includes multiple array initializers in one declaration, where only the second one has
2018// array indexing. This makes sure that the qualifier for the declaration is set correctly if
2019// transformations are applied to the declaration also in the case of ESSL output.
2020TEST_P(GLSLTest_ES3, InitGlobalArrayWithArrayIndexing)
2021{
Yuly Novikov41db2242016-06-25 00:14:28 -04002022 // TODO(ynovikov): re-enable once root cause of http://anglebug.com/1428 is fixed
2023 if (IsAndroid() && IsAdreno() && IsOpenGLES())
2024 {
2025 std::cout << "Test skipped on Adreno OpenGLES on Android." << std::endl;
2026 return;
2027 }
2028
Olli Etuahod4f4c112016-04-15 15:11:24 +03002029 const std::string vertexShaderSource =
2030 "#version 300 es\n"
2031 "precision highp float;\n"
2032 "in vec4 a_vec;\n"
2033 "void main()\n"
2034 "{\n"
2035 " gl_Position = vec4(a_vec);\n"
2036 "}";
2037
2038 const std::string fragmentShaderSource =
2039 "#version 300 es\n"
2040 "precision highp float;\n"
2041 "out vec4 my_FragColor;\n"
2042 "const highp float f[2] = float[2](0.1, 0.2);\n"
2043 "const highp float[2] g = float[2](0.3, 0.4), h = float[2](0.5, f[1]);\n"
2044 "void main()\n"
2045 "{\n"
2046 " my_FragColor = vec4(h[1]);\n"
2047 "}";
2048
2049 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
2050 EXPECT_NE(0u, program);
2051}
2052
Corentin Wallez419bfc92016-06-28 10:54:45 -07002053// Test that index-constant sampler array indexing is supported.
2054TEST_P(GLSLTest, IndexConstantSamplerArrayIndexing)
2055{
2056 if (IsD3D11_FL93()) {
2057 std::cout << "Test skipped on D3D11 FL 9.3." << std::endl;
2058 return;
2059 }
2060
2061 const std::string vertexShaderSource =
2062 "attribute vec4 vPosition;\n"
2063 "void main()\n"
2064 "{\n"
2065 " gl_Position = vPosition;\n"
2066 "}";
2067
2068 const std::string fragmentShaderSource =
2069 "precision mediump float;\n"
2070 "uniform sampler2D uni[2];\n"
2071 "\n"
2072 "float zero(int x)\n"
2073 "{\n"
2074 " return float(x) - float(x);\n"
2075 "}\n"
2076 "\n"
2077 "void main()\n"
2078 "{\n"
2079 " vec4 c = vec4(0,0,0,0);\n"
2080 " for (int ii = 1; ii < 3; ++ii) {\n"
2081 " if (c.x > 255.0) {\n"
2082 " c.x = 255.0 + zero(ii);\n"
2083 " break;\n"
2084 " }\n"
2085 // Index the sampler array with a predictable loop index (index-constant) as opposed to
2086 // a true constant. This is valid in OpenGL ES but isn't in many Desktop OpenGL versions,
2087 // without an extension.
2088 " c += texture2D(uni[ii - 1], vec2(0.5, 0.5));\n"
2089 " }\n"
2090 " gl_FragColor = c;\n"
2091 "}";
2092
2093 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
2094 EXPECT_NE(0u, program);
2095}
2096
Corentin Wallezb00dcee2016-07-11 17:42:58 -04002097// Test that the #pragma directive is supported and doesn't trigger a compilation failure on the
2098// native driver. The only pragma that gets passed to the OpenGL driver is "invariant" but we don't
2099// want to test its behavior, so don't use any varyings.
2100TEST_P(GLSLTest, PragmaDirective)
2101{
2102 const std::string vertexShaderSource =
2103 "#pragma STDGL invariant(all)\n"
2104 "void main()\n"
2105 "{\n"
2106 " gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
2107 "}\n";
2108
2109 const std::string fragmentShaderSource =
2110 "precision mediump float;\n"
2111 "void main()\n"
2112 "{\n"
2113 " gl_FragColor = vec4(1.0);\n"
2114 "}\n";
2115
2116 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
2117 EXPECT_NE(0u, program);
2118}
2119
Olli Etuahoe1d199b2016-07-19 17:14:27 +03002120// Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
2121// The function call that returns the array needs to be evaluated after ++j for the expression to
2122// return the correct value (true).
2123TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderArray)
2124{
2125 const std::string &fragmentShaderSource =
2126 "#version 300 es\n"
2127 "precision mediump float;\n"
2128 "out vec4 my_FragColor; \n"
2129 "int[2] func(int param) {\n"
2130 " return int[2](param, param);\n"
2131 "}\n"
2132 "void main() {\n"
2133 " int a[2]; \n"
2134 " for (int i = 0; i < 2; ++i) {\n"
2135 " a[i] = 1;\n"
2136 " }\n"
2137 " int j = 0; \n"
2138 " bool result = ((++j), (a == func(j)));\n"
2139 " my_FragColor = vec4(0.0, (result ? 1.0 : 0.0), 0.0, 1.0);\n"
2140 "}\n";
2141
2142 GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
2143 ASSERT_NE(0u, program);
2144
2145 drawQuad(program, "inputAttribute", 0.5f);
2146
2147 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2148}
2149
2150// Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
2151// The short-circuiting expression needs to be evaluated after ++j for the expression to return the
2152// correct value (true).
2153TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderShortCircuit)
2154{
2155 const std::string &fragmentShaderSource =
2156 "#version 300 es\n"
2157 "precision mediump float;\n"
2158 "out vec4 my_FragColor; \n"
2159 "void main() {\n"
2160 " int j = 0; \n"
2161 " bool result = ((++j), (j == 1 ? true : (++j == 3)));\n"
2162 " my_FragColor = vec4(0.0, ((result && j == 1) ? 1.0 : 0.0), 0.0, 1.0);\n"
2163 "}\n";
2164
2165 GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
2166 ASSERT_NE(0u, program);
2167
2168 drawQuad(program, "inputAttribute", 0.5f);
2169
2170 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2171}
2172
Jamie Madill666f65a2016-08-26 01:34:37 +00002173// Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
2174// Indexing the vector needs to be evaluated after func() for the right result.
2175TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderDynamicVectorIndexingInLValue)
2176{
2177 const std::string &fragmentShaderSource =
2178 "#version 300 es\n"
2179 "precision mediump float;\n"
2180 "out vec4 my_FragColor;\n"
2181 "uniform int u_zero;\n"
2182 "int sideEffectCount = 0;\n"
2183 "float func() {\n"
2184 " ++sideEffectCount;\n"
2185 " return -1.0;\n"
2186 "}\n"
2187 "void main() {\n"
2188 " vec4 v = vec4(0.0, 2.0, 4.0, 6.0); \n"
2189 " float f = (func(), (++v[u_zero + sideEffectCount]));\n"
2190 " bool green = abs(f - 3.0) < 0.01 && abs(v[1] - 3.0) < 0.01 && sideEffectCount == 1;\n"
2191 " my_FragColor = vec4(0.0, (green ? 1.0 : 0.0), 0.0, 1.0);\n"
2192 "}\n";
2193
2194 GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
2195 ASSERT_NE(0u, program);
2196
2197 drawQuad(program, "inputAttribute", 0.5f);
2198
2199 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2200}
2201
Jamie Madillc9bde922016-07-24 17:58:50 -04002202// Test that using gl_PointCoord with GL_TRIANGLES doesn't produce a link error.
2203// From WebGL test conformance/rendering/point-specific-shader-variables.html
2204// See http://anglebug.com/1380
2205TEST_P(GLSLTest, RenderTrisWithPointCoord)
2206{
2207 const std::string &vert =
2208 "attribute vec2 aPosition;\n"
2209 "void main()\n"
2210 "{\n"
2211 " gl_Position = vec4(aPosition, 0, 1);\n"
2212 " gl_PointSize = 1.0;\n"
2213 "}";
2214 const std::string &frag =
2215 "void main()\n"
2216 "{\n"
2217 " gl_FragColor = vec4(gl_PointCoord.xy, 0, 1);\n"
2218 " gl_FragColor = vec4(0, 1, 0, 1);\n"
2219 "}";
2220
2221 ANGLE_GL_PROGRAM(prog, vert, frag);
2222 drawQuad(prog.get(), "aPosition", 0.5f);
2223 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2224}
2225
Jamie Madill5655b842016-08-02 11:00:07 -04002226// Convers a bug with the integer pow statement workaround.
2227TEST_P(GLSLTest, NestedPowStatements)
2228{
2229 const std::string &vert =
2230 "attribute vec2 position;\n"
2231 "void main()\n"
2232 "{\n"
2233 " gl_Position = vec4(position, 0, 1);\n"
2234 "}";
2235 const std::string &frag =
2236 "precision mediump float;\n"
2237 "float func(float v)\n"
2238 "{\n"
2239 " float f1 = pow(v, 2.0);\n"
2240 " return pow(f1 + v, 2.0);\n"
2241 "}\n"
2242 "void main()\n"
2243 "{\n"
2244 " float v = func(2.0);\n"
2245 " gl_FragColor = abs(v - 36.0) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
2246 "}";
2247
2248 ANGLE_GL_PROGRAM(prog, vert, frag);
2249 drawQuad(prog.get(), "position", 0.5f);
2250 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2251}
2252
Qiankun Miaof52fe932016-12-07 13:39:15 +08002253// Test that -float calculation is correct.
2254TEST_P(GLSLTest_ES3, UnaryMinusOperatorFloat)
2255{
Qiankun Miaof52fe932016-12-07 13:39:15 +08002256 const std::string &vert =
2257 "#version 300 es\n"
2258 "in highp vec4 position;\n"
2259 "void main() {\n"
2260 " gl_Position = position;\n"
2261 "}\n";
2262 const std::string &frag =
2263 "#version 300 es\n"
2264 "out highp vec4 o_color;\n"
2265 "void main() {\n"
2266 " highp float f = -1.0;\n"
2267 " // atan(tan(0.5), -f) should be 0.5.\n"
2268 " highp float v = atan(tan(0.5), -f);\n"
2269 " o_color = abs(v - 0.5) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
2270 "}\n";
2271
2272 ANGLE_GL_PROGRAM(prog, vert, frag);
2273 drawQuad(prog.get(), "position", 0.5f);
2274 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2275}
2276
Olli Etuahoda9fb092016-12-09 17:32:29 +00002277// Test that atan(vec2, vec2) calculation is correct.
2278TEST_P(GLSLTest_ES3, AtanVec2)
2279{
2280 const std::string &vert =
2281 "#version 300 es\n"
2282 "in highp vec4 position;\n"
2283 "void main() {\n"
2284 " gl_Position = position;\n"
2285 "}\n";
2286 const std::string &frag =
2287 "#version 300 es\n"
2288 "out highp vec4 o_color;\n"
2289 "void main() {\n"
2290 " highp float f = 1.0;\n"
2291 " // atan(tan(0.5), f) should be 0.5.\n"
2292 " highp vec2 v = atan(vec2(tan(0.5)), vec2(f));\n"
2293 " o_color = (abs(v[0] - 0.5) < 0.001 && abs(v[1] - 0.5) < 0.001) ? vec4(0, 1, 0, 1) : "
2294 "vec4(1, 0, 0, 1);\n"
2295 "}\n";
2296
2297 ANGLE_GL_PROGRAM(prog, vert, frag);
2298 drawQuad(prog.get(), "position", 0.5f);
2299 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2300}
2301
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002302// Convers a bug with the unary minus operator on signed integer workaround.
2303TEST_P(GLSLTest_ES3, UnaryMinusOperatorSignedInt)
2304{
2305 const std::string &vert =
2306 "#version 300 es\n"
2307 "in highp vec4 position;\n"
2308 "out mediump vec4 v_color;\n"
2309 "uniform int ui_one;\n"
2310 "uniform int ui_two;\n"
2311 "uniform int ui_three;\n"
2312 "void main() {\n"
2313 " int s[3];\n"
2314 " s[0] = ui_one;\n"
2315 " s[1] = -(-(-ui_two + 1) + 1);\n" // s[1] = -ui_two
2316 " s[2] = ui_three;\n"
2317 " int result = 0;\n"
2318 " for (int i = 0; i < ui_three; i++) {\n"
2319 " result += s[i];\n"
2320 " }\n"
2321 " v_color = (result == 2) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
2322 " gl_Position = position;\n"
2323 "}\n";
2324 const std::string &frag =
2325 "#version 300 es\n"
2326 "in mediump vec4 v_color;\n"
2327 "layout(location=0) out mediump vec4 o_color;\n"
2328 "void main() {\n"
2329 " o_color = v_color;\n"
2330 "}\n";
2331
2332 ANGLE_GL_PROGRAM(prog, vert, frag);
2333
Jamie Madille1faacb2016-12-13 12:42:14 -05002334 GLint oneIndex = glGetUniformLocation(prog.get(), "ui_one");
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002335 ASSERT_NE(-1, oneIndex);
Jamie Madille1faacb2016-12-13 12:42:14 -05002336 GLint twoIndex = glGetUniformLocation(prog.get(), "ui_two");
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002337 ASSERT_NE(-1, twoIndex);
Jamie Madille1faacb2016-12-13 12:42:14 -05002338 GLint threeIndex = glGetUniformLocation(prog.get(), "ui_three");
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002339 ASSERT_NE(-1, threeIndex);
2340 glUseProgram(prog.get());
2341 glUniform1i(oneIndex, 1);
2342 glUniform1i(twoIndex, 2);
2343 glUniform1i(threeIndex, 3);
2344
2345 drawQuad(prog.get(), "position", 0.5f);
2346 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2347}
2348
2349// Convers a bug with the unary minus operator on unsigned integer workaround.
2350TEST_P(GLSLTest_ES3, UnaryMinusOperatorUnsignedInt)
2351{
2352 const std::string &vert =
2353 "#version 300 es\n"
2354 "in highp vec4 position;\n"
2355 "out mediump vec4 v_color;\n"
2356 "uniform uint ui_one;\n"
2357 "uniform uint ui_two;\n"
2358 "uniform uint ui_three;\n"
2359 "void main() {\n"
2360 " uint s[3];\n"
2361 " s[0] = ui_one;\n"
2362 " s[1] = -(-(-ui_two + 1u) + 1u);\n" // s[1] = -ui_two
2363 " s[2] = ui_three;\n"
2364 " uint result = 0u;\n"
2365 " for (uint i = 0u; i < ui_three; i++) {\n"
2366 " result += s[i];\n"
2367 " }\n"
2368 " v_color = (result == 2u) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
2369 " gl_Position = position;\n"
2370 "}\n";
2371 const std::string &frag =
2372 "#version 300 es\n"
2373 "in mediump vec4 v_color;\n"
2374 "layout(location=0) out mediump vec4 o_color;\n"
2375 "void main() {\n"
2376 " o_color = v_color;\n"
2377 "}\n";
2378
2379 ANGLE_GL_PROGRAM(prog, vert, frag);
2380
Jamie Madille1faacb2016-12-13 12:42:14 -05002381 GLint oneIndex = glGetUniformLocation(prog.get(), "ui_one");
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002382 ASSERT_NE(-1, oneIndex);
Jamie Madille1faacb2016-12-13 12:42:14 -05002383 GLint twoIndex = glGetUniformLocation(prog.get(), "ui_two");
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002384 ASSERT_NE(-1, twoIndex);
Jamie Madille1faacb2016-12-13 12:42:14 -05002385 GLint threeIndex = glGetUniformLocation(prog.get(), "ui_three");
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002386 ASSERT_NE(-1, threeIndex);
2387 glUseProgram(prog.get());
2388 glUniform1ui(oneIndex, 1u);
2389 glUniform1ui(twoIndex, 2u);
2390 glUniform1ui(threeIndex, 3u);
2391
2392 drawQuad(prog.get(), "position", 0.5f);
2393 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2394}
2395
Olli Etuahoab481642016-08-26 12:09:10 +03002396// Test a nested sequence operator with a ternary operator inside. The ternary operator is
2397// intended to be such that it gets converted to an if statement on the HLSL backend.
2398TEST_P(GLSLTest, NestedSequenceOperatorWithTernaryInside)
2399{
2400 const std::string &vert =
2401 "attribute vec2 position;\n"
2402 "void main()\n"
2403 "{\n"
2404 " gl_Position = vec4(position, 0, 1);\n"
2405 "}";
2406
2407 // Note that the uniform keep_flop_positive doesn't need to be set - the test expects it to have
2408 // its default value false.
2409 const std::string &frag =
2410 "precision mediump float;\n"
2411 "uniform bool keep_flop_positive;\n"
2412 "float flop;\n"
2413 "void main() {\n"
2414 " flop = -1.0,\n"
2415 " (flop *= -1.0,\n"
2416 " keep_flop_positive ? 0.0 : flop *= -1.0),\n"
2417 " gl_FragColor = vec4(0, -flop, 0, 1);\n"
2418 "}";
2419
2420 ANGLE_GL_PROGRAM(prog, vert, frag);
2421 drawQuad(prog.get(), "position", 0.5f);
2422 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2423}
2424
Geoff Lang28a97ee2016-09-22 13:01:26 -04002425// Test that using a sampler2D and samplerExternalOES in the same shader works (anglebug.com/1534)
2426TEST_P(GLSLTest, ExternalAnd2DSampler)
2427{
2428 if (!extensionEnabled("GL_OES_EGL_image_external"))
2429 {
2430 std::cout << "Test skipped because GL_OES_EGL_image_external is not available."
2431 << std::endl;
2432 return;
2433 }
2434
2435 const std::string fragmentShader =
Olli Etuaho703671e2017-11-08 17:47:18 +02002436 R"(
2437 #extension GL_OES_EGL_image_external : enable
2438 precision mediump float;
2439 uniform samplerExternalOES tex0;
2440 uniform sampler2D tex1;
2441 void main(void)
2442 {
2443 vec2 uv = vec2(0.0, 0.0);
2444 gl_FragColor = texture2D(tex0, uv) + texture2D(tex1, uv);
2445 })";
Geoff Lang28a97ee2016-09-22 13:01:26 -04002446
2447 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2448}
2449
Olli Etuaho56a2f952016-12-08 12:16:27 +00002450// Test that literal infinity can be written out from the shader translator.
2451// A similar test can't be made for NaNs, since ESSL 3.00.6 requirements for NaNs are very loose.
2452TEST_P(GLSLTest_ES3, LiteralInfinityOutput)
2453{
2454 const std::string &fragmentShader =
2455 "#version 300 es\n"
2456 "precision highp float;\n"
2457 "out vec4 out_color;\n"
2458 "uniform float u;\n"
2459 "void main()\n"
2460 "{\n"
2461 " float infVar = 1.0e40 - u;\n"
2462 " bool correct = isinf(infVar) && infVar > 0.0;\n"
2463 " out_color = correct ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
2464 "}\n";
2465
2466 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2467 drawQuad(program.get(), "inputAttribute", 0.5f);
2468 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2469}
2470
2471// Test that literal negative infinity can be written out from the shader translator.
2472// A similar test can't be made for NaNs, since ESSL 3.00.6 requirements for NaNs are very loose.
2473TEST_P(GLSLTest_ES3, LiteralNegativeInfinityOutput)
2474{
2475 const std::string &fragmentShader =
2476 "#version 300 es\n"
2477 "precision highp float;\n"
2478 "out vec4 out_color;\n"
2479 "uniform float u;\n"
2480 "void main()\n"
2481 "{\n"
2482 " float infVar = -1.0e40 + u;\n"
2483 " bool correct = isinf(infVar) && infVar < 0.0;\n"
2484 " out_color = correct ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
2485 "}\n";
2486
2487 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2488 drawQuad(program.get(), "inputAttribute", 0.5f);
2489 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2490}
2491
Corentin Wallez36fd1002016-12-08 11:30:44 -05002492// The following MultipleDeclaration* tests are testing TranslatorHLSL specific simplification
2493// passes. Because the interaction of multiple passes must be tested, it is difficult to write
2494// a unittest for them. Instead we add the tests as end2end so will in particular test
2495// TranslatorHLSL when run on Windows.
2496
2497// Test that passes splitting multiple declarations and comma operators are correctly ordered.
2498TEST_P(GLSLTest_ES3, MultipleDeclarationWithCommaOperator)
2499{
2500 const std::string &fragmentShader =
Olli Etuaho7caa80e2017-11-14 15:03:14 +02002501 R"(#version 300 es
2502 precision mediump float;
2503 out vec4 color;
2504
2505 uniform float u;
2506 float c = 0.0;
2507 float sideEffect()
2508 {
2509 c = u;
2510 return c;
2511 }
2512
2513 void main(void)
2514 {
2515 float a = 0.0, b = ((gl_FragCoord.x < 0.5 ? a : sideEffect()), a);
2516 color = vec4(b + c);
2517 })";
Corentin Wallez36fd1002016-12-08 11:30:44 -05002518
2519 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2520}
2521
2522// Test that passes splitting multiple declarations and comma operators and for loops are
2523// correctly ordered.
2524TEST_P(GLSLTest_ES3, MultipleDeclarationWithCommaOperatorInForLoop)
2525{
2526 const std::string &fragmentShader =
Olli Etuaho7caa80e2017-11-14 15:03:14 +02002527 R"(#version 300 es
2528 precision mediump float;
2529 out vec4 color;
2530
2531 uniform float u;
2532 float c = 0.0;
2533 float sideEffect()
2534 {
2535 c = u;
2536 return c;
2537 }
2538
2539 void main(void)
2540 {
2541 for(float a = 0.0, b = ((gl_FragCoord.x < 0.5 ? a : sideEffect()), a); a < 10.0; a++)
2542 {
2543 b += 1.0;
2544 color = vec4(b);
2545 }
2546 })";
Corentin Wallez36fd1002016-12-08 11:30:44 -05002547
2548 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2549}
2550
2551// Test that splitting multiple declaration in for loops works with no loop condition
2552TEST_P(GLSLTest_ES3, MultipleDeclarationInForLoopEmptyCondition)
2553{
2554 const std::string &fragmentShader =
2555 "#version 300 es\n"
2556 "precision mediump float;\n"
2557 "out vec4 color;\n"
2558 "void main(void)\n"
2559 "{\n"
2560 " for(float a = 0.0, b = 1.0;; a++)\n"
2561 " {\n"
2562 " b += 1.0;\n"
2563 " if (a > 10.0) {break;}\n"
2564 " color = vec4(b);\n"
2565 " }\n"
2566 "}\n";
2567
2568 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2569}
2570
2571// Test that splitting multiple declaration in for loops works with no loop expression
2572TEST_P(GLSLTest_ES3, MultipleDeclarationInForLoopEmptyExpression)
2573{
2574 const std::string &fragmentShader =
2575 "#version 300 es\n"
2576 "precision mediump float;\n"
2577 "out vec4 color;\n"
2578 "void main(void)\n"
2579 "{\n"
2580 " for(float a = 0.0, b = 1.0; a < 10.0;)\n"
2581 " {\n"
2582 " b += 1.0;\n"
2583 " a += 1.0;\n"
2584 " color = vec4(b);\n"
2585 " }\n"
2586 "}\n";
2587
2588 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2589}
2590
Olli Etuaho8f6eb2a2017-01-12 17:04:58 +00002591// Test that dynamic indexing of a matrix inside a dynamic indexing of a vector in an l-value works
2592// correctly.
2593TEST_P(GLSLTest_ES3, NestedDynamicIndexingInLValue)
2594{
2595 const std::string &fragmentShader =
2596 "#version 300 es\n"
2597 "precision mediump float;\n"
2598 "out vec4 my_FragColor;\n"
2599 "uniform int u_zero;\n"
2600 "void main() {\n"
2601 " mat2 m = mat2(0.0, 0.0, 0.0, 0.0);\n"
2602 " m[u_zero + 1][u_zero + 1] = float(u_zero + 1);\n"
2603 " float f = m[1][1];\n"
2604 " my_FragColor = vec4(1.0 - f, f, 0.0, 1.0);\n"
2605 "}\n";
2606
2607 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2608 drawQuad(program.get(), "inputAttribute", 0.5f);
2609 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2610}
2611
Jamie Madill192745a2016-12-22 15:58:21 -05002612class WebGLGLSLTest : public GLSLTest
2613{
2614 protected:
2615 WebGLGLSLTest() { setWebGLCompatibilityEnabled(true); }
2616};
2617
2618TEST_P(WebGLGLSLTest, MaxVaryingVec4PlusFragCoord)
2619{
2620 GLint maxVaryings = 0;
2621 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2622
2623 // Generate shader code that uses gl_FragCoord, a special fragment shader variables.
2624 // This test should fail, since we are really using (maxVaryings + 1) varyings.
2625 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, true, false, false, false);
2626}
2627
2628TEST_P(WebGLGLSLTest, MaxVaryingVec4PlusPointCoord)
2629{
2630 GLint maxVaryings = 0;
2631 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2632
2633 // Generate shader code that uses gl_FragCoord, a special fragment shader variables.
2634 // This test should fail, since we are really using (maxVaryings + 1) varyings.
2635 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, false, true, false, false);
2636}
2637
2638TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec3)
2639{
2640 GLint maxVaryings = 0;
2641 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2642
2643 VaryingTestBase(0, 0, 0, 0, maxVaryings + 1, 0, 0, 0, false, false, false, false);
2644}
2645
2646TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec3Array)
2647{
2648 GLint maxVaryings = 0;
2649 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2650
2651 VaryingTestBase(0, 0, 0, 0, 0, maxVaryings / 2 + 1, 0, 0, false, false, false, false);
2652}
2653
2654TEST_P(WebGLGLSLTest, MaxVaryingVec3AndOneVec2)
2655{
2656 GLint maxVaryings = 0;
2657 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2658
2659 VaryingTestBase(0, 0, 1, 0, maxVaryings, 0, 0, 0, false, false, false, false);
2660}
2661
2662TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec2)
2663{
2664 GLint maxVaryings = 0;
2665 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2666
2667 VaryingTestBase(0, 0, 2 * maxVaryings + 1, 0, 0, 0, 0, 0, false, false, false, false);
2668}
2669
2670TEST_P(WebGLGLSLTest, MaxVaryingVec3ArrayAndMaxPlusOneFloatArray)
2671{
2672 GLint maxVaryings = 0;
2673 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2674
2675 VaryingTestBase(0, maxVaryings / 2 + 1, 0, 0, 0, 0, 0, maxVaryings / 2, false, false, false,
2676 false);
2677}
2678
Jamie Madill6c9503e2016-08-16 14:06:32 -04002679} // anonymous namespace
2680
Olli Etuaho9250cb22017-01-21 10:51:27 +00002681// Test that FindLSB and FindMSB return correct values in their corner cases.
2682TEST_P(GLSLTest_ES31, FindMSBAndFindLSBCornerCases)
2683{
Olli Etuaho61bd9fe2017-01-27 14:20:34 -08002684 // Suspecting AMD driver bug - failure seen on bots running on AMD R5 230.
2685 if (IsAMD() && IsOpenGL() && IsLinux())
2686 {
2687 std::cout << "Test skipped on AMD OpenGL Linux" << std::endl;
2688 return;
2689 }
2690
Yuly Novikov4e36db82018-01-19 17:35:33 -05002691 // Failing on N5X Oreo http://anglebug.com/2304
2692 ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
2693
Olli Etuaho9250cb22017-01-21 10:51:27 +00002694 const std::string &fragmentShader =
2695 "#version 310 es\n"
2696 "precision mediump float;\n"
2697 "out vec4 my_FragColor;\n"
2698 "uniform int u_zero;\n"
2699 "void main() {\n"
2700 " if (findLSB(u_zero) == -1 && findMSB(u_zero) == -1 && findMSB(u_zero - 1) == -1)\n"
2701 " {\n"
2702 " my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
2703 " }\n"
2704 " else\n"
2705 " {\n"
2706 " my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
2707 " }\n"
2708 "}\n";
2709
2710 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2711 drawQuad(program.get(), "inputAttribute", 0.5f);
2712 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2713}
2714
Olli Etuahoc9da71f2017-03-06 16:28:54 +00002715// Test that writing into a swizzled vector that is dynamically indexed succeeds.
2716TEST_P(GLSLTest_ES3, WriteIntoDynamicIndexingOfSwizzledVector)
2717{
Corentin Wallez6445ddf2017-03-08 19:00:32 -05002718 if (IsOpenGL())
Olli Etuahoc9da71f2017-03-06 16:28:54 +00002719 {
2720 // http://anglebug.com/1924
Corentin Wallez6445ddf2017-03-08 19:00:32 -05002721 std::cout << "Test skipped on all OpenGL configurations because it has incorrect results"
2722 << std::endl;
Olli Etuahoc9da71f2017-03-06 16:28:54 +00002723 return;
2724 }
2725
2726 // The shader first assigns v.x to v.z (1.0)
2727 // Then v.y to v.y (2.0)
2728 // Then v.z to v.x (1.0)
2729 const std::string &fragmentShader =
2730 "#version 300 es\n"
2731 "precision highp float;\n"
2732 "out vec4 my_FragColor;\n"
2733 "void main() {\n"
2734 " vec3 v = vec3(1.0, 2.0, 3.0);\n"
2735 " for (int i = 0; i < 3; i++) {\n"
2736 " v.zyx[i] = v[i];\n"
2737 " }\n"
2738 " my_FragColor = distance(v, vec3(1.0, 2.0, 1.0)) < 0.01 ? vec4(0, 1, 0, 1) : vec4(1, "
2739 "0, 0, 1);\n"
2740 "}\n";
2741
2742 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2743 drawQuad(program.get(), "inputAttribute", 0.5f);
2744 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2745}
2746
Jamie Madill8aeeed62017-03-15 18:09:26 -04002747// This test covers a bug (and associated workaround) with nested sampling operations in the HLSL
2748// compiler DLL.
2749TEST_P(GLSLTest_ES3, NestedSamplingOperation)
2750{
2751 // This seems to be bugged on some version of Android. Might not affect the newest versions.
2752 // TODO(jmadill): Lift suppression when Chromium bots are upgraded.
2753 if (IsAndroid() && IsOpenGLES())
2754 {
2755 std::cout << "Test skipped on Android because of bug with Nexus 5X." << std::endl;
2756 return;
2757 }
2758
2759 const std::string &vertexShader =
2760 "#version 300 es\n"
2761 "out vec2 texCoord;\n"
2762 "in vec2 position;\n"
2763 "void main()\n"
2764 "{\n"
2765 " gl_Position = vec4(position, 0, 1);\n"
2766 " texCoord = position * 0.5 + vec2(0.5);\n"
2767 "}\n";
2768
2769 const std::string &simpleFragmentShader =
2770 "#version 300 es\n"
2771 "in mediump vec2 texCoord;\n"
2772 "out mediump vec4 fragColor;\n"
2773 "void main()\n"
2774 "{\n"
2775 " fragColor = vec4(texCoord, 0, 1);\n"
2776 "}\n";
2777
2778 const std::string &nestedFragmentShader =
2779 "#version 300 es\n"
2780 "uniform mediump sampler2D samplerA;\n"
2781 "uniform mediump sampler2D samplerB;\n"
2782 "in mediump vec2 texCoord;\n"
2783 "out mediump vec4 fragColor;\n"
2784 "void main ()\n"
2785 "{\n"
2786 " fragColor = texture(samplerB, texture(samplerA, texCoord).xy);\n"
2787 "}\n";
2788
2789 ANGLE_GL_PROGRAM(initProg, vertexShader, simpleFragmentShader);
2790 ANGLE_GL_PROGRAM(nestedProg, vertexShader, nestedFragmentShader);
2791
2792 // Initialize a first texture with default texCoord data.
2793 GLTexture texA;
2794 glActiveTexture(GL_TEXTURE0);
2795 glBindTexture(GL_TEXTURE_2D, texA);
2796 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
2797 GL_UNSIGNED_BYTE, nullptr);
2798 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2799 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2800
2801 GLFramebuffer fbo;
2802 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2803 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texA, 0);
2804
2805 drawQuad(initProg, "position", 0.5f);
2806 ASSERT_GL_NO_ERROR();
2807
2808 // Initialize a second texture with a simple color pattern.
2809 GLTexture texB;
2810 glActiveTexture(GL_TEXTURE1);
2811 glBindTexture(GL_TEXTURE_2D, texB);
2812
2813 std::array<GLColor, 4> simpleColors = {
2814 {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
2815 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2816 simpleColors.data());
2817 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2818 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2819
2820 // Draw with the nested program, using the first texture to index the second.
2821 glBindFramebuffer(GL_FRAMEBUFFER, 0);
2822 glUseProgram(nestedProg);
2823 GLint samplerALoc = glGetUniformLocation(nestedProg, "samplerA");
2824 ASSERT_NE(-1, samplerALoc);
2825 glUniform1i(samplerALoc, 0);
2826 GLint samplerBLoc = glGetUniformLocation(nestedProg, "samplerB");
2827 ASSERT_NE(-1, samplerBLoc);
2828 glUniform1i(samplerBLoc, 1);
2829
2830 drawQuad(nestedProg, "position", 0.5f);
2831 ASSERT_GL_NO_ERROR();
2832
2833 // Compute four texel centers.
2834 Vector2 windowSize(getWindowWidth(), getWindowHeight());
2835 Vector2 quarterWindowSize = windowSize / 4;
2836 Vector2 ul = quarterWindowSize;
2837 Vector2 ur(windowSize.x() - quarterWindowSize.x(), quarterWindowSize.y());
2838 Vector2 ll(quarterWindowSize.x(), windowSize.y() - quarterWindowSize.y());
2839 Vector2 lr = windowSize - quarterWindowSize;
2840
2841 EXPECT_PIXEL_COLOR_EQ_VEC2(ul, simpleColors[0]);
2842 EXPECT_PIXEL_COLOR_EQ_VEC2(ur, simpleColors[1]);
2843 EXPECT_PIXEL_COLOR_EQ_VEC2(ll, simpleColors[2]);
2844 EXPECT_PIXEL_COLOR_EQ_VEC2(lr, simpleColors[3]);
2845}
2846
Olli Etuaho81629262017-04-19 11:56:01 +03002847// Tests that using a constant declaration as the only statement in a for loop without curly braces
2848// doesn't crash.
2849TEST_P(GLSLTest, ConstantStatementInForLoop)
2850{
2851 const std::string &vertexShader =
2852 "void main()\n"
2853 "{\n"
2854 " for (int i = 0; i < 10; ++i)\n"
2855 " const int b = 0;\n"
2856 "}\n";
2857
2858 GLuint shader = CompileShader(GL_VERTEX_SHADER, vertexShader);
2859 EXPECT_NE(0u, shader);
2860 glDeleteShader(shader);
2861}
2862
2863// Tests that using a constant declaration as a loop init expression doesn't crash. Note that this
2864// test doesn't work on D3D9 due to looping limitations, so it is only run on ES3.
2865TEST_P(GLSLTest_ES3, ConstantStatementAsLoopInit)
2866{
2867 const std::string &vertexShader =
2868 "void main()\n"
2869 "{\n"
2870 " for (const int i = 0; i < 0;) {}\n"
2871 "}\n";
2872
2873 GLuint shader = CompileShader(GL_VERTEX_SHADER, vertexShader);
2874 EXPECT_NE(0u, shader);
2875 glDeleteShader(shader);
2876}
2877
Olli Etuaho9733cee2017-05-11 19:14:35 +03002878// Test that uninitialized local variables are initialized to 0.
2879TEST_P(GLSLTest_ES3, InitUninitializedLocals)
2880{
2881 if (IsAndroid() && IsOpenGLES())
2882 {
2883 // http://anglebug.com/2046
2884 std::cout
2885 << "Test skipped on Android GLES because local variable initialization is disabled."
2886 << std::endl;
2887 return;
2888 }
2889
Olli Etuaho9733cee2017-05-11 19:14:35 +03002890 const std::string &fragmentShader =
2891 "#version 300 es\n"
2892 "precision mediump float;\n"
2893 "out vec4 my_FragColor;\n"
2894 "int result = 0;\n"
2895 "void main()\n"
2896 "{\n"
2897 " int u;\n"
2898 " result += u;\n"
2899 " int k = 0;\n"
2900 " for (int i[2], j = i[0] + 1; k < 2; ++k)\n"
2901 " {\n"
2902 " result += j;\n"
2903 " }\n"
2904 " if (result == 2)\n"
2905 " {\n"
2906 " my_FragColor = vec4(0, 1, 0, 1);\n"
2907 " }\n"
2908 " else\n"
2909 " {\n"
2910 " my_FragColor = vec4(1, 0, 0, 1);\n"
2911 " }\n"
2912 "}\n";
2913
2914 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2915 drawQuad(program.get(), "inputAttribute", 0.5f);
2916 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2917}
2918
2919// Test that uninitialized structs containing arrays of structs are initialized to 0. This
2920// specifically tests with two different struct variables declared in the same block.
2921TEST_P(GLSLTest, InitUninitializedStructContainingArrays)
2922{
2923 if (IsAndroid() && IsOpenGLES())
2924 {
2925 // http://anglebug.com/2046
2926 std::cout
2927 << "Test skipped on Android GLES because local variable initialization is disabled."
2928 << std::endl;
2929 return;
2930 }
2931
2932 if (IsOSX() && IsOpenGL())
2933 {
2934 // http://anglebug.com/2041
2935 std::cout << "Test skipped on Mac OpenGL because local variable initialization is disabled."
2936 << std::endl;
2937 return;
2938 }
2939
2940 const std::string &fragmentShader =
2941 "precision mediump float;\n"
2942 "struct T\n"
2943 "{\n"
2944 " int a[2];\n"
2945 "};\n"
2946 "struct S\n"
2947 "{\n"
2948 " T t[2];\n"
2949 "};\n"
2950 "void main()\n"
2951 "{\n"
2952 " S s;\n"
2953 " S s2;\n"
2954 " if (s.t[1].a[1] == 0 && s2.t[1].a[1] == 0)\n"
2955 " {\n"
2956 " gl_FragColor = vec4(0, 1, 0, 1);\n"
2957 " }\n"
2958 " else\n"
2959 " {\n"
2960 " gl_FragColor = vec4(1, 0, 0, 1);\n"
2961 " }\n"
2962 "}\n";
2963
2964 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2965 drawQuad(program.get(), "inputAttribute", 0.5f);
2966 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2967}
2968
Geoff Langbb1e7502017-06-05 16:40:09 -04002969// Verify that two shaders with the same uniform name and members but different structure names will
2970// not link.
2971TEST_P(GLSLTest, StructureNameMatchingTest)
2972{
2973 const char *vsSource =
2974 "// Structures must have the same name, sequence of type names, and\n"
2975 "// type definitions, and field names to be considered the same type.\n"
2976 "// GLSL 1.017 4.2.4\n"
2977 "precision mediump float;\n"
2978 "struct info {\n"
2979 " vec4 pos;\n"
2980 " vec4 color;\n"
2981 "};\n"
2982 "\n"
2983 "uniform info uni;\n"
2984 "void main()\n"
2985 "{\n"
2986 " gl_Position = uni.pos;\n"
2987 "}\n";
2988
2989 GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
2990 ASSERT_NE(0u, vs);
2991 glDeleteShader(vs);
2992
2993 const char *fsSource =
2994 "// Structures must have the same name, sequence of type names, and\n"
2995 "// type definitions, and field names to be considered the same type.\n"
2996 "// GLSL 1.017 4.2.4\n"
2997 "precision mediump float;\n"
2998 "struct info1 {\n"
2999 " vec4 pos;\n"
3000 " vec4 color;\n"
3001 "};\n"
3002 "\n"
3003 "uniform info1 uni;\n"
3004 "void main()\n"
3005 "{\n"
3006 " gl_FragColor = uni.color;\n"
3007 "}\n";
3008
3009 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
3010 ASSERT_NE(0u, fs);
3011 glDeleteShader(fs);
3012
3013 GLuint program = CompileProgram(vsSource, fsSource);
3014 EXPECT_EQ(0u, program);
3015}
3016
Olli Etuaho9733cee2017-05-11 19:14:35 +03003017// Test that an uninitialized nameless struct inside a for loop init statement works.
3018TEST_P(GLSLTest_ES3, UninitializedNamelessStructInForInitStatement)
3019{
3020 if (IsAndroid() && IsOpenGLES())
3021 {
3022 // http://anglebug.com/2046
3023 std::cout
3024 << "Test skipped on Android GLES because local variable initialization is disabled."
3025 << std::endl;
3026 return;
3027 }
3028
3029 if (IsOSX() && IsOpenGL())
3030 {
3031 // http://anglebug.com/2041
3032 std::cout << "Test skipped on Mac OpenGL because local variable initialization is disabled."
3033 << std::endl;
3034 return;
3035 }
3036
3037 const std::string &fragmentShader =
3038 "#version 300 es\n"
3039 "precision highp float;\n"
3040 "out vec4 my_FragColor;\n"
3041 "void main()\n"
3042 "{\n"
3043 " my_FragColor = vec4(1, 0, 0, 1);\n"
3044 " for (struct { float q; } b; b.q < 2.0; b.q++) {\n"
3045 " my_FragColor = vec4(0, 1, 0, 1);\n"
3046 " }\n"
3047 "}\n";
3048
3049 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3050 drawQuad(program.get(), "inputAttribute", 0.5f);
3051 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3052}
3053
Olli Etuaho0ffc4412017-05-19 14:18:55 +03003054// Test that uninitialized global variables are initialized to 0.
3055TEST_P(WebGLGLSLTest, InitUninitializedGlobals)
3056{
3057 const std::string &fragmentShader =
3058 "precision mediump float;\n"
3059 "int result;\n"
3060 "int i[2], j = i[0] + 1;\n"
3061 "void main()\n"
3062 "{\n"
3063 " result += j;\n"
3064 " if (result == 1)\n"
3065 " {\n"
3066 " gl_FragColor = vec4(0, 1, 0, 1);\n"
3067 " }\n"
3068 " else\n"
3069 " {\n"
3070 " gl_FragColor = vec4(1, 0, 0, 1);\n"
3071 " }\n"
3072 "}\n";
3073
3074 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3075 drawQuad(program.get(), "inputAttribute", 0.5f, 1.0f, true);
3076 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3077}
3078
3079// Test that an uninitialized nameless struct in the global scope works.
3080TEST_P(WebGLGLSLTest, UninitializedNamelessStructInGlobalScope)
3081{
3082 const std::string &fragmentShader =
3083 "precision mediump float;\n"
3084 "struct { float q; } b;\n"
3085 "void main()\n"
3086 "{\n"
3087 " gl_FragColor = vec4(1, 0, 0, 1);\n"
3088 " if (b.q == 0.0)\n"
3089 " {\n"
3090 " gl_FragColor = vec4(0, 1, 0, 1);\n"
3091 " }\n"
3092 "}\n";
3093
3094 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3095 drawQuad(program.get(), "inputAttribute", 0.5f, 1.0f, true);
3096 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3097}
3098
Olli Etuaho914b79a2017-06-19 16:03:19 +03003099// Test that a loop condition that has an initializer declares a variable.
3100TEST_P(GLSLTest_ES3, ConditionInitializerDeclaresVariable)
3101{
3102 const std::string &fragmentShader =
3103 "#version 300 es\n"
3104 "precision highp float;\n"
3105 "out vec4 my_FragColor;\n"
3106 "void main()\n"
3107 "{\n"
3108 " float i = 0.0;\n"
3109 " while (bool foo = (i < 1.5))\n"
3110 " {\n"
3111 " if (!foo)\n"
3112 " {\n"
3113 " ++i;\n"
3114 " }\n"
3115 " if (i > 3.5)\n"
3116 " {\n"
3117 " break;\n"
3118 " }\n"
3119 " ++i;\n"
3120 " }\n"
3121 " my_FragColor = vec4(i * 0.5 - 1.0, i * 0.5, 0.0, 1.0);\n"
3122 "}\n";
3123
3124 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3125 drawQuad(program.get(), "inputAttribute", 0.5f);
3126 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3127}
3128
Olli Etuahoff526f12017-06-30 12:26:54 +03003129// Test that a variable hides a user-defined function with the same name after its initializer.
3130// GLSL ES 1.00.17 section 4.2.2: "A variable declaration is visible immediately following the
3131// initializer if present, otherwise immediately following the identifier"
3132TEST_P(GLSLTest, VariableHidesUserDefinedFunctionAfterInitializer)
3133{
3134 const std::string &fragmentShader =
3135 "precision mediump float;\n"
3136 "uniform vec4 u;\n"
3137 "vec4 foo()\n"
3138 "{\n"
3139 " return u;\n"
3140 "}\n"
3141 "void main()\n"
3142 "{\n"
3143 " vec4 foo = foo();\n"
3144 " gl_FragColor = foo + vec4(0, 1, 0, 1);\n"
3145 "}\n";
3146
3147 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3148 drawQuad(program.get(), "inputAttribute", 0.5f);
3149 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3150}
3151
Olli Etuaho088031e2017-07-03 15:59:33 +03003152// Test that structs with identical members are not ambiguous as function arguments.
3153TEST_P(GLSLTest, StructsWithSameMembersDisambiguatedByName)
3154{
3155 const std::string &fragmentShader =
3156 "precision mediump float;\n"
3157 "uniform float u_zero;\n"
3158 "struct S { float foo; };\n"
3159 "struct S2 { float foo; };\n"
3160 "float get(S s) { return s.foo + u_zero; }\n"
3161 "float get(S2 s2) { return 0.25 + s2.foo + u_zero; }\n"
3162 "void main()\n"
3163 "{\n"
3164 " S s;\n"
3165 " s.foo = 0.5;\n"
3166 " S2 s2;\n"
3167 " s2.foo = 0.25;\n"
3168 " gl_FragColor = vec4(0.0, get(s) + get(s2), 0.0, 1.0);\n"
3169 "}\n";
3170
3171 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3172 drawQuad(program.get(), "inputAttribute", 0.5f);
3173 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3174}
3175
Olli Etuaho06a06f52017-07-12 12:22:15 +03003176// Test that a varying struct that's not statically used in the fragment shader works.
3177// GLSL ES 3.00.6 section 4.3.10.
3178TEST_P(GLSLTest_ES3, VaryingStructNotStaticallyUsedInFragmentShader)
3179{
3180 const std::string &vertexShader =
3181 "#version 300 es\n"
3182 "struct S {\n"
3183 " vec4 field;\n"
3184 "};\n"
3185 "out S varStruct;\n"
3186 "void main()\n"
3187 "{\n"
3188 " gl_Position = vec4(1.0);\n"
3189 " varStruct.field = vec4(0.0, 0.5, 0.0, 0.0);\n"
3190 "}\n";
3191
3192 const std::string &fragmentShader =
3193 "#version 300 es\n"
3194 "precision mediump float;\n"
3195 "struct S {\n"
3196 " vec4 field;\n"
3197 "};\n"
3198 "in S varStruct;\n"
3199 "out vec4 col;\n"
3200 "void main()\n"
3201 "{\n"
3202 " col = vec4(1.0);\n"
3203 "}\n";
3204
3205 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3206}
3207
3208// Test that a varying struct that's not declared in the fragment shader links successfully.
3209// GLSL ES 3.00.6 section 4.3.10.
3210TEST_P(GLSLTest_ES3, VaryingStructNotDeclaredInFragmentShader)
3211{
3212 const std::string &vertexShader =
3213 "#version 300 es\n"
3214 "struct S {\n"
3215 " vec4 field;\n"
3216 "};\n"
3217 "out S varStruct;\n"
3218 "void main()\n"
3219 "{\n"
3220 " gl_Position = vec4(1.0);\n"
3221 " varStruct.field = vec4(0.0, 0.5, 0.0, 0.0);\n"
3222 "}\n";
3223
3224 const std::string &fragmentShader =
3225 "#version 300 es\n"
3226 "precision mediump float;\n"
3227 "out vec4 col;\n"
3228 "void main()\n"
3229 "{\n"
3230 " col = vec4(1.0);\n"
3231 "}\n";
3232
3233 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3234}
3235
3236// Test that a varying struct that gets used in the fragment shader works.
3237TEST_P(GLSLTest_ES3, VaryingStructUsedInFragmentShader)
3238{
3239 const std::string &vertexShader =
3240 "#version 300 es\n"
3241 "in vec4 inputAttribute;\n"
3242 "struct S {\n"
3243 " vec4 field;\n"
3244 "};\n"
3245 "out S varStruct;\n"
3246 "void main()\n"
3247 "{\n"
3248 " gl_Position = inputAttribute;\n"
3249 " varStruct.field = vec4(0.0, 1.0, 0.0, 1.0);\n"
3250 "}\n";
3251
3252 const std::string &fragmentShader =
3253 "#version 300 es\n"
3254 "precision mediump float;\n"
3255 "out vec4 col;\n"
3256 "struct S {\n"
3257 " vec4 field;\n"
3258 "};\n"
3259 "in S varStruct;\n"
3260 "void main()\n"
3261 "{\n"
3262 " col = varStruct.field;\n"
3263 "}\n";
3264
3265 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3266 drawQuad(program.get(), "inputAttribute", 0.5f);
3267 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3268}
3269
Olli Etuaho3860b6c2017-07-19 16:17:24 +03003270// This test covers passing an array of structs containing samplers as a function argument.
3271TEST_P(GLSLTest, ArrayOfStructsWithSamplersAsFunctionArg)
3272{
3273 if (IsAndroid() && IsAdreno() && IsOpenGLES())
3274 {
3275 // Shader failed to compile on Android. http://anglebug.com/2114
3276 std::cout << "Test skipped on Adreno OpenGLES on Android." << std::endl;
3277 return;
3278 }
3279
3280 const std::string &vertexShader =
3281 "attribute vec2 position;\n"
3282 "void main()\n"
3283 "{\n"
3284 " gl_Position = vec4(position, 0, 1);\n"
3285 "}\n";
3286
3287 const std::string &fragmentShader =
3288 "precision mediump float;\n"
3289 "struct S\n"
3290 "{\n"
3291 " sampler2D samplerMember; \n"
3292 "};\n"
3293 "uniform S uStructs[2];\n"
3294 "uniform vec2 uTexCoord;\n"
3295 "\n"
3296 "vec4 foo(S[2] structs)\n"
3297 "{\n"
3298 " return texture2D(structs[0].samplerMember, uTexCoord);\n"
3299 "}\n"
3300 "void main()\n"
3301 "{\n"
3302 " gl_FragColor = foo(uStructs);\n"
3303 "}\n";
3304
3305 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3306
3307 // Initialize the texture with green.
3308 GLTexture tex;
3309 glActiveTexture(GL_TEXTURE0);
3310 glBindTexture(GL_TEXTURE_2D, tex);
3311 GLubyte texData[] = {0u, 255u, 0u, 255u};
3312 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
3313 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3314 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3315 ASSERT_GL_NO_ERROR();
3316
3317 // Draw
3318 glUseProgram(program);
3319 GLint samplerMemberLoc = glGetUniformLocation(program, "uStructs[0].samplerMember");
3320 ASSERT_NE(-1, samplerMemberLoc);
3321 glUniform1i(samplerMemberLoc, 0);
3322 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
3323 ASSERT_NE(-1, texCoordLoc);
3324 glUniform2f(texCoordLoc, 0.5f, 0.5f);
3325
3326 drawQuad(program, "position", 0.5f);
3327 ASSERT_GL_NO_ERROR();
3328
3329 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
3330}
3331
Olli Etuaho28839f02017-08-15 11:38:16 +03003332// This test covers passing a struct containing an array of samplers as a function argument.
3333TEST_P(GLSLTest, StructWithSamplerArrayAsFunctionArg)
3334{
3335 if (IsAndroid() && IsAdreno() && IsOpenGLES())
3336 {
3337 // Shader failed to compile on Android. http://anglebug.com/2114
3338 std::cout << "Test skipped on Adreno OpenGLES on Android." << std::endl;
3339 return;
3340 }
3341
3342 const std::string &vertexShader =
3343 "attribute vec2 position;\n"
3344 "void main()\n"
3345 "{\n"
3346 " gl_Position = vec4(position, 0, 1);\n"
3347 "}\n";
3348
3349 const std::string &fragmentShader =
3350 "precision mediump float;\n"
3351 "struct S\n"
3352 "{\n"
3353 " sampler2D samplerMembers[2];\n"
3354 "};\n"
3355 "uniform S uStruct;\n"
3356 "uniform vec2 uTexCoord;\n"
3357 "\n"
3358 "vec4 foo(S str)\n"
3359 "{\n"
3360 " return texture2D(str.samplerMembers[0], uTexCoord);\n"
3361 "}\n"
3362 "void main()\n"
3363 "{\n"
3364 " gl_FragColor = foo(uStruct);\n"
3365 "}\n";
3366
3367 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3368
3369 // Initialize the texture with green.
3370 GLTexture tex;
3371 glActiveTexture(GL_TEXTURE0);
3372 glBindTexture(GL_TEXTURE_2D, tex);
3373 GLubyte texData[] = {0u, 255u, 0u, 255u};
3374 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
3375 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3376 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3377 ASSERT_GL_NO_ERROR();
3378
3379 // Draw
3380 glUseProgram(program);
3381 GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMembers[0]");
3382 ASSERT_NE(-1, samplerMemberLoc);
3383 glUniform1i(samplerMemberLoc, 0);
3384 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
3385 ASSERT_NE(-1, texCoordLoc);
3386 glUniform2f(texCoordLoc, 0.5f, 0.5f);
3387
3388 drawQuad(program, "position", 0.5f);
3389 ASSERT_GL_NO_ERROR();
3390
3391 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
3392}
3393
Olli Etuahoa16a84f2017-09-12 13:49:18 +03003394// Test that a global variable declared after main() works. This is a regression test for an issue
3395// in global variable initialization.
3396TEST_P(WebGLGLSLTest, GlobalVariableDeclaredAfterMain)
3397{
3398 const std::string &fragmentShader =
3399 "precision mediump float;\n"
3400 "int getFoo();\n"
3401 "uniform int u_zero;\n"
3402 "void main()\n"
3403 "{\n"
3404 " gl_FragColor = vec4(1, 0, 0, 1);\n"
3405 " if (getFoo() == 0)\n"
3406 " {\n"
3407 " gl_FragColor = vec4(0, 1, 0, 1);\n"
3408 " }\n"
3409 "}\n"
3410 "int foo;\n"
3411 "int getFoo()\n"
3412 "{\n"
3413 " foo = u_zero;\n"
3414 " return foo;\n"
3415 "}\n";
3416
3417 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3418 drawQuad(program.get(), "inputAttribute", 0.5f, 1.0f, true);
3419 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3420}
3421
Olli Etuahobb5a7e22017-08-30 13:03:12 +03003422// Test calling array length() with a "this" expression having side effects inside a loop condition.
3423// The spec says that sequence operator operands need to run in sequence.
3424TEST_P(GLSLTest_ES3, ArrayLengthOnExpressionWithSideEffectsInLoopCondition)
3425{
3426 // "a" gets doubled three times in the below program.
3427 const std::string &fragmentShader =
3428 R"(#version 300 es
3429 precision highp float;
3430 out vec4 my_FragColor;
3431 uniform int u_zero;
3432 int a;
3433 int[2] doubleA()
3434 {
3435 a *= 2;
3436 return int[2](a, a);
3437 }
3438 void main()
3439 {
3440 a = u_zero + 1;
3441 for (int i = 0; i < doubleA().length(); ++i)
3442 {}
3443 if (a == 8)
3444 {
3445 my_FragColor = vec4(0, 1, 0, 1);
3446 }
3447 else
3448 {
3449 my_FragColor = vec4(1, 0, 0, 1);
3450 }
3451 })";
3452
3453 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3454 drawQuad(program.get(), "inputAttribute", 0.5f);
3455 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3456}
3457
3458// Test calling array length() with a "this" expression having side effects that interact with side
3459// effects of another operand of the same sequence operator. The spec says that sequence operator
3460// operands need to run in order from left to right (ESSL 3.00.6 section 5.9).
3461TEST_P(GLSLTest_ES3, ArrayLengthOnExpressionWithSideEffectsInSequence)
3462{
3463 const std::string &fragmentShader =
3464 R"(#version 300 es
3465 precision highp float;
3466 out vec4 my_FragColor;
3467 uniform int u_zero;
3468 int a;
3469 int[3] doubleA()
3470 {
3471 a *= 2;
3472 return int[3](a, a, a);
3473 }
3474 void main()
3475 {
3476 a = u_zero;
3477 int b = (a++, doubleA().length());
3478 if (b == 3 && a == 2)
3479 {
3480 my_FragColor = vec4(0, 1, 0, 1);
3481 }
3482 else
3483 {
3484 my_FragColor = vec4(1, 0, 0, 1);
3485 }
3486 })";
3487
3488 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3489 drawQuad(program.get(), "inputAttribute", 0.5f);
3490 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3491}
3492
3493// Test calling array length() with a "this" expression that also contains a call of array length().
3494// Both "this" expressions also have side effects.
3495TEST_P(GLSLTest_ES3, NestedArrayLengthMethodsWithSideEffects)
3496{
3497 const std::string &fragmentShader =
3498 R"(#version 300 es
3499 precision highp float;
3500 out vec4 my_FragColor;
3501 uniform int u_zero;
3502 int a;
3503 int[3] multiplyA(int multiplier)
3504 {
3505 a *= multiplier;
3506 return int[3](a, a, a);
3507 }
3508 void main()
3509 {
3510 a = u_zero + 1;
3511 int b = multiplyA(multiplyA(2).length()).length();
3512 if (b == 3 && a == 6)
3513 {
3514 my_FragColor = vec4(0, 1, 0, 1);
3515 }
3516 else
3517 {
3518 my_FragColor = vec4(1, 0, 0, 1);
3519 }
3520 })";
3521
3522 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3523 drawQuad(program.get(), "inputAttribute", 0.5f);
3524 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3525}
3526
Olli Etuaho78507c62017-10-10 15:06:45 +03003527// Test that statements inside switch() get translated to correct HLSL.
3528TEST_P(GLSLTest_ES3, DifferentStatementsInsideSwitch)
3529{
3530 const std::string &fragmentShader =
3531 R"(#version 300 es
3532
3533 precision highp float;
3534
3535 uniform int u;
3536
3537 void main()
3538 {
3539 switch (u)
3540 {
3541 case 0:
3542 ivec2 i;
3543 i.yx;
3544 }
3545 })";
3546 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3547}
3548
Olli Etuaho852fe872017-10-10 15:13:59 +03003549// Test that switch fall-through works correctly.
3550// This is a regression test for http://anglebug.com/2178
3551TEST_P(GLSLTest_ES3, SwitchFallThroughCodeDuplication)
3552{
3553 const std::string &fragmentShader =
3554 R"(#version 300 es
3555
3556 precision highp float;
3557
3558 out vec4 my_FragColor;
3559
3560 uniform int u_zero;
3561
3562 void main()
3563 {
3564 int i = 0;
3565 // switch should fall through both cases.
3566 switch(u_zero)
3567 {
3568 case 0:
3569 i += 1;
3570 case 1:
3571 i += 2;
3572 }
3573 if (i == 3)
3574 {
3575 my_FragColor = vec4(0, 1, 0, 1);
3576 }
3577 else
3578 {
3579 my_FragColor = vec4(1, 0, 0, 1);
3580 }
3581 })";
3582
3583 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3584 drawQuad(program.get(), "inputAttribute", 0.5f);
3585 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3586}
3587
Olli Etuaho923ecef2017-10-11 12:01:38 +03003588// Test that a switch statement with an empty block inside as a final statement compiles.
3589TEST_P(GLSLTest_ES3, SwitchFinalCaseHasEmptyBlock)
3590{
3591 const std::string &fragmentShader =
3592 R"(#version 300 es
3593
3594 precision mediump float;
3595 uniform int i;
3596 void main()
3597 {
3598 switch (i)
3599 {
3600 case 0:
3601 break;
3602 default:
3603 {}
3604 }
3605 })";
3606 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3607}
3608
3609// Test that a switch statement with an empty declaration inside as a final statement compiles.
3610TEST_P(GLSLTest_ES3, SwitchFinalCaseHasEmptyDeclaration)
3611{
3612 const std::string &fragmentShader =
3613 R"(#version 300 es
3614
3615 precision mediump float;
3616 uniform int i;
3617 void main()
3618 {
3619 switch (i)
3620 {
3621 case 0:
3622 break;
3623 default:
3624 float;
3625 }
3626 })";
3627 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3628}
3629
Olli Etuaho4bd730c2017-10-10 14:14:19 +03003630// Test switch/case where break/return statements are within blocks.
3631TEST_P(GLSLTest_ES3, SwitchBreakOrReturnInsideBlocks)
3632{
3633 const std::string &fragmentShader =
3634 R"(#version 300 es
3635
3636 precision highp float;
3637
3638 uniform int u_zero;
3639 out vec4 my_FragColor;
3640
3641 bool test(int n)
3642 {
3643 switch(n) {
3644 case 0:
3645 {
3646 {
3647 break;
3648 }
3649 }
3650 case 1:
3651 {
3652 return true;
3653 }
3654 case 2:
3655 {
3656 n++;
3657 }
3658 }
3659 return false;
3660 }
3661
3662 void main()
3663 {
3664 my_FragColor = test(u_zero + 1) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
3665 })";
3666
3667 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3668 drawQuad(program.get(), "inputAttribute", 0.5f);
3669 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3670}
3671
Olli Etuahof6d242e2017-10-12 17:21:06 +03003672// Test switch/case where a variable is declared inside one of the cases and is accessed by a
3673// subsequent case.
3674TEST_P(GLSLTest_ES3, SwitchWithVariableDeclarationInside)
3675{
3676 const std::string &fragmentShader =
3677 R"(#version 300 es
3678
3679 precision highp float;
3680 out vec4 my_FragColor;
3681
3682 uniform int u_zero;
3683
3684 void main()
3685 {
3686 my_FragColor = vec4(1, 0, 0, 1);
3687 switch (u_zero)
3688 {
3689 case 0:
3690 ivec2 i;
3691 i = ivec2(1, 0);
3692 default:
3693 my_FragColor = vec4(0, i[0], 0, 1);
3694 }
3695 })";
3696
3697 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3698 drawQuad(program.get(), "inputAttribute", 0.5f);
3699 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3700}
3701
3702// Test nested switch/case where a variable is declared inside one of the cases and is accessed by a
3703// subsequent case.
3704TEST_P(GLSLTest_ES3, NestedSwitchWithVariableDeclarationInside)
3705{
3706 const std::string &fragmentShader =
3707 R"(#version 300 es
3708
3709 precision highp float;
3710 out vec4 my_FragColor;
3711
3712 uniform int u_zero;
3713 uniform int u_zero2;
3714
3715 void main()
3716 {
3717 my_FragColor = vec4(1, 0, 0, 1);
3718 switch (u_zero)
3719 {
3720 case 0:
3721 ivec2 i;
3722 i = ivec2(1, 0);
3723 switch (u_zero2)
3724 {
3725 case 0:
3726 int j;
3727 default:
3728 j = 1;
3729 i *= j;
3730 }
3731 default:
3732 my_FragColor = vec4(0, i[0], 0, 1);
3733 }
3734 })";
3735
3736 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3737 drawQuad(program.get(), "inputAttribute", 0.5f);
3738 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3739}
3740
Olli Etuahoc1f14fb2017-10-28 19:17:23 +03003741// Test that an empty switch/case statement is translated in a way that compiles and executes the
3742// init-statement.
3743TEST_P(GLSLTest_ES3, EmptySwitch)
3744{
3745 const std::string &fragmentShader =
3746 R"(#version 300 es
3747
3748 precision highp float;
3749
3750 uniform int u_zero;
3751 out vec4 my_FragColor;
3752
3753 void main()
3754 {
3755 int i = u_zero;
3756 switch(++i) {}
3757 my_FragColor = (i == 1) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
3758 })";
3759
3760 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3761 drawQuad(program.get(), "inputAttribute", 0.5f);
3762 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3763}
3764
Olli Etuahobd3cd502017-11-03 15:48:52 +02003765// Test that a constant struct inside an expression is handled correctly.
3766TEST_P(GLSLTest_ES3, ConstStructInsideExpression)
3767{
3768 // Incorrect output color was seen on Android. http://anglebug.com/2226
3769 ANGLE_SKIP_TEST_IF(IsAndroid() && !IsNVIDIA() && IsOpenGLES());
3770
3771 const std::string &fragmentShader =
3772 R"(#version 300 es
3773
3774 precision highp float;
3775 out vec4 my_FragColor;
3776
3777 uniform float u_zero;
3778
3779 struct S
3780 {
3781 float field;
3782 };
3783
3784 void main()
3785 {
3786 const S constS = S(1.0);
3787 S nonConstS = constS;
3788 nonConstS.field = u_zero;
3789 bool fail = (constS == nonConstS);
3790 my_FragColor = vec4(0, 1, 0, 1);
3791 if (fail)
3792 {
3793 my_FragColor = vec4(1, 0, 0, 1);
3794 }
3795 })";
3796
3797 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3798 drawQuad(program.get(), "inputAttribute", 0.5f);
3799 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3800}
3801
3802// Test that a varying struct that's defined as a part of the declaration is handled correctly.
3803TEST_P(GLSLTest_ES3, VaryingStructWithInlineDefinition)
3804{
3805 const std::string &vertexShader =
3806 R"(#version 300 es
3807 in vec4 inputAttribute;
3808
3809 flat out struct S
3810 {
3811 int field;
3812 } v_s;
3813
3814 void main()
3815 {
3816 v_s.field = 1;
3817 gl_Position = inputAttribute;
3818 })";
3819
3820 const std::string &fragmentShader =
3821 R"(#version 300 es
3822
3823 precision highp float;
3824 out vec4 my_FragColor;
3825
3826 flat in struct S
3827 {
3828 int field;
3829 } v_s;
3830
3831 void main()
3832 {
3833 bool success = (v_s.field == 1);
3834 my_FragColor = vec4(1, 0, 0, 1);
3835 if (success)
3836 {
3837 my_FragColor = vec4(0, 1, 0, 1);
3838 }
3839 })";
3840
3841 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3842 drawQuad(program.get(), "inputAttribute", 0.5f);
3843 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3844}
3845
Olli Etuaho661fc482017-10-16 12:17:05 +03003846// Test vector/scalar arithmetic (in this case multiplication and addition). Meant to reproduce a
3847// bug that appeared in NVIDIA OpenGL drivers and that is worked around by
3848// VectorizeVectorScalarArithmetic AST transform.
3849TEST_P(GLSLTest, VectorScalarMultiplyAndAddInLoop)
3850{
3851 const std::string &fragmentShader =
3852 R"(
3853
3854 precision mediump float;
3855
3856 void main() {
3857 gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
3858 for (int i = 0; i < 2; i++)
3859 {
3860 gl_FragColor += (2.0 * gl_FragCoord.x);
3861 }
3862 if (gl_FragColor.g == gl_FragColor.r &&
3863 gl_FragColor.b == gl_FragColor.r &&
3864 gl_FragColor.a == gl_FragColor.r)
3865 {
3866 gl_FragColor = vec4(0, 1, 0, 1);
3867 }
3868 })";
3869
3870 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3871 drawQuad(program.get(), "inputAttribute", 0.5f);
3872 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3873}
3874
3875// Test vector/scalar arithmetic (in this case compound division and addition). Meant to reproduce a
3876// bug that appeared in NVIDIA OpenGL drivers and that is worked around by
3877// VectorizeVectorScalarArithmetic AST transform.
3878TEST_P(GLSLTest, VectorScalarDivideAndAddInLoop)
3879{
3880 const std::string &fragmentShader =
3881 R"(
3882
3883 precision mediump float;
3884
3885 void main() {
3886 gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
3887 for (int i = 0; i < 2; i++)
3888 {
3889 float x = gl_FragCoord.x;
3890 gl_FragColor = gl_FragColor + (x /= 2.0);
3891 }
3892 if (gl_FragColor.g == gl_FragColor.r &&
3893 gl_FragColor.b == gl_FragColor.r &&
3894 gl_FragColor.a == gl_FragColor.r)
3895 {
3896 gl_FragColor = vec4(0, 1, 0, 1);
3897 }
3898 })";
3899
3900 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3901 drawQuad(program.get(), "inputAttribute", 0.5f);
3902 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3903}
3904
Olli Etuahob8cb9392017-12-20 14:23:19 +02003905// Test that a varying with a flat qualifier that is used as an operand of a folded ternary operator
3906// is handled correctly.
3907TEST_P(GLSLTest_ES3, FlatVaryingUsedInFoldedTernary)
3908{
3909 const std::string &vertexShader =
3910 R"(#version 300 es
3911
3912 in vec4 inputAttribute;
3913
3914 flat out int v;
3915
3916 void main()
3917 {
3918 v = 1;
3919 gl_Position = inputAttribute;
3920 })";
3921
3922 const std::string &fragmentShader =
3923 R"(#version 300 es
3924
3925 precision highp float;
3926 out vec4 my_FragColor;
3927
3928 flat in int v;
3929
3930 void main()
3931 {
3932 my_FragColor = vec4(0, (true ? v : 0), 0, 1);
3933 })";
3934
3935 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3936 drawQuad(program.get(), "inputAttribute", 0.5f);
3937 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3938}
3939
Jiawei Shao02f15232017-12-27 10:10:28 +08003940// Verify that the link error message from last link failure is cleared when the new link is
3941// finished.
3942TEST_P(GLSLTest, ClearLinkErrorLog)
3943{
3944 const std::string &vertexShader =
3945 R"(
3946
3947 attribute vec4 vert_in;
3948 varying vec4 vert_out;
3949 void main()
3950 {
3951 gl_Position = vert_in;
3952 vert_out = vert_in;
3953 })";
3954
3955 const std::string &fragmentShader =
3956 R"(
3957
3958 precision mediump float;
3959 varying vec4 frag_in;
3960 void main()
3961 {
3962 gl_FragColor = frag_in;
3963 })";
3964
3965 GLuint vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
3966 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);
3967
3968 GLuint program = glCreateProgram();
3969
3970 // The first time the program link fails because of lack of fragment shader.
3971 glAttachShader(program, vs);
3972 glLinkProgram(program);
3973 GLint linkStatus = GL_TRUE;
3974 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
3975 ASSERT_FALSE(linkStatus);
3976
3977 const std::string &lackOfFragmentShader = QueryErrorMessage(program);
3978
3979 // The second time the program link fails because of the mismatch of the varying types.
3980 glAttachShader(program, fs);
3981 glLinkProgram(program);
3982 linkStatus = GL_TRUE;
3983 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
3984 ASSERT_FALSE(linkStatus);
3985
3986 const std::string &varyingTypeMismatch = QueryErrorMessage(program);
3987
3988 EXPECT_EQ(std::string::npos, varyingTypeMismatch.find(lackOfFragmentShader));
3989
3990 glDetachShader(program, vs);
3991 glDetachShader(program, fs);
3992 glDeleteShader(vs);
3993 glDeleteShader(fs);
3994 glDeleteProgram(program);
3995
3996 ASSERT_GL_NO_ERROR();
3997}
3998
Jamie Madillfa05f602015-05-07 13:47:11 -04003999// 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 -05004000ANGLE_INSTANTIATE_TEST(GLSLTest,
4001 ES2_D3D9(),
4002 ES2_D3D11(),
4003 ES2_D3D11_FL9_3(),
4004 ES2_OPENGL(),
4005 ES3_OPENGL(),
4006 ES2_OPENGLES(),
4007 ES3_OPENGLES());
Jamie Madillfa05f602015-05-07 13:47:11 -04004008
4009// 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 -05004010ANGLE_INSTANTIATE_TEST(GLSLTest_ES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
Jamie Madill192745a2016-12-22 15:58:21 -05004011
4012ANGLE_INSTANTIATE_TEST(WebGLGLSLTest, ES2_D3D11(), ES2_OPENGL(), ES2_OPENGLES());
Olli Etuaho9250cb22017-01-21 10:51:27 +00004013
4014ANGLE_INSTANTIATE_TEST(GLSLTest_ES31, ES31_D3D11(), ES31_OPENGL(), ES31_OPENGLES());