blob: e25457734667eab22207420c3388274470163306 [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
Jamie Madill2bf8b372014-06-16 17:18:51 -040033 mSimpleVSSource = SHADER_SOURCE
Jamie Madillbfa91f42014-06-05 15:45:18 -040034 (
35 attribute vec4 inputAttribute;
36 void main()
37 {
38 gl_Position = inputAttribute;
39 }
40 );
41 }
42
Austin Kinrossaf875522014-08-25 21:06:07 -070043 std::string GenerateVaryingType(GLint vectorSize)
44 {
45 char varyingType[10];
46
47 if (vectorSize == 1)
48 {
49 sprintf(varyingType, "float");
50 }
51 else
52 {
53 sprintf(varyingType, "vec%d", vectorSize);
54 }
55
56 return std::string(varyingType);
57 }
58
59 std::string GenerateVectorVaryingDeclaration(GLint vectorSize, GLint arraySize, GLint id)
60 {
61 char buff[100];
62
63 if (arraySize == 1)
64 {
65 sprintf(buff, "varying %s v%d;\n", GenerateVaryingType(vectorSize).c_str(), id);
66 }
67 else
68 {
69 sprintf(buff, "varying %s v%d[%d];\n", GenerateVaryingType(vectorSize).c_str(), id, arraySize);
70 }
71
72 return std::string(buff);
73 }
74
75 std::string GenerateVectorVaryingSettingCode(GLint vectorSize, GLint arraySize, GLint id)
76 {
77 std::string returnString;
78 char buff[100];
79
80 if (arraySize == 1)
81 {
82 sprintf(buff, "\t v%d = %s(1.0);\n", id, GenerateVaryingType(vectorSize).c_str());
83 returnString += buff;
84 }
85 else
86 {
87 for (int i = 0; i < arraySize; i++)
88 {
89 sprintf(buff, "\t v%d[%d] = %s(1.0);\n", id, i, GenerateVaryingType(vectorSize).c_str());
90 returnString += buff;
91 }
92 }
93
94 return returnString;
95 }
96
97 std::string GenerateVectorVaryingUseCode(GLint arraySize, GLint id)
98 {
99 if (arraySize == 1)
100 {
101 char buff[100];
102 sprintf(buff, "v%d + ", id);
103 return std::string(buff);
104 }
105 else
106 {
107 std::string returnString;
108 for (int i = 0; i < arraySize; i++)
109 {
110 char buff[100];
111 sprintf(buff, "v%d[%d] + ", id, i);
112 returnString += buff;
113 }
114 return returnString;
115 }
116 }
117
Austin Kinross8b695ee2015-03-12 13:12:20 -0700118 void GenerateGLSLWithVaryings(GLint floatCount, GLint floatArrayCount, GLint vec2Count, GLint vec2ArrayCount, GLint vec3Count, GLint vec3ArrayCount,
119 GLint vec4Count, GLint vec4ArrayCount, bool useFragCoord, bool usePointCoord, bool usePointSize,
120 std::string* fragmentShader, std::string* vertexShader)
Austin Kinrossaf875522014-08-25 21:06:07 -0700121 {
122 // Generate a string declaring the varyings, to share between the fragment shader and the vertex shader.
123 std::string varyingDeclaration;
124
125 unsigned int varyingCount = 0;
126
127 for (GLint i = 0; i < floatCount; i++)
128 {
129 varyingDeclaration += GenerateVectorVaryingDeclaration(1, 1, varyingCount);
130 varyingCount += 1;
131 }
132
133 for (GLint i = 0; i < floatArrayCount; i++)
134 {
135 varyingDeclaration += GenerateVectorVaryingDeclaration(1, 2, varyingCount);
136 varyingCount += 1;
137 }
138
139 for (GLint i = 0; i < vec2Count; i++)
140 {
141 varyingDeclaration += GenerateVectorVaryingDeclaration(2, 1, varyingCount);
142 varyingCount += 1;
143 }
144
145 for (GLint i = 0; i < vec2ArrayCount; i++)
146 {
147 varyingDeclaration += GenerateVectorVaryingDeclaration(2, 2, varyingCount);
148 varyingCount += 1;
149 }
150
151 for (GLint i = 0; i < vec3Count; i++)
152 {
153 varyingDeclaration += GenerateVectorVaryingDeclaration(3, 1, varyingCount);
154 varyingCount += 1;
155 }
156
157 for (GLint i = 0; i < vec3ArrayCount; i++)
158 {
159 varyingDeclaration += GenerateVectorVaryingDeclaration(3, 2, varyingCount);
160 varyingCount += 1;
161 }
162
Austin Kinross8b695ee2015-03-12 13:12:20 -0700163 for (GLint i = 0; i < vec4Count; i++)
164 {
165 varyingDeclaration += GenerateVectorVaryingDeclaration(4, 1, varyingCount);
166 varyingCount += 1;
167 }
168
169 for (GLint i = 0; i < vec4ArrayCount; i++)
170 {
171 varyingDeclaration += GenerateVectorVaryingDeclaration(4, 2, varyingCount);
172 varyingCount += 1;
173 }
174
Austin Kinrossaf875522014-08-25 21:06:07 -0700175 // Generate the vertex shader
176 vertexShader->clear();
177 vertexShader->append(varyingDeclaration);
178 vertexShader->append("\nvoid main()\n{\n");
179
180 unsigned int currentVSVarying = 0;
181
182 for (GLint i = 0; i < floatCount; i++)
183 {
184 vertexShader->append(GenerateVectorVaryingSettingCode(1, 1, currentVSVarying));
185 currentVSVarying += 1;
186 }
187
188 for (GLint i = 0; i < floatArrayCount; i++)
189 {
190 vertexShader->append(GenerateVectorVaryingSettingCode(1, 2, currentVSVarying));
191 currentVSVarying += 1;
192 }
193
194 for (GLint i = 0; i < vec2Count; i++)
195 {
196 vertexShader->append(GenerateVectorVaryingSettingCode(2, 1, currentVSVarying));
197 currentVSVarying += 1;
198 }
199
200 for (GLint i = 0; i < vec2ArrayCount; i++)
201 {
202 vertexShader->append(GenerateVectorVaryingSettingCode(2, 2, currentVSVarying));
203 currentVSVarying += 1;
204 }
205
206 for (GLint i = 0; i < vec3Count; i++)
207 {
208 vertexShader->append(GenerateVectorVaryingSettingCode(3, 1, currentVSVarying));
209 currentVSVarying += 1;
210 }
211
212 for (GLint i = 0; i < vec3ArrayCount; i++)
213 {
214 vertexShader->append(GenerateVectorVaryingSettingCode(3, 2, currentVSVarying));
215 currentVSVarying += 1;
216 }
217
Austin Kinross8b695ee2015-03-12 13:12:20 -0700218 for (GLint i = 0; i < vec4Count; i++)
219 {
220 vertexShader->append(GenerateVectorVaryingSettingCode(4, 1, currentVSVarying));
221 currentVSVarying += 1;
222 }
223
224 for (GLint i = 0; i < vec4ArrayCount; i++)
225 {
226 vertexShader->append(GenerateVectorVaryingSettingCode(4, 2, currentVSVarying));
227 currentVSVarying += 1;
228 }
229
230 if (usePointSize)
231 {
232 vertexShader->append("gl_PointSize = 1.0;\n");
233 }
234
Austin Kinrossaf875522014-08-25 21:06:07 -0700235 vertexShader->append("}\n");
236
237 // Generate the fragment shader
238 fragmentShader->clear();
239 fragmentShader->append("precision highp float;\n");
240 fragmentShader->append(varyingDeclaration);
241 fragmentShader->append("\nvoid main() \n{ \n\tvec4 retColor = vec4(0,0,0,0);\n");
242
243 unsigned int currentFSVarying = 0;
244
245 // Make use of the float varyings
246 fragmentShader->append("\tretColor += vec4(");
247
248 for (GLint i = 0; i < floatCount; i++)
249 {
250 fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying));
251 currentFSVarying += 1;
252 }
253
254 for (GLint i = 0; i < floatArrayCount; i++)
255 {
256 fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying));
257 currentFSVarying += 1;
258 }
259
260 fragmentShader->append("0.0, 0.0, 0.0, 0.0);\n");
261
262 // Make use of the vec2 varyings
263 fragmentShader->append("\tretColor += vec4(");
264
265 for (GLint i = 0; i < vec2Count; i++)
266 {
267 fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying));
268 currentFSVarying += 1;
269 }
270
271 for (GLint i = 0; i < vec2ArrayCount; i++)
272 {
273 fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying));
274 currentFSVarying += 1;
275 }
276
277 fragmentShader->append("vec2(0.0, 0.0), 0.0, 0.0);\n");
278
279 // Make use of the vec3 varyings
280 fragmentShader->append("\tretColor += vec4(");
281
282 for (GLint i = 0; i < vec3Count; i++)
283 {
284 fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying));
285 currentFSVarying += 1;
286 }
287
288 for (GLint i = 0; i < vec3ArrayCount; i++)
289 {
290 fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying));
291 currentFSVarying += 1;
292 }
293
294 fragmentShader->append("vec3(0.0, 0.0, 0.0), 0.0);\n");
Austin Kinross8b695ee2015-03-12 13:12:20 -0700295
296 // Make use of the vec4 varyings
297 fragmentShader->append("\tretColor += ");
298
299 for (GLint i = 0; i < vec4Count; i++)
300 {
301 fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying));
302 currentFSVarying += 1;
303 }
304
305 for (GLint i = 0; i < vec4ArrayCount; i++)
306 {
307 fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying));
308 currentFSVarying += 1;
309 }
310
311 fragmentShader->append("vec4(0.0, 0.0, 0.0, 0.0);\n");
312
313 // Set gl_FragColor, and use special variables if requested
314 fragmentShader->append("\tgl_FragColor = retColor");
315
316 if (useFragCoord)
317 {
318 fragmentShader->append(" + gl_FragCoord");
319 }
320
321 if (usePointCoord)
322 {
323 fragmentShader->append(" + vec4(gl_PointCoord, 0.0, 0.0)");
324 }
325
326 fragmentShader->append(";\n}");
327 }
328
329 void VaryingTestBase(GLint floatCount, GLint floatArrayCount, GLint vec2Count, GLint vec2ArrayCount, GLint vec3Count, GLint vec3ArrayCount,
330 GLint vec4Count, GLint vec4ArrayCount, bool useFragCoord, bool usePointCoord, bool usePointSize, bool expectSuccess)
331 {
332 std::string fragmentShaderSource;
333 std::string vertexShaderSource;
334
335 GenerateGLSLWithVaryings(floatCount, floatArrayCount, vec2Count, vec2ArrayCount, vec3Count, vec3ArrayCount,
336 vec4Count, vec4ArrayCount, useFragCoord, usePointCoord, usePointSize,
337 &fragmentShaderSource, &vertexShaderSource);
338
339 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
340
341 if (expectSuccess)
342 {
343 EXPECT_NE(0u, program);
344 }
345 else
346 {
347 EXPECT_EQ(0u, program);
348 }
Austin Kinrossaf875522014-08-25 21:06:07 -0700349 }
350
Austin Kinross7a3e8e22015-10-08 15:50:06 -0700351 void CompileGLSLWithUniformsAndSamplers(GLint vertexUniformCount,
352 GLint fragmentUniformCount,
353 GLint vertexSamplersCount,
354 GLint fragmentSamplersCount,
355 bool expectSuccess)
356 {
357 std::stringstream vertexShader;
358 std::stringstream fragmentShader;
359
360 // Generate the vertex shader
361 vertexShader << "precision mediump float;\n";
362
363 for (int i = 0; i < vertexUniformCount; i++)
364 {
365 vertexShader << "uniform vec4 v" << i << ";\n";
366 }
367
368 for (int i = 0; i < vertexSamplersCount; i++)
369 {
370 vertexShader << "uniform sampler2D s" << i << ";\n";
371 }
372
373 vertexShader << "void main()\n{\n";
374
375 for (int i = 0; i < vertexUniformCount; i++)
376 {
377 vertexShader << " gl_Position += v" << i << ";\n";
378 }
379
380 for (int i = 0; i < vertexSamplersCount; i++)
381 {
382 vertexShader << " gl_Position += texture2D(s" << i << ", vec2(0.0, 0.0));\n";
383 }
384
385 if (vertexUniformCount == 0 && vertexSamplersCount == 0)
386 {
387 vertexShader << " gl_Position = vec4(0.0);\n";
388 }
389
390 vertexShader << "}\n";
391
392 // Generate the fragment shader
393 fragmentShader << "precision mediump float;\n";
394
395 for (int i = 0; i < fragmentUniformCount; i++)
396 {
397 fragmentShader << "uniform vec4 v" << i << ";\n";
398 }
399
400 for (int i = 0; i < fragmentSamplersCount; i++)
401 {
402 fragmentShader << "uniform sampler2D s" << i << ";\n";
403 }
404
405 fragmentShader << "void main()\n{\n";
406
407 for (int i = 0; i < fragmentUniformCount; i++)
408 {
409 fragmentShader << " gl_FragColor += v" << i << ";\n";
410 }
411
412 for (int i = 0; i < fragmentSamplersCount; i++)
413 {
414 fragmentShader << " gl_FragColor += texture2D(s" << i << ", vec2(0.0, 0.0));\n";
415 }
416
417 if (fragmentUniformCount == 0 && fragmentSamplersCount == 0)
418 {
419 fragmentShader << " gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n";
420 }
421
422 fragmentShader << "}\n";
423
424 GLuint program = CompileProgram(vertexShader.str(), fragmentShader.str());
425
426 if (expectSuccess)
427 {
428 EXPECT_NE(0u, program);
429 }
430 else
431 {
432 EXPECT_EQ(0u, program);
433 }
434 }
435
Jamie Madill2bf8b372014-06-16 17:18:51 -0400436 std::string mSimpleVSSource;
Jamie Madill96509e42014-05-29 14:33:27 -0400437};
438
Jamie Madille1faacb2016-12-13 12:42:14 -0500439class GLSLTestNoValidation : public GLSLTest
440{
441 public:
442 GLSLTestNoValidation() { setNoErrorEnabled(true); }
443};
444
Jamie Madillfa05f602015-05-07 13:47:11 -0400445class GLSLTest_ES3 : public GLSLTest
Gregoire Payen de La Garanderieb3dced22015-01-12 14:54:55 +0000446{
Olli Etuahoe1d199b2016-07-19 17:14:27 +0300447 void SetUp() override
448 {
449 ANGLETest::SetUp();
450
451 mSimpleVSSource =
452 "#version 300 es\n"
453 "in vec4 inputAttribute;"
454 "void main()"
455 "{"
456 " gl_Position = inputAttribute;"
457 "}";
458 }
Gregoire Payen de La Garanderieb3dced22015-01-12 14:54:55 +0000459};
460
Olli Etuaho9250cb22017-01-21 10:51:27 +0000461class GLSLTest_ES31 : public GLSLTest
462{
463 void SetUp() override
464 {
465 ANGLETest::SetUp();
466
467 mSimpleVSSource =
468 "#version 310 es\n"
469 "in vec4 inputAttribute;"
470 "void main()"
471 "{"
472 " gl_Position = inputAttribute;"
473 "}";
474 }
475};
476
Jamie Madillfa05f602015-05-07 13:47:11 -0400477TEST_P(GLSLTest, NamelessScopedStructs)
Jamie Madill96509e42014-05-29 14:33:27 -0400478{
Jamie Madillbfa91f42014-06-05 15:45:18 -0400479 const std::string fragmentShaderSource = SHADER_SOURCE
Jamie Madill96509e42014-05-29 14:33:27 -0400480 (
Jamie Madillbfa91f42014-06-05 15:45:18 -0400481 precision mediump float;
482
Jamie Madill96509e42014-05-29 14:33:27 -0400483 void main()
484 {
Jamie Madillbfa91f42014-06-05 15:45:18 -0400485 struct
486 {
487 float q;
488 } b;
489
490 gl_FragColor = vec4(1, 0, 0, 1);
491 gl_FragColor.a += b.q;
Jamie Madill96509e42014-05-29 14:33:27 -0400492 }
493 );
494
Jamie Madill5599c8f2014-08-26 13:16:39 -0400495 GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
Jamie Madillbfa91f42014-06-05 15:45:18 -0400496 EXPECT_NE(0u, program);
497}
Austin Kinross18b931d2014-09-29 12:58:31 -0700498
Jamie Madillfa05f602015-05-07 13:47:11 -0400499TEST_P(GLSLTest, ScopedStructsOrderBug)
Jamie Madillbfa91f42014-06-05 15:45:18 -0400500{
Geoff Lange0cc2a42016-01-20 10:58:17 -0500501 // TODO(geofflang): Find out why this doesn't compile on Apple OpenGL drivers
502 // (http://anglebug.com/1292)
Geoff Lang5103f4c2016-01-26 11:40:18 -0500503 // TODO(geofflang): Find out why this doesn't compile on AMD OpenGL drivers
Geoff Lange0cc2a42016-01-20 10:58:17 -0500504 // (http://anglebug.com/1291)
Corentin Wallezc7f59d02016-06-20 10:12:08 -0400505 if (IsDesktopOpenGL() && (IsOSX() || !IsNVIDIA()))
Geoff Lange0cc2a42016-01-20 10:58:17 -0500506 {
Jamie Madill518b9fa2016-03-02 11:26:02 -0500507 std::cout << "Test disabled on this OpenGL configuration." << std::endl;
Geoff Lange0cc2a42016-01-20 10:58:17 -0500508 return;
509 }
Geoff Lange0cc2a42016-01-20 10:58:17 -0500510
Jamie Madillbfa91f42014-06-05 15:45:18 -0400511 const std::string fragmentShaderSource = SHADER_SOURCE
512 (
513 precision mediump float;
514
515 struct T
516 {
517 float f;
518 };
519
520 void main()
521 {
522 T a;
523
524 struct T
525 {
526 float q;
527 };
528
529 T b;
530
531 gl_FragColor = vec4(1, 0, 0, 1);
532 gl_FragColor.a += a.f;
533 gl_FragColor.a += b.q;
534 }
535 );
536
Jamie Madill5599c8f2014-08-26 13:16:39 -0400537 GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
Jamie Madillbfa91f42014-06-05 15:45:18 -0400538 EXPECT_NE(0u, program);
539}
540
Jamie Madillfa05f602015-05-07 13:47:11 -0400541TEST_P(GLSLTest, ScopedStructsBug)
Jamie Madillbfa91f42014-06-05 15:45:18 -0400542{
Jamie Madill96509e42014-05-29 14:33:27 -0400543 const std::string fragmentShaderSource = SHADER_SOURCE
544 (
545 precision mediump float;
546
547 struct T_0
548 {
549 float f;
550 };
551
552 void main()
553 {
554 gl_FragColor = vec4(1, 0, 0, 1);
555
556 struct T
557 {
558 vec2 v;
559 };
560
561 T_0 a;
562 T b;
563
564 gl_FragColor.a += a.f;
565 gl_FragColor.a += b.v.x;
566 }
567 );
568
Jamie Madill5599c8f2014-08-26 13:16:39 -0400569 GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
Jamie Madill2bf8b372014-06-16 17:18:51 -0400570 EXPECT_NE(0u, program);
571}
572
Jamie Madillfa05f602015-05-07 13:47:11 -0400573TEST_P(GLSLTest, DxPositionBug)
Jamie Madill2bf8b372014-06-16 17:18:51 -0400574{
575 const std::string &vertexShaderSource = SHADER_SOURCE
576 (
577 attribute vec4 inputAttribute;
578 varying float dx_Position;
579 void main()
580 {
581 gl_Position = vec4(inputAttribute);
582 dx_Position = 0.0;
583 }
584 );
585
586 const std::string &fragmentShaderSource = SHADER_SOURCE
587 (
588 precision mediump float;
589
590 varying float dx_Position;
591
592 void main()
593 {
594 gl_FragColor = vec4(dx_Position, 0, 0, 1);
595 }
596 );
597
Jamie Madill5599c8f2014-08-26 13:16:39 -0400598 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
Jamie Madill96509e42014-05-29 14:33:27 -0400599 EXPECT_NE(0u, program);
600}
Jamie Madill4836d222014-07-24 06:55:51 -0400601
Jamie Madillfa05f602015-05-07 13:47:11 -0400602TEST_P(GLSLTest, ElseIfRewriting)
Jamie Madill4836d222014-07-24 06:55:51 -0400603{
604 const std::string &vertexShaderSource =
605 "attribute vec4 a_position;\n"
606 "varying float v;\n"
607 "void main() {\n"
608 " gl_Position = a_position;\n"
609 " v = 1.0;\n"
610 " if (a_position.x <= 0.5) {\n"
611 " v = 0.0;\n"
612 " } else if (a_position.x >= 0.5) {\n"
613 " v = 2.0;\n"
614 " }\n"
615 "}\n";
616
617 const std::string &fragmentShaderSource =
618 "precision highp float;\n"
619 "varying float v;\n"
620 "void main() {\n"
621 " vec4 color = vec4(1.0, 0.0, 0.0, 1.0);\n"
622 " if (v >= 1.0) color = vec4(0.0, 1.0, 0.0, 1.0);\n"
623 " if (v >= 2.0) color = vec4(0.0, 0.0, 1.0, 1.0);\n"
624 " gl_FragColor = color;\n"
625 "}\n";
626
Jamie Madill5599c8f2014-08-26 13:16:39 -0400627 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
Jamie Madill4836d222014-07-24 06:55:51 -0400628 ASSERT_NE(0u, program);
629
630 drawQuad(program, "a_position", 0.5f);
Jamie Madill4836d222014-07-24 06:55:51 -0400631
632 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
633 EXPECT_PIXEL_EQ(getWindowWidth()-1, 0, 0, 255, 0, 255);
634}
635
Jamie Madillfa05f602015-05-07 13:47:11 -0400636TEST_P(GLSLTest, TwoElseIfRewriting)
Jamie Madill4836d222014-07-24 06:55:51 -0400637{
638 const std::string &vertexShaderSource =
639 "attribute vec4 a_position;\n"
640 "varying float v;\n"
641 "void main() {\n"
642 " gl_Position = a_position;\n"
Jamie Madill778d5272014-08-04 13:13:25 -0400643 " if (a_position.x == 0.0) {\n"
Jamie Madill4836d222014-07-24 06:55:51 -0400644 " v = 1.0;\n"
645 " } else if (a_position.x > 0.5) {\n"
646 " v = 0.0;\n"
647 " } else if (a_position.x > 0.75) {\n"
648 " v = 0.5;\n"
649 " }\n"
650 "}\n";
651
652 const std::string &fragmentShaderSource =
653 "precision highp float;\n"
654 "varying float v;\n"
655 "void main() {\n"
656 " gl_FragColor = vec4(v, 0.0, 0.0, 1.0);\n"
657 "}\n";
658
Jamie Madill5599c8f2014-08-26 13:16:39 -0400659 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
Jamie Madill4836d222014-07-24 06:55:51 -0400660 EXPECT_NE(0u, program);
661}
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400662
Jamie Madillfa05f602015-05-07 13:47:11 -0400663TEST_P(GLSLTest, FrontFacingAndVarying)
Jamie Madille6256f82014-09-17 10:31:15 -0400664{
Geoff Langdd323e92015-06-09 15:16:31 -0400665 EGLPlatformParameters platform = GetParam().eglParameters;
Austin Kinross8b695ee2015-03-12 13:12:20 -0700666
Jamie Madille6256f82014-09-17 10:31:15 -0400667 const std::string vertexShaderSource = SHADER_SOURCE
668 (
669 attribute vec4 a_position;
670 varying float v_varying;
671 void main()
672 {
673 v_varying = a_position.x;
674 gl_Position = a_position;
675 }
676 );
677
678 const std::string fragmentShaderSource = SHADER_SOURCE
679 (
680 precision mediump float;
681 varying float v_varying;
682 void main()
683 {
684 vec4 c;
685
686 if (gl_FrontFacing)
687 {
688 c = vec4(v_varying, 0, 0, 1.0);
689 }
690 else
691 {
692 c = vec4(0, v_varying, 0, 1.0);
693 }
694 gl_FragColor = c;
695 }
696 );
697
698 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
Austin Kinross02df7962015-07-01 10:03:42 -0700699
700 // Compilation should fail on D3D11 feature level 9_3, since gl_FrontFacing isn't supported.
701 if (platform.renderer == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
702 {
703 if (platform.majorVersion == 9 && platform.minorVersion == 3)
704 {
705 EXPECT_EQ(0u, program);
706 return;
707 }
708 }
709
710 // Otherwise, compilation should succeed
Jamie Madille6256f82014-09-17 10:31:15 -0400711 EXPECT_NE(0u, program);
712}
713
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400714// Verify that linking shaders declaring different shading language versions fails.
715TEST_P(GLSLTest_ES3, VersionMismatch)
716{
717 const std::string fragmentShaderSource100 =
718 "precision mediump float;\n"
719 "varying float v_varying;\n"
720 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
721
722 const std::string vertexShaderSource100 =
723 "attribute vec4 a_position;\n"
724 "varying float v_varying;\n"
725 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
726
727 const std::string fragmentShaderSource300 =
728 "#version 300 es\n"
729 "precision mediump float;\n"
730 "in float v_varying;\n"
731 "out vec4 my_FragColor;\n"
732 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
733
734 const std::string vertexShaderSource300 =
735 "#version 300 es\n"
736 "in vec4 a_position;\n"
737 "out float v_varying;\n"
738 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
739
740 GLuint program = CompileProgram(vertexShaderSource300, fragmentShaderSource100);
741 EXPECT_EQ(0u, program);
742
743 program = CompileProgram(vertexShaderSource100, fragmentShaderSource300);
744 EXPECT_EQ(0u, program);
745}
746
747// Verify that declaring varying as invariant only in vertex shader fails in ESSL 1.00.
748TEST_P(GLSLTest, InvariantVaryingOut)
749{
750 const std::string fragmentShaderSource =
751 "precision mediump float;\n"
752 "varying float v_varying;\n"
753 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
754
755 const std::string vertexShaderSource =
756 "attribute vec4 a_position;\n"
757 "invariant varying float v_varying;\n"
758 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
759
760 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
761 EXPECT_EQ(0u, program);
762}
763
764// Verify that declaring varying as invariant only in vertex shader succeeds in ESSL 3.00.
765TEST_P(GLSLTest_ES3, InvariantVaryingOut)
766{
767 // TODO: ESSL 3.00 -> GLSL 1.20 translation should add "invariant" in fragment shader
768 // for varyings which are invariant in vertex shader (http://anglebug.com/1293)
Corentin Wallezc7f59d02016-06-20 10:12:08 -0400769 if (IsDesktopOpenGL())
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400770 {
771 std::cout << "Test disabled on OpenGL." << std::endl;
772 return;
773 }
774
775 const std::string fragmentShaderSource =
776 "#version 300 es\n"
777 "precision mediump float;\n"
778 "in float v_varying;\n"
779 "out vec4 my_FragColor;\n"
780 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
781
782 const std::string vertexShaderSource =
783 "#version 300 es\n"
784 "in vec4 a_position;\n"
785 "invariant out 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_NE(0u, program);
790}
791
792// Verify that declaring varying as invariant only in fragment shader fails in ESSL 1.00.
Jamie Madillfa05f602015-05-07 13:47:11 -0400793TEST_P(GLSLTest, InvariantVaryingIn)
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400794{
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400795 const std::string fragmentShaderSource =
796 "precision mediump float;\n"
797 "invariant varying float v_varying;\n"
798 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
Geoff Lange0cc2a42016-01-20 10:58:17 -0500799
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400800 const std::string vertexShaderSource =
801 "attribute vec4 a_position;\n"
802 "varying float v_varying;\n"
803 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400804
Jamie Madill5599c8f2014-08-26 13:16:39 -0400805 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400806 EXPECT_EQ(0u, program);
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400807}
808
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400809// Verify that declaring varying as invariant only in fragment shader fails in ESSL 3.00.
810TEST_P(GLSLTest_ES3, InvariantVaryingIn)
811{
812 const std::string fragmentShaderSource =
813 "#version 300 es\n"
814 "precision mediump float;\n"
815 "invariant in float v_varying;\n"
816 "out vec4 my_FragColor;\n"
817 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
818
819 const std::string vertexShaderSource =
820 "#version 300 es\n"
821 "in vec4 a_position;\n"
822 "out float v_varying;\n"
823 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
824
825 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
826 EXPECT_EQ(0u, program);
827}
828
829// Verify that declaring varying as invariant in both shaders succeeds in ESSL 1.00.
Jamie Madillfa05f602015-05-07 13:47:11 -0400830TEST_P(GLSLTest, InvariantVaryingBoth)
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400831{
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400832 const std::string fragmentShaderSource =
833 "precision mediump float;\n"
834 "invariant varying float v_varying;\n"
835 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400836
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400837 const std::string vertexShaderSource =
838 "attribute vec4 a_position;\n"
839 "invariant varying float v_varying;\n"
840 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400841
Jamie Madill5599c8f2014-08-26 13:16:39 -0400842 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400843 EXPECT_NE(0u, program);
844}
845
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400846// Verify that declaring varying as invariant in both shaders fails in ESSL 3.00.
847TEST_P(GLSLTest_ES3, InvariantVaryingBoth)
848{
849 const std::string fragmentShaderSource =
850 "#version 300 es\n"
851 "precision mediump float;\n"
852 "invariant in float v_varying;\n"
853 "out vec4 my_FragColor;\n"
854 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
855
856 const std::string vertexShaderSource =
857 "#version 300 es\n"
858 "in vec4 a_position;\n"
859 "invariant out float v_varying;\n"
860 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
861
862 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
863 EXPECT_EQ(0u, program);
864}
865
866// Verify that declaring gl_Position as invariant succeeds in ESSL 1.00.
Jamie Madillfa05f602015-05-07 13:47:11 -0400867TEST_P(GLSLTest, InvariantGLPosition)
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400868{
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400869 const std::string fragmentShaderSource =
870 "precision mediump float;\n"
871 "varying float v_varying;\n"
872 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400873
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400874 const std::string vertexShaderSource =
875 "attribute vec4 a_position;\n"
876 "invariant gl_Position;\n"
877 "varying float v_varying;\n"
878 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400879
Jamie Madill5599c8f2014-08-26 13:16:39 -0400880 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400881 EXPECT_NE(0u, program);
882}
883
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400884// Verify that declaring gl_Position as invariant succeeds in ESSL 3.00.
885TEST_P(GLSLTest_ES3, InvariantGLPosition)
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400886{
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400887 const std::string fragmentShaderSource =
888 "#version 300 es\n"
889 "precision mediump float;\n"
890 "in float v_varying;\n"
891 "out vec4 my_FragColor;\n"
892 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
893
894 const std::string vertexShaderSource =
895 "#version 300 es\n"
896 "in vec4 a_position;\n"
897 "invariant gl_Position;\n"
898 "out float v_varying;\n"
899 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
900
901 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
902 EXPECT_NE(0u, program);
903}
904
905// Verify that using invariant(all) in both shaders succeeds in ESSL 1.00.
906TEST_P(GLSLTest, InvariantAllBoth)
907{
908 // TODO: ESSL 1.00 -> GLSL 1.20 translation should add "invariant" in fragment shader
909 // for varyings which are invariant in vertex shader individually,
910 // and remove invariant(all) from fragment shader (http://anglebug.com/1293)
Corentin Wallezc7f59d02016-06-20 10:12:08 -0400911 if (IsDesktopOpenGL())
Geoff Lange0cc2a42016-01-20 10:58:17 -0500912 {
913 std::cout << "Test disabled on OpenGL." << std::endl;
914 return;
915 }
916
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400917 const std::string fragmentShaderSource =
918 "#pragma STDGL invariant(all)\n"
919 "precision mediump float;\n"
920 "varying float v_varying;\n"
921 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400922
923 const std::string vertexShaderSource =
924 "#pragma STDGL invariant(all)\n"
925 "attribute vec4 a_position;\n"
926 "varying float v_varying;\n"
927 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
928
Jamie Madill5599c8f2014-08-26 13:16:39 -0400929 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400930 EXPECT_NE(0u, program);
931}
Austin Kinrossaf875522014-08-25 21:06:07 -0700932
Geoff Lang156d7192016-07-21 16:11:00 -0400933// Verify that functions without return statements still compile
934TEST_P(GLSLTest, MissingReturnFloat)
935{
936 const std::string vertexShaderSource =
937 "varying float v_varying;\n"
938 "float f() { if (v_varying > 0.0) return 1.0; }\n"
939 "void main() { gl_Position = vec4(f(), 0, 0, 1); }\n";
940
941 const std::string fragmentShaderSource =
942 "precision mediump float;\n"
943 "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
944
945 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
946 EXPECT_NE(0u, program);
947}
948
949// Verify that functions without return statements still compile
950TEST_P(GLSLTest, MissingReturnVec2)
951{
952 const std::string vertexShaderSource =
953 "varying float v_varying;\n"
954 "vec2 f() { if (v_varying > 0.0) return vec2(1.0, 1.0); }\n"
955 "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
956
957 const std::string fragmentShaderSource =
958 "precision mediump float;\n"
959 "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
960
961 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
962 EXPECT_NE(0u, program);
963}
964
965// Verify that functions without return statements still compile
966TEST_P(GLSLTest, MissingReturnVec3)
967{
968 const std::string vertexShaderSource =
969 "varying float v_varying;\n"
970 "vec3 f() { if (v_varying > 0.0) return vec3(1.0, 1.0, 1.0); }\n"
971 "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
972
973 const std::string fragmentShaderSource =
974 "precision mediump float;\n"
975 "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
976
977 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
978 EXPECT_NE(0u, program);
979}
980
981// Verify that functions without return statements still compile
982TEST_P(GLSLTest, MissingReturnVec4)
983{
984 const std::string vertexShaderSource =
985 "varying float v_varying;\n"
986 "vec4 f() { if (v_varying > 0.0) return vec4(1.0, 1.0, 1.0, 1.0); }\n"
987 "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
988
989 const std::string fragmentShaderSource =
990 "precision mediump float;\n"
991 "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
992
993 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
994 EXPECT_NE(0u, program);
995}
996
997// Verify that functions without return statements still compile
998TEST_P(GLSLTest, MissingReturnIVec4)
999{
1000 const std::string vertexShaderSource =
1001 "varying float v_varying;\n"
1002 "ivec4 f() { if (v_varying > 0.0) return ivec4(1, 1, 1, 1); }\n"
1003 "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
1004
1005 const std::string fragmentShaderSource =
1006 "precision mediump float;\n"
1007 "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
1008
1009 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1010 EXPECT_NE(0u, program);
1011}
1012
1013// Verify that functions without return statements still compile
1014TEST_P(GLSLTest, MissingReturnMat4)
1015{
1016 const std::string vertexShaderSource =
1017 "varying float v_varying;\n"
1018 "mat4 f() { if (v_varying > 0.0) return mat4(1.0); }\n"
1019 "void main() { gl_Position = vec4(f()[0][0], 0, 0, 1); }\n";
1020
1021 const std::string fragmentShaderSource =
1022 "precision mediump float;\n"
1023 "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
1024
1025 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1026 EXPECT_NE(0u, program);
1027}
1028
1029// Verify that functions without return statements still compile
1030TEST_P(GLSLTest, MissingReturnStruct)
1031{
1032 const std::string vertexShaderSource =
1033 "varying float v_varying;\n"
1034 "struct s { float a; int b; vec2 c; };\n"
1035 "s f() { if (v_varying > 0.0) return s(1.0, 1, vec2(1.0, 1.0)); }\n"
1036 "void main() { gl_Position = vec4(f().a, 0, 0, 1); }\n";
1037
1038 const std::string fragmentShaderSource =
1039 "precision mediump float;\n"
1040 "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
1041
1042 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1043 EXPECT_NE(0u, program);
1044}
1045
1046// Verify that functions without return statements still compile
1047TEST_P(GLSLTest_ES3, MissingReturnArray)
1048{
1049 const std::string vertexShaderSource =
1050 "#version 300 es\n"
1051 "in float v_varying;\n"
1052 "vec2[2] f() { if (v_varying > 0.0) { return vec2[2](vec2(1.0, 1.0), vec2(1.0, 1.0)); } }\n"
1053 "void main() { gl_Position = vec4(f()[0].x, 0, 0, 1); }\n";
1054
1055 const std::string fragmentShaderSource =
1056 "#version 300 es\n"
1057 "precision mediump float;\n"
1058 "out vec4 my_FragColor;\n"
1059 "void main() { my_FragColor = vec4(0, 0, 0, 1); }\n";
1060
1061 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1062 EXPECT_NE(0u, program);
1063}
1064
1065// Verify that functions without return statements still compile
1066TEST_P(GLSLTest_ES3, MissingReturnArrayOfStructs)
1067{
1068 const std::string vertexShaderSource =
1069 "#version 300 es\n"
1070 "in float v_varying;\n"
1071 "struct s { float a; int b; vec2 c; };\n"
1072 "s[2] f() { if (v_varying > 0.0) { return s[2](s(1.0, 1, vec2(1.0, 1.0)), s(1.0, 1, "
1073 "vec2(1.0, 1.0))); } }\n"
1074 "void main() { gl_Position = vec4(f()[0].a, 0, 0, 1); }\n";
1075
1076 const std::string fragmentShaderSource =
1077 "#version 300 es\n"
1078 "precision mediump float;\n"
1079 "out vec4 my_FragColor;\n"
1080 "void main() { my_FragColor = vec4(0, 0, 0, 1); }\n";
1081
1082 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1083 EXPECT_NE(0u, program);
1084}
1085
Corentin Wallez509e4562016-08-25 14:55:44 -04001086// Verify that functions without return statements still compile
1087TEST_P(GLSLTest_ES3, MissingReturnStructOfArrays)
1088{
1089 // TODO(cwallez) remove the suppression once NVIDIA removes the restriction for
1090 // GLSL >= 300. It was defined only in GLSL 2.0, section 6.1.
1091 if (IsNVIDIA() && IsOpenGLES())
1092 {
1093 std::cout << "Test skipped on NVIDIA OpenGL ES because it disallows returning "
1094 "structure of arrays"
1095 << std::endl;
1096 return;
1097 }
1098
1099 const std::string vertexShaderSource =
1100 "#version 300 es\n"
1101 "in float v_varying;\n"
1102 "struct s { float a[2]; int b[2]; vec2 c[2]; };\n"
1103 "s f() { if (v_varying > 0.0) { return s(float[2](1.0, 1.0), int[2](1, 1),"
1104 "vec2[2](vec2(1.0, 1.0), vec2(1.0, 1.0))); } }\n"
1105 "void main() { gl_Position = vec4(f().a[0], 0, 0, 1); }\n";
1106
1107 const std::string fragmentShaderSource =
1108 "#version 300 es\n"
1109 "precision mediump float;\n"
1110 "out vec4 my_FragColor;\n"
1111 "void main() { my_FragColor = vec4(0, 0, 0, 1); }\n";
1112
1113 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1114 EXPECT_NE(0u, program);
1115}
1116
Yuly Novikova1f6dc92016-06-15 23:27:04 -04001117// Verify that using invariant(all) in both shaders fails in ESSL 3.00.
1118TEST_P(GLSLTest_ES3, InvariantAllBoth)
1119{
1120 const std::string fragmentShaderSource =
1121 "#version 300 es\n"
1122 "#pragma STDGL invariant(all)\n"
1123 "precision mediump float;\n"
1124 "in float v_varying;\n"
1125 "out vec4 my_FragColor;\n"
1126 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1127
1128 const std::string vertexShaderSource =
1129 "#version 300 es\n"
1130 "#pragma STDGL invariant(all)\n"
1131 "in vec4 a_position;\n"
1132 "out float v_varying;\n"
1133 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1134
1135 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1136 EXPECT_EQ(0u, program);
1137}
1138
1139// Verify that using invariant(all) only in fragment shader fails in ESSL 1.00.
1140TEST_P(GLSLTest, InvariantAllIn)
1141{
1142 const std::string fragmentShaderSource =
1143 "#pragma STDGL invariant(all)\n"
1144 "precision mediump float;\n"
1145 "varying float v_varying;\n"
1146 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1147
1148 const std::string vertexShaderSource =
1149 "attribute vec4 a_position;\n"
1150 "varying float v_varying;\n"
1151 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1152
1153 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1154 EXPECT_EQ(0u, program);
1155}
1156
1157// Verify that using invariant(all) only in fragment shader fails in ESSL 3.00.
1158TEST_P(GLSLTest_ES3, InvariantAllIn)
1159{
1160 const std::string fragmentShaderSource =
1161 "#version 300 es\n"
1162 "#pragma STDGL invariant(all)\n"
1163 "precision mediump float;\n"
1164 "in float v_varying;\n"
1165 "out vec4 my_FragColor;\n"
1166 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1167
1168 const std::string vertexShaderSource =
1169 "#version 300 es\n"
1170 "in vec4 a_position;\n"
1171 "out float v_varying;\n"
1172 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1173
1174 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1175 EXPECT_EQ(0u, program);
1176}
1177
1178// Verify that using invariant(all) only in vertex shader fails in ESSL 1.00.
1179TEST_P(GLSLTest, InvariantAllOut)
1180{
1181 const std::string fragmentShaderSource =
1182 "precision mediump float;\n"
1183 "varying float v_varying;\n"
1184 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1185
1186 const std::string vertexShaderSource =
1187 "#pragma STDGL invariant(all)\n"
1188 "attribute vec4 a_position;\n"
1189 "varying float v_varying;\n"
1190 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1191
1192 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1193 EXPECT_EQ(0u, program);
1194}
1195
1196// Verify that using invariant(all) only in vertex shader succeeds in ESSL 3.00.
1197TEST_P(GLSLTest_ES3, InvariantAllOut)
1198{
1199 // TODO: ESSL 3.00 -> GLSL 1.20 translation should add "invariant" in fragment shader
1200 // for varyings which are invariant in vertex shader,
1201 // because of invariant(all) being used in vertex shader (http://anglebug.com/1293)
Corentin Wallezc7f59d02016-06-20 10:12:08 -04001202 if (IsDesktopOpenGL())
Yuly Novikova1f6dc92016-06-15 23:27:04 -04001203 {
1204 std::cout << "Test disabled on OpenGL." << std::endl;
1205 return;
1206 }
1207
1208 const std::string fragmentShaderSource =
1209 "#version 300 es\n"
1210 "precision mediump float;\n"
1211 "in float v_varying;\n"
1212 "out vec4 my_FragColor;\n"
1213 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1214
1215 const std::string vertexShaderSource =
1216 "#version 300 es\n"
1217 "#pragma STDGL invariant(all)\n"
1218 "in vec4 a_position;\n"
1219 "out float v_varying;\n"
1220 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1221
1222 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1223 EXPECT_NE(0u, program);
1224}
1225
Jamie Madillfa05f602015-05-07 13:47:11 -04001226TEST_P(GLSLTest, MaxVaryingVec4)
Austin Kinross8b695ee2015-03-12 13:12:20 -07001227{
Geoff Lang69accbd2016-01-25 16:22:32 -05001228#if defined(__APPLE__)
1229 // TODO(geofflang): Find out why this doesn't compile on Apple AND OpenGL drivers
1230 // (http://anglebug.com/1291)
Jamie Madill518b9fa2016-03-02 11:26:02 -05001231 if (IsAMD() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
Geoff Lang69accbd2016-01-25 16:22:32 -05001232 {
1233 std::cout << "Test disabled on Apple AMD OpenGL." << std::endl;
1234 return;
1235 }
1236#endif
1237
Austin Kinross8b695ee2015-03-12 13:12:20 -07001238 GLint maxVaryings = 0;
1239 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1240
1241 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, false, false, false, true);
1242}
1243
Jamie Madillfa05f602015-05-07 13:47:11 -04001244TEST_P(GLSLTest, MaxMinusTwoVaryingVec4PlusTwoSpecialVariables)
Austin Kinross8b695ee2015-03-12 13:12:20 -07001245{
1246 GLint maxVaryings = 0;
1247 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1248
1249 // Generate shader code that uses gl_FragCoord and gl_PointCoord, two special fragment shader variables.
1250 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 2, 0, true, true, false, true);
1251}
1252
Jamie Madillfa05f602015-05-07 13:47:11 -04001253TEST_P(GLSLTest, MaxMinusTwoVaryingVec4PlusThreeSpecialVariables)
Austin Kinross8b695ee2015-03-12 13:12:20 -07001254{
Geoff Lange0cc2a42016-01-20 10:58:17 -05001255 // TODO(geofflang): Figure out why this fails on OpenGL AMD (http://anglebug.com/1291)
Jamie Madill518b9fa2016-03-02 11:26:02 -05001256 if (IsAMD() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
Geoff Lange0cc2a42016-01-20 10:58:17 -05001257 {
1258 std::cout << "Test disabled on OpenGL." << std::endl;
1259 return;
1260 }
1261
Austin Kinross8b695ee2015-03-12 13:12:20 -07001262 GLint maxVaryings = 0;
1263 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1264
1265 // Generate shader code that uses gl_FragCoord, gl_PointCoord and gl_PointSize.
1266 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 2, 0, true, true, true, true);
1267}
1268
Jamie Madillfa05f602015-05-07 13:47:11 -04001269TEST_P(GLSLTest, MaxVaryingVec3)
Austin Kinrossaf875522014-08-25 21:06:07 -07001270{
1271 GLint maxVaryings = 0;
1272 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1273
Austin Kinross8b695ee2015-03-12 13:12:20 -07001274 VaryingTestBase(0, 0, 0, 0, maxVaryings, 0, 0, 0, false, false, false, true);
Austin Kinrossaf875522014-08-25 21:06:07 -07001275}
1276
Jamie Madillfa05f602015-05-07 13:47:11 -04001277TEST_P(GLSLTest, MaxVaryingVec3Array)
Austin Kinrossaf875522014-08-25 21:06:07 -07001278{
1279 GLint maxVaryings = 0;
1280 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1281
Austin Kinross8b695ee2015-03-12 13:12:20 -07001282 VaryingTestBase(0, 0, 0, 0, 0, maxVaryings / 2, 0, 0, false, false, false, true);
Austin Kinrossaf875522014-08-25 21:06:07 -07001283}
1284
Jamie Madillbee59e02014-10-02 10:44:18 -04001285// Disabled because of a failure in D3D9
Jamie Madill9fc36822015-11-18 13:08:07 -05001286TEST_P(GLSLTest, MaxVaryingVec3AndOneFloat)
Austin Kinrossaf875522014-08-25 21:06:07 -07001287{
Jamie Madill518b9fa2016-03-02 11:26:02 -05001288 if (IsD3D9())
Jamie Madill9fc36822015-11-18 13:08:07 -05001289 {
1290 std::cout << "Test disabled on D3D9." << std::endl;
1291 return;
1292 }
1293
Austin Kinrossaf875522014-08-25 21:06:07 -07001294 GLint maxVaryings = 0;
1295 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1296
Austin Kinross8b695ee2015-03-12 13:12:20 -07001297 VaryingTestBase(1, 0, 0, 0, maxVaryings, 0, 0, 0, false, false, false, true);
Austin Kinrossaf875522014-08-25 21:06:07 -07001298}
1299
Jamie Madillbee59e02014-10-02 10:44:18 -04001300// Disabled because of a failure in D3D9
Jamie Madill9fc36822015-11-18 13:08:07 -05001301TEST_P(GLSLTest, MaxVaryingVec3ArrayAndOneFloatArray)
Austin Kinrossaf875522014-08-25 21:06:07 -07001302{
Jamie Madill518b9fa2016-03-02 11:26:02 -05001303 if (IsD3D9())
Jamie Madill9fc36822015-11-18 13:08:07 -05001304 {
1305 std::cout << "Test disabled on D3D9." << std::endl;
1306 return;
1307 }
1308
Austin Kinrossaf875522014-08-25 21:06:07 -07001309 GLint maxVaryings = 0;
1310 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1311
Austin Kinross8b695ee2015-03-12 13:12:20 -07001312 VaryingTestBase(0, 1, 0, 0, 0, maxVaryings / 2, 0, 0, false, false, false, true);
Austin Kinrossaf875522014-08-25 21:06:07 -07001313}
1314
Jamie Madillbee59e02014-10-02 10:44:18 -04001315// Disabled because of a failure in D3D9
Jamie Madill9fc36822015-11-18 13:08:07 -05001316TEST_P(GLSLTest, TwiceMaxVaryingVec2)
Austin Kinrossaf875522014-08-25 21:06:07 -07001317{
Jamie Madill518b9fa2016-03-02 11:26:02 -05001318 if (IsD3D9())
Jamie Madill9fc36822015-11-18 13:08:07 -05001319 {
1320 std::cout << "Test disabled on D3D9." << std::endl;
1321 return;
1322 }
1323
Geoff Lange0cc2a42016-01-20 10:58:17 -05001324 if (getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
1325 {
1326 // TODO(geofflang): Figure out why this fails on NVIDIA's GLES driver
1327 std::cout << "Test disabled on OpenGL ES." << std::endl;
1328 return;
1329 }
1330
Geoff Lang69accbd2016-01-25 16:22:32 -05001331#if defined(__APPLE__)
1332 // TODO(geofflang): Find out why this doesn't compile on Apple AND OpenGL drivers
1333 // (http://anglebug.com/1291)
Jamie Madill518b9fa2016-03-02 11:26:02 -05001334 if (IsAMD() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
Geoff Lang69accbd2016-01-25 16:22:32 -05001335 {
1336 std::cout << "Test disabled on Apple AMD OpenGL." << std::endl;
1337 return;
1338 }
1339#endif
1340
Austin Kinrossaf875522014-08-25 21:06:07 -07001341 GLint maxVaryings = 0;
1342 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1343
Austin Kinross8b695ee2015-03-12 13:12:20 -07001344 VaryingTestBase(0, 0, 2 * maxVaryings, 0, 0, 0, 0, 0, false, false, false, true);
Austin Kinrossaf875522014-08-25 21:06:07 -07001345}
1346
Jamie Madillbee59e02014-10-02 10:44:18 -04001347// Disabled because of a failure in D3D9
Jamie Madill9fc36822015-11-18 13:08:07 -05001348TEST_P(GLSLTest, MaxVaryingVec2Arrays)
Austin Kinrossaf875522014-08-25 21:06:07 -07001349{
Jamie Madill518b9fa2016-03-02 11:26:02 -05001350 if (IsD3DSM3())
Jamie Madill9fc36822015-11-18 13:08:07 -05001351 {
1352 std::cout << "Test disabled on SM3." << std::endl;
1353 return;
1354 }
1355
Geoff Lange0cc2a42016-01-20 10:58:17 -05001356 if (getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
1357 {
1358 // TODO(geofflang): Figure out why this fails on NVIDIA's GLES driver
1359 std::cout << "Test disabled on OpenGL ES." << std::endl;
1360 return;
1361 }
1362
Geoff Lang69accbd2016-01-25 16:22:32 -05001363#if defined(__APPLE__)
1364 // TODO(geofflang): Find out why this doesn't compile on Apple AND OpenGL drivers
1365 // (http://anglebug.com/1291)
Jamie Madill518b9fa2016-03-02 11:26:02 -05001366 if (IsAMD() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
Geoff Lang69accbd2016-01-25 16:22:32 -05001367 {
1368 std::cout << "Test disabled on Apple AMD OpenGL." << std::endl;
1369 return;
1370 }
1371#endif
1372
Austin Kinrossaf875522014-08-25 21:06:07 -07001373 GLint maxVaryings = 0;
1374 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1375
Jamie Madill192745a2016-12-22 15:58:21 -05001376 // Special case: because arrays of mat2 are packed as small grids of two rows by two columns,
1377 // we should be aware that when we're packing into an odd number of varying registers the
1378 // last row will be empty and can not fit the final vec2 arrary.
1379 GLint maxVec2Arrays = (maxVaryings >> 1) << 1;
1380
1381 VaryingTestBase(0, 0, 0, maxVec2Arrays, 0, 0, 0, 0, false, false, false, true);
Austin Kinrossaf875522014-08-25 21:06:07 -07001382}
1383
Geoff Langf60fab62014-11-24 11:21:20 -05001384// Verify shader source with a fixed length that is less than the null-terminated length will compile.
Jamie Madillfa05f602015-05-07 13:47:11 -04001385TEST_P(GLSLTest, FixedShaderLength)
Geoff Langf60fab62014-11-24 11:21:20 -05001386{
1387 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1388
1389 const std::string appendGarbage = "abcasdfasdfasdfasdfasdf";
1390 const std::string source = "void main() { gl_FragColor = vec4(0, 0, 0, 0); }" + appendGarbage;
1391 const char *sourceArray[1] = { source.c_str() };
Corentin Wallez973402f2015-05-11 13:42:22 -04001392 GLint lengths[1] = { static_cast<GLint>(source.length() - appendGarbage.length()) };
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001393 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
Geoff Langf60fab62014-11-24 11:21:20 -05001394 glCompileShader(shader);
1395
1396 GLint compileResult;
1397 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1398 EXPECT_NE(compileResult, 0);
1399}
1400
1401// Verify that a negative shader source length is treated as a null-terminated length.
Jamie Madillfa05f602015-05-07 13:47:11 -04001402TEST_P(GLSLTest, NegativeShaderLength)
Geoff Langf60fab62014-11-24 11:21:20 -05001403{
1404 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1405
1406 const char *sourceArray[1] = { "void main() { gl_FragColor = vec4(0, 0, 0, 0); }" };
1407 GLint lengths[1] = { -10 };
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001408 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
Geoff Langf60fab62014-11-24 11:21:20 -05001409 glCompileShader(shader);
1410
1411 GLint compileResult;
1412 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1413 EXPECT_NE(compileResult, 0);
1414}
1415
Corentin Wallez9a9c0482016-04-12 10:36:25 -04001416// Check that having an invalid char after the "." doesn't cause an assert.
1417TEST_P(GLSLTest, InvalidFieldFirstChar)
1418{
1419 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
1420 const char *source = "void main() {vec4 x; x.}";
1421 glShaderSource(shader, 1, &source, 0);
1422 glCompileShader(shader);
1423
1424 GLint compileResult;
1425 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1426 EXPECT_EQ(0, compileResult);
1427}
1428
Geoff Langf60fab62014-11-24 11:21:20 -05001429// Verify that a length array with mixed positive and negative values compiles.
Jamie Madillfa05f602015-05-07 13:47:11 -04001430TEST_P(GLSLTest, MixedShaderLengths)
Geoff Langf60fab62014-11-24 11:21:20 -05001431{
1432 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1433
1434 const char *sourceArray[] =
1435 {
1436 "void main()",
1437 "{",
1438 " gl_FragColor = vec4(0, 0, 0, 0);",
1439 "}",
1440 };
1441 GLint lengths[] =
1442 {
1443 -10,
1444 1,
Corentin Wallez973402f2015-05-11 13:42:22 -04001445 static_cast<GLint>(strlen(sourceArray[2])),
Geoff Langf60fab62014-11-24 11:21:20 -05001446 -1,
1447 };
1448 ASSERT_EQ(ArraySize(sourceArray), ArraySize(lengths));
1449
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001450 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
Geoff Langf60fab62014-11-24 11:21:20 -05001451 glCompileShader(shader);
1452
1453 GLint compileResult;
1454 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1455 EXPECT_NE(compileResult, 0);
1456}
1457
1458// Verify that zero-length shader source does not affect shader compilation.
Jamie Madillfa05f602015-05-07 13:47:11 -04001459TEST_P(GLSLTest, ZeroShaderLength)
Geoff Langf60fab62014-11-24 11:21:20 -05001460{
1461 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1462
1463 const char *sourceArray[] =
1464 {
1465 "adfasdf",
1466 "34534",
1467 "void main() { gl_FragColor = vec4(0, 0, 0, 0); }",
1468 "",
1469 "asdfasdfsdsdf",
1470 };
1471 GLint lengths[] =
1472 {
1473 0,
1474 0,
1475 -1,
1476 0,
1477 0,
1478 };
1479 ASSERT_EQ(ArraySize(sourceArray), ArraySize(lengths));
1480
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001481 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
Geoff Langf60fab62014-11-24 11:21:20 -05001482 glCompileShader(shader);
1483
1484 GLint compileResult;
1485 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1486 EXPECT_NE(compileResult, 0);
1487}
Jamie Madill21c1e452014-12-29 11:33:41 -05001488
1489// Tests that bad index expressions don't crash ANGLE's translator.
1490// https://code.google.com/p/angleproject/issues/detail?id=857
Jamie Madillfa05f602015-05-07 13:47:11 -04001491TEST_P(GLSLTest, BadIndexBug)
Jamie Madill21c1e452014-12-29 11:33:41 -05001492{
1493 const std::string &fragmentShaderSourceVec =
1494 "precision mediump float;\n"
1495 "uniform vec4 uniformVec;\n"
1496 "void main()\n"
1497 "{\n"
1498 " gl_FragColor = vec4(uniformVec[int()]);\n"
1499 "}";
1500
1501 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, fragmentShaderSourceVec);
1502 EXPECT_EQ(0u, shader);
1503
1504 if (shader != 0)
1505 {
1506 glDeleteShader(shader);
1507 }
1508
1509 const std::string &fragmentShaderSourceMat =
1510 "precision mediump float;\n"
1511 "uniform mat4 uniformMat;\n"
1512 "void main()\n"
1513 "{\n"
1514 " gl_FragColor = vec4(uniformMat[int()]);\n"
1515 "}";
1516
1517 shader = CompileShader(GL_FRAGMENT_SHADER, fragmentShaderSourceMat);
1518 EXPECT_EQ(0u, shader);
1519
1520 if (shader != 0)
1521 {
1522 glDeleteShader(shader);
1523 }
1524
1525 const std::string &fragmentShaderSourceArray =
1526 "precision mediump float;\n"
1527 "uniform vec4 uniformArray;\n"
1528 "void main()\n"
1529 "{\n"
1530 " gl_FragColor = vec4(uniformArray[int()]);\n"
1531 "}";
1532
1533 shader = CompileShader(GL_FRAGMENT_SHADER, fragmentShaderSourceArray);
1534 EXPECT_EQ(0u, shader);
1535
1536 if (shader != 0)
1537 {
1538 glDeleteShader(shader);
1539 }
Jamie Madill37997142015-01-28 10:06:34 -05001540}
1541
Jamie Madill2e295e22015-04-29 10:41:33 -04001542// Test that structs defined in uniforms are translated correctly.
Jamie Madillfa05f602015-05-07 13:47:11 -04001543TEST_P(GLSLTest, StructSpecifiersUniforms)
Jamie Madill2e295e22015-04-29 10:41:33 -04001544{
1545 const std::string fragmentShaderSource = SHADER_SOURCE
1546 (
1547 precision mediump float;
1548
1549 uniform struct S { float field;} s;
1550
1551 void main()
1552 {
1553 gl_FragColor = vec4(1, 0, 0, 1);
1554 gl_FragColor.a += s.field;
1555 }
1556 );
1557
1558 GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
1559 EXPECT_NE(0u, program);
1560}
Jamie Madill55def582015-05-04 11:24:57 -04001561
1562// Test that gl_DepthRange is not stored as a uniform location. Since uniforms
1563// beginning with "gl_" are filtered out by our validation logic, we must
1564// bypass the validation to test the behaviour of the implementation.
1565// (note this test is still Impl-independent)
Jamie Madille1faacb2016-12-13 12:42:14 -05001566TEST_P(GLSLTestNoValidation, DepthRangeUniforms)
Jamie Madill55def582015-05-04 11:24:57 -04001567{
1568 const std::string fragmentShaderSource = SHADER_SOURCE
1569 (
1570 precision mediump float;
1571
1572 void main()
1573 {
1574 gl_FragColor = vec4(gl_DepthRange.near, gl_DepthRange.far, gl_DepthRange.diff, 1);
1575 }
1576 );
1577
Jamie Madille1faacb2016-12-13 12:42:14 -05001578 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShaderSource);
Jamie Madill55def582015-05-04 11:24:57 -04001579
Jamie Madille1faacb2016-12-13 12:42:14 -05001580 // We need to bypass validation for this call.
1581 GLint nearIndex = glGetUniformLocation(program.get(), "gl_DepthRange.near");
Jamie Madill55def582015-05-04 11:24:57 -04001582 EXPECT_EQ(-1, nearIndex);
1583
1584 // Test drawing does not throw an exception.
Jamie Madille1faacb2016-12-13 12:42:14 -05001585 drawQuad(program.get(), "inputAttribute", 0.5f);
Jamie Madill55def582015-05-04 11:24:57 -04001586
1587 EXPECT_GL_NO_ERROR();
Jamie Madill55def582015-05-04 11:24:57 -04001588}
Jamie Madill4052dfc2015-05-06 15:18:49 -04001589
Jamie Madill6c9503e2016-08-16 14:06:32 -04001590std::string GenerateSmallPowShader(double base, double exponent)
1591{
1592 std::stringstream stream;
1593
1594 stream.precision(8);
1595
1596 double result = pow(base, exponent);
1597
1598 stream << "precision highp float;\n"
1599 << "float fun(float arg)\n"
1600 << "{\n"
1601 << " return pow(arg, " << std::fixed << exponent << ");\n"
1602 << "}\n"
1603 << "\n"
1604 << "void main()\n"
1605 << "{\n"
1606 << " const float a = " << std::scientific << base << ";\n"
1607 << " float b = fun(a);\n"
1608 << " if (abs(" << result << " - b) < " << std::abs(result * 0.001) << ")\n"
1609 << " {\n"
1610 << " gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
1611 << " }\n"
1612 << " else\n"
1613 << " {\n"
1614 << " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
1615 << " }\n"
1616 << "}\n";
1617
1618 return stream.str();
1619}
1620
Jamie Madill4052dfc2015-05-06 15:18:49 -04001621// Covers the WebGL test 'glsl/bugs/pow-of-small-constant-in-user-defined-function'
Jamie Madill1048e432016-07-23 18:51:28 -04001622// See http://anglebug.com/851
1623TEST_P(GLSLTest, PowOfSmallConstant)
Jamie Madill4052dfc2015-05-06 15:18:49 -04001624{
Jamie Madill6c9503e2016-08-16 14:06:32 -04001625 std::vector<double> bads;
1626 for (int eps = -1; eps <= 1; ++eps)
1627 {
1628 for (int i = -4; i <= 5; ++i)
Jamie Madill4052dfc2015-05-06 15:18:49 -04001629 {
Jamie Madill6c9503e2016-08-16 14:06:32 -04001630 if (i >= -1 && i <= 1)
1631 continue;
1632 const double epsilon = 1.0e-8;
1633 double bad = static_cast<double>(i) + static_cast<double>(eps) * epsilon;
1634 bads.push_back(bad);
Jamie Madill4052dfc2015-05-06 15:18:49 -04001635 }
Jamie Madill6c9503e2016-08-16 14:06:32 -04001636 }
Jamie Madill4052dfc2015-05-06 15:18:49 -04001637
Jamie Madill6c9503e2016-08-16 14:06:32 -04001638 for (double bad : bads)
1639 {
1640 const std::string &fragmentShaderSource = GenerateSmallPowShader(1.0e-6, bad);
Jamie Madill4052dfc2015-05-06 15:18:49 -04001641
Jamie Madill6c9503e2016-08-16 14:06:32 -04001642 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShaderSource);
Jamie Madill4052dfc2015-05-06 15:18:49 -04001643
Jamie Madill6c9503e2016-08-16 14:06:32 -04001644 drawQuad(program.get(), "inputAttribute", 0.5f);
1645
1646 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1647 EXPECT_GL_NO_ERROR();
1648 }
Jamie Madill4052dfc2015-05-06 15:18:49 -04001649}
Jamie Madillfa05f602015-05-07 13:47:11 -04001650
Cooper Partina5ef8d82015-08-19 14:52:21 -07001651// Test that fragment shaders which contain non-constant loop indexers and compiled for FL9_3 and
1652// below
1653// fail with a specific error message.
1654// Additionally test that the same fragment shader compiles successfully with feature levels greater
1655// than FL9_3.
1656TEST_P(GLSLTest, LoopIndexingValidation)
1657{
1658 const std::string fragmentShaderSource = SHADER_SOURCE
1659 (
1660 precision mediump float;
1661
1662 uniform float loopMax;
1663
1664 void main()
1665 {
1666 gl_FragColor = vec4(1, 0, 0, 1);
1667 for (float l = 0.0; l < loopMax; l++)
1668 {
1669 if (loopMax > 3.0)
1670 {
1671 gl_FragColor.a += 0.1;
1672 }
1673 }
1674 }
1675 );
1676
1677 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1678
1679 const char *sourceArray[1] = {fragmentShaderSource.c_str()};
1680 glShaderSource(shader, 1, sourceArray, nullptr);
1681 glCompileShader(shader);
1682
1683 GLint compileResult;
1684 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1685
1686 // If the test is configured to run limited to Feature Level 9_3, then it is
1687 // assumed that shader compilation will fail with an expected error message containing
1688 // "Loop index cannot be compared with non-constant expression"
Olli Etuaho814a54d2015-08-27 16:23:09 +03001689 if ((GetParam() == ES2_D3D11_FL9_3() || GetParam() == ES2_D3D9()))
Cooper Partina5ef8d82015-08-19 14:52:21 -07001690 {
1691 if (compileResult != 0)
1692 {
1693 FAIL() << "Shader compilation succeeded, expected failure";
1694 }
1695 else
1696 {
1697 GLint infoLogLength;
1698 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
1699
1700 std::string infoLog;
1701 infoLog.resize(infoLogLength);
Yunchao Hef81ce4a2017-04-24 10:49:17 +08001702 glGetShaderInfoLog(shader, static_cast<GLsizei>(infoLog.size()), nullptr, &infoLog[0]);
Cooper Partina5ef8d82015-08-19 14:52:21 -07001703
1704 if (infoLog.find("Loop index cannot be compared with non-constant expression") ==
1705 std::string::npos)
1706 {
1707 FAIL() << "Shader compilation failed with unexpected error message";
1708 }
1709 }
1710 }
1711 else
1712 {
1713 EXPECT_NE(0, compileResult);
1714 }
1715
1716 if (shader != 0)
1717 {
1718 glDeleteShader(shader);
1719 }
1720}
1721
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001722// Tests that the maximum uniforms count returned from querying GL_MAX_VERTEX_UNIFORM_VECTORS
1723// can actually be used.
1724TEST_P(GLSLTest, VerifyMaxVertexUniformVectors)
1725{
Zhenyao Mo1a256722017-01-12 11:52:57 -08001726 if (IsLinux() && IsIntel())
1727 {
1728 std::cout << "Test timed out on Linux Intel. See crbug.com/680631." << std::endl;
1729 return;
1730 }
1731
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001732 int maxUniforms = 10000;
1733 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
1734 EXPECT_GL_NO_ERROR();
1735 std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS = " << maxUniforms << std::endl;
1736
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001737 CompileGLSLWithUniformsAndSamplers(maxUniforms, 0, 0, 0, true);
1738}
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001739
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001740// Tests that the maximum uniforms count returned from querying GL_MAX_VERTEX_UNIFORM_VECTORS
1741// can actually be used along with the maximum number of texture samplers.
1742TEST_P(GLSLTest, VerifyMaxVertexUniformVectorsWithSamplers)
1743{
Geoff Lange0cc2a42016-01-20 10:58:17 -05001744 if (GetParam().eglParameters.renderer == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE ||
1745 GetParam().eglParameters.renderer == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
1746 {
1747 std::cout << "Test disabled on OpenGL." << std::endl;
1748 return;
1749 }
1750
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001751 int maxUniforms = 10000;
1752 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
1753 EXPECT_GL_NO_ERROR();
1754 std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS = " << maxUniforms << std::endl;
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001755
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001756 int maxTextureImageUnits = 0;
1757 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001758
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001759 CompileGLSLWithUniformsAndSamplers(maxUniforms, 0, maxTextureImageUnits, 0, true);
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001760}
1761
1762// Tests that the maximum uniforms count + 1 from querying GL_MAX_VERTEX_UNIFORM_VECTORS
1763// fails shader compilation.
1764TEST_P(GLSLTest, VerifyMaxVertexUniformVectorsExceeded)
1765{
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001766 int maxUniforms = 10000;
1767 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
1768 EXPECT_GL_NO_ERROR();
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001769 std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS + 1 = " << maxUniforms + 1 << std::endl;
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001770
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001771 CompileGLSLWithUniformsAndSamplers(maxUniforms + 1, 0, 0, 0, false);
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001772}
1773
1774// Tests that the maximum uniforms count returned from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
1775// can actually be used.
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001776TEST_P(GLSLTest, VerifyMaxFragmentUniformVectors)
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001777{
Zhenyao Mo1a256722017-01-12 11:52:57 -08001778 if (IsLinux() && IsIntel())
1779 {
1780 std::cout << "Test timed out on Linux Intel. See crbug.com/680631." << std::endl;
1781 return;
1782 }
1783
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001784 int maxUniforms = 10000;
1785 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
1786 EXPECT_GL_NO_ERROR();
1787 std::cout << "Validating GL_MAX_FRAGMENT_UNIFORM_VECTORS = " << maxUniforms << std::endl;
1788
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001789 CompileGLSLWithUniformsAndSamplers(0, maxUniforms, 0, 0, true);
1790}
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001791
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001792// Tests that the maximum uniforms count returned from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
1793// can actually be used along with the maximum number of texture samplers.
1794TEST_P(GLSLTest, VerifyMaxFragmentUniformVectorsWithSamplers)
1795{
Geoff Lange0cc2a42016-01-20 10:58:17 -05001796 if (GetParam().eglParameters.renderer == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE ||
1797 GetParam().eglParameters.renderer == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
1798 {
1799 std::cout << "Test disabled on OpenGL." << std::endl;
1800 return;
1801 }
1802
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001803 int maxUniforms = 10000;
1804 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
1805 EXPECT_GL_NO_ERROR();
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001806
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001807 int maxTextureImageUnits = 0;
1808 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001809
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001810 CompileGLSLWithUniformsAndSamplers(0, maxUniforms, 0, maxTextureImageUnits, true);
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001811}
1812
1813// Tests that the maximum uniforms count + 1 from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
1814// fails shader compilation.
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001815TEST_P(GLSLTest, VerifyMaxFragmentUniformVectorsExceeded)
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001816{
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001817 int maxUniforms = 10000;
1818 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
1819 EXPECT_GL_NO_ERROR();
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001820 std::cout << "Validating GL_MAX_FRAGMENT_UNIFORM_VECTORS + 1 = " << maxUniforms + 1
1821 << std::endl;
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001822
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001823 CompileGLSLWithUniformsAndSamplers(0, maxUniforms + 1, 0, 0, false);
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001824}
1825
Geoff Langba992ab2017-04-19 11:18:14 -04001826// Test compiling shaders using the GL_EXT_shader_texture_lod extension
1827TEST_P(GLSLTest, TextureLOD)
1828{
1829 if (!extensionEnabled("GL_EXT_shader_texture_lod"))
1830 {
1831 std::cout << "Test skipped due to missing GL_EXT_shader_texture_lod." << std::endl;
1832 return;
1833 }
1834
1835 const std::string source =
1836 "#extension GL_EXT_shader_texture_lod : require\n"
1837 "uniform sampler2D u_texture;\n"
1838 "void main() {\n"
1839 " gl_FragColor = texture2DGradEXT(u_texture, vec2(0.0, 0.0), vec2(0.0, 0.0), vec2(0.0, "
1840 "0.0));\n"
1841 "}\n";
1842
1843 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, source);
1844 ASSERT_NE(0u, shader);
1845 glDeleteShader(shader);
1846}
1847
Olli Etuahobe59c2f2016-03-07 11:32:34 +02001848// Test that two constructors which have vec4 and mat2 parameters get disambiguated (issue in
1849// HLSL).
1850TEST_P(GLSLTest_ES3, AmbiguousConstructorCall2x2)
1851{
1852 const std::string fragmentShaderSource =
1853 "#version 300 es\n"
1854 "precision highp float;\n"
1855 "out vec4 my_FragColor;\n"
1856 "void main()\n"
1857 "{\n"
1858 " my_FragColor = vec4(0.0);\n"
1859 "}";
1860
1861 const std::string vertexShaderSource =
1862 "#version 300 es\n"
1863 "precision highp float;\n"
1864 "in vec4 a_vec;\n"
1865 "in mat2 a_mat;\n"
1866 "void main()\n"
1867 "{\n"
1868 " gl_Position = vec4(a_vec) + vec4(a_mat);\n"
1869 "}";
1870
1871 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1872 EXPECT_NE(0u, program);
1873}
1874
1875// Test that two constructors which have mat2x3 and mat3x2 parameters get disambiguated.
1876// This was suspected to be an issue in HLSL, but HLSL seems to be able to natively choose between
1877// the function signatures in this case.
1878TEST_P(GLSLTest_ES3, AmbiguousConstructorCall2x3)
1879{
1880 const std::string fragmentShaderSource =
1881 "#version 300 es\n"
1882 "precision highp float;\n"
1883 "out vec4 my_FragColor;\n"
1884 "void main()\n"
1885 "{\n"
1886 " my_FragColor = vec4(0.0);\n"
1887 "}";
1888
1889 const std::string vertexShaderSource =
1890 "#version 300 es\n"
1891 "precision highp float;\n"
1892 "in mat3x2 a_matA;\n"
1893 "in mat2x3 a_matB;\n"
1894 "void main()\n"
1895 "{\n"
1896 " gl_Position = vec4(a_matA) + vec4(a_matB);\n"
1897 "}";
1898
1899 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1900 EXPECT_NE(0u, program);
1901}
1902
1903// Test that two functions which have vec4 and mat2 parameters get disambiguated (issue in HLSL).
1904TEST_P(GLSLTest_ES3, AmbiguousFunctionCall2x2)
1905{
1906 const std::string fragmentShaderSource =
1907 "#version 300 es\n"
1908 "precision highp float;\n"
1909 "out vec4 my_FragColor;\n"
1910 "void main()\n"
1911 "{\n"
1912 " my_FragColor = vec4(0.0);\n"
1913 "}";
1914
1915 const std::string vertexShaderSource =
1916 "#version 300 es\n"
1917 "precision highp float;\n"
1918 "in vec4 a_vec;\n"
1919 "in mat2 a_mat;\n"
1920 "vec4 foo(vec4 a)\n"
1921 "{\n"
1922 " return a;\n"
1923 "}\n"
1924 "vec4 foo(mat2 a)\n"
1925 "{\n"
1926 " return vec4(a[0][0]);\n"
1927 "}\n"
1928 "void main()\n"
1929 "{\n"
1930 " gl_Position = foo(a_vec) + foo(a_mat);\n"
1931 "}";
1932
1933 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1934 EXPECT_NE(0u, program);
1935}
1936
1937// Test that an user-defined function with a large number of float4 parameters doesn't fail due to
1938// the function name being too long.
1939TEST_P(GLSLTest_ES3, LargeNumberOfFloat4Parameters)
1940{
1941 const std::string fragmentShaderSource =
1942 "#version 300 es\n"
1943 "precision highp float;\n"
1944 "out vec4 my_FragColor;\n"
1945 "void main()\n"
1946 "{\n"
1947 " my_FragColor = vec4(0.0);\n"
1948 "}";
1949
1950 std::stringstream vertexShaderStream;
1951 const unsigned int paramCount = 1024u;
1952
1953 vertexShaderStream << "#version 300 es\n"
1954 "precision highp float;\n"
1955 "in vec4 a_vec;\n"
1956 "vec4 lotsOfVec4Parameters(";
1957 for (unsigned int i = 0; i < paramCount; ++i)
1958 {
1959 vertexShaderStream << "vec4 a" << i << ", ";
1960 }
1961 vertexShaderStream << "vec4 aLast)\n"
1962 "{\n"
1963 " return ";
1964 for (unsigned int i = 0; i < paramCount; ++i)
1965 {
1966 vertexShaderStream << "a" << i << " + ";
1967 }
1968 vertexShaderStream << "aLast;\n"
1969 "}\n"
1970 "void main()\n"
1971 "{\n"
1972 " gl_Position = lotsOfVec4Parameters(";
1973 for (unsigned int i = 0; i < paramCount; ++i)
1974 {
1975 vertexShaderStream << "a_vec, ";
1976 }
1977 vertexShaderStream << "a_vec);\n"
1978 "}";
1979
1980 GLuint program = CompileProgram(vertexShaderStream.str(), fragmentShaderSource);
1981 EXPECT_NE(0u, program);
1982}
1983
Olli Etuahod4f4c112016-04-15 15:11:24 +03001984// This test was written specifically to stress DeferGlobalInitializers AST transformation.
1985// Test a shader where a global constant array is initialized with an expression containing array
1986// indexing. This initializer is tricky to constant fold, so if it's not constant folded it needs to
1987// be handled in a way that doesn't generate statements in the global scope in HLSL output.
1988// Also includes multiple array initializers in one declaration, where only the second one has
1989// array indexing. This makes sure that the qualifier for the declaration is set correctly if
1990// transformations are applied to the declaration also in the case of ESSL output.
1991TEST_P(GLSLTest_ES3, InitGlobalArrayWithArrayIndexing)
1992{
Yuly Novikov41db2242016-06-25 00:14:28 -04001993 // TODO(ynovikov): re-enable once root cause of http://anglebug.com/1428 is fixed
1994 if (IsAndroid() && IsAdreno() && IsOpenGLES())
1995 {
1996 std::cout << "Test skipped on Adreno OpenGLES on Android." << std::endl;
1997 return;
1998 }
1999
Olli Etuahod4f4c112016-04-15 15:11:24 +03002000 const std::string vertexShaderSource =
2001 "#version 300 es\n"
2002 "precision highp float;\n"
2003 "in vec4 a_vec;\n"
2004 "void main()\n"
2005 "{\n"
2006 " gl_Position = vec4(a_vec);\n"
2007 "}";
2008
2009 const std::string fragmentShaderSource =
2010 "#version 300 es\n"
2011 "precision highp float;\n"
2012 "out vec4 my_FragColor;\n"
2013 "const highp float f[2] = float[2](0.1, 0.2);\n"
2014 "const highp float[2] g = float[2](0.3, 0.4), h = float[2](0.5, f[1]);\n"
2015 "void main()\n"
2016 "{\n"
2017 " my_FragColor = vec4(h[1]);\n"
2018 "}";
2019
2020 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
2021 EXPECT_NE(0u, program);
2022}
2023
Corentin Wallez419bfc92016-06-28 10:54:45 -07002024// Test that index-constant sampler array indexing is supported.
2025TEST_P(GLSLTest, IndexConstantSamplerArrayIndexing)
2026{
2027 if (IsD3D11_FL93()) {
2028 std::cout << "Test skipped on D3D11 FL 9.3." << std::endl;
2029 return;
2030 }
2031
2032 const std::string vertexShaderSource =
2033 "attribute vec4 vPosition;\n"
2034 "void main()\n"
2035 "{\n"
2036 " gl_Position = vPosition;\n"
2037 "}";
2038
2039 const std::string fragmentShaderSource =
2040 "precision mediump float;\n"
2041 "uniform sampler2D uni[2];\n"
2042 "\n"
2043 "float zero(int x)\n"
2044 "{\n"
2045 " return float(x) - float(x);\n"
2046 "}\n"
2047 "\n"
2048 "void main()\n"
2049 "{\n"
2050 " vec4 c = vec4(0,0,0,0);\n"
2051 " for (int ii = 1; ii < 3; ++ii) {\n"
2052 " if (c.x > 255.0) {\n"
2053 " c.x = 255.0 + zero(ii);\n"
2054 " break;\n"
2055 " }\n"
2056 // Index the sampler array with a predictable loop index (index-constant) as opposed to
2057 // a true constant. This is valid in OpenGL ES but isn't in many Desktop OpenGL versions,
2058 // without an extension.
2059 " c += texture2D(uni[ii - 1], vec2(0.5, 0.5));\n"
2060 " }\n"
2061 " gl_FragColor = c;\n"
2062 "}";
2063
2064 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
2065 EXPECT_NE(0u, program);
2066}
2067
Corentin Wallezb00dcee2016-07-11 17:42:58 -04002068// Test that the #pragma directive is supported and doesn't trigger a compilation failure on the
2069// native driver. The only pragma that gets passed to the OpenGL driver is "invariant" but we don't
2070// want to test its behavior, so don't use any varyings.
2071TEST_P(GLSLTest, PragmaDirective)
2072{
2073 const std::string vertexShaderSource =
2074 "#pragma STDGL invariant(all)\n"
2075 "void main()\n"
2076 "{\n"
2077 " gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
2078 "}\n";
2079
2080 const std::string fragmentShaderSource =
2081 "precision mediump float;\n"
2082 "void main()\n"
2083 "{\n"
2084 " gl_FragColor = vec4(1.0);\n"
2085 "}\n";
2086
2087 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
2088 EXPECT_NE(0u, program);
2089}
2090
Olli Etuahoe1d199b2016-07-19 17:14:27 +03002091// Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
2092// The function call that returns the array needs to be evaluated after ++j for the expression to
2093// return the correct value (true).
2094TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderArray)
2095{
2096 const std::string &fragmentShaderSource =
2097 "#version 300 es\n"
2098 "precision mediump float;\n"
2099 "out vec4 my_FragColor; \n"
2100 "int[2] func(int param) {\n"
2101 " return int[2](param, param);\n"
2102 "}\n"
2103 "void main() {\n"
2104 " int a[2]; \n"
2105 " for (int i = 0; i < 2; ++i) {\n"
2106 " a[i] = 1;\n"
2107 " }\n"
2108 " int j = 0; \n"
2109 " bool result = ((++j), (a == func(j)));\n"
2110 " my_FragColor = vec4(0.0, (result ? 1.0 : 0.0), 0.0, 1.0);\n"
2111 "}\n";
2112
2113 GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
2114 ASSERT_NE(0u, program);
2115
2116 drawQuad(program, "inputAttribute", 0.5f);
2117
2118 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2119}
2120
2121// Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
2122// The short-circuiting expression needs to be evaluated after ++j for the expression to return the
2123// correct value (true).
2124TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderShortCircuit)
2125{
2126 const std::string &fragmentShaderSource =
2127 "#version 300 es\n"
2128 "precision mediump float;\n"
2129 "out vec4 my_FragColor; \n"
2130 "void main() {\n"
2131 " int j = 0; \n"
2132 " bool result = ((++j), (j == 1 ? true : (++j == 3)));\n"
2133 " my_FragColor = vec4(0.0, ((result && j == 1) ? 1.0 : 0.0), 0.0, 1.0);\n"
2134 "}\n";
2135
2136 GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
2137 ASSERT_NE(0u, program);
2138
2139 drawQuad(program, "inputAttribute", 0.5f);
2140
2141 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2142}
2143
Jamie Madill666f65a2016-08-26 01:34:37 +00002144// Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
2145// Indexing the vector needs to be evaluated after func() for the right result.
2146TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderDynamicVectorIndexingInLValue)
2147{
2148 const std::string &fragmentShaderSource =
2149 "#version 300 es\n"
2150 "precision mediump float;\n"
2151 "out vec4 my_FragColor;\n"
2152 "uniform int u_zero;\n"
2153 "int sideEffectCount = 0;\n"
2154 "float func() {\n"
2155 " ++sideEffectCount;\n"
2156 " return -1.0;\n"
2157 "}\n"
2158 "void main() {\n"
2159 " vec4 v = vec4(0.0, 2.0, 4.0, 6.0); \n"
2160 " float f = (func(), (++v[u_zero + sideEffectCount]));\n"
2161 " bool green = abs(f - 3.0) < 0.01 && abs(v[1] - 3.0) < 0.01 && sideEffectCount == 1;\n"
2162 " my_FragColor = vec4(0.0, (green ? 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 Madillc9bde922016-07-24 17:58:50 -04002173// Test that using gl_PointCoord with GL_TRIANGLES doesn't produce a link error.
2174// From WebGL test conformance/rendering/point-specific-shader-variables.html
2175// See http://anglebug.com/1380
2176TEST_P(GLSLTest, RenderTrisWithPointCoord)
2177{
2178 const std::string &vert =
2179 "attribute vec2 aPosition;\n"
2180 "void main()\n"
2181 "{\n"
2182 " gl_Position = vec4(aPosition, 0, 1);\n"
2183 " gl_PointSize = 1.0;\n"
2184 "}";
2185 const std::string &frag =
2186 "void main()\n"
2187 "{\n"
2188 " gl_FragColor = vec4(gl_PointCoord.xy, 0, 1);\n"
2189 " gl_FragColor = vec4(0, 1, 0, 1);\n"
2190 "}";
2191
2192 ANGLE_GL_PROGRAM(prog, vert, frag);
2193 drawQuad(prog.get(), "aPosition", 0.5f);
2194 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2195}
2196
Jamie Madill5655b842016-08-02 11:00:07 -04002197// Convers a bug with the integer pow statement workaround.
2198TEST_P(GLSLTest, NestedPowStatements)
2199{
2200 const std::string &vert =
2201 "attribute vec2 position;\n"
2202 "void main()\n"
2203 "{\n"
2204 " gl_Position = vec4(position, 0, 1);\n"
2205 "}";
2206 const std::string &frag =
2207 "precision mediump float;\n"
2208 "float func(float v)\n"
2209 "{\n"
2210 " float f1 = pow(v, 2.0);\n"
2211 " return pow(f1 + v, 2.0);\n"
2212 "}\n"
2213 "void main()\n"
2214 "{\n"
2215 " float v = func(2.0);\n"
2216 " gl_FragColor = abs(v - 36.0) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
2217 "}";
2218
2219 ANGLE_GL_PROGRAM(prog, vert, frag);
2220 drawQuad(prog.get(), "position", 0.5f);
2221 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2222}
2223
Qiankun Miaof52fe932016-12-07 13:39:15 +08002224// Test that -float calculation is correct.
2225TEST_P(GLSLTest_ES3, UnaryMinusOperatorFloat)
2226{
Qiankun Miaof52fe932016-12-07 13:39:15 +08002227 const std::string &vert =
2228 "#version 300 es\n"
2229 "in highp vec4 position;\n"
2230 "void main() {\n"
2231 " gl_Position = position;\n"
2232 "}\n";
2233 const std::string &frag =
2234 "#version 300 es\n"
2235 "out highp vec4 o_color;\n"
2236 "void main() {\n"
2237 " highp float f = -1.0;\n"
2238 " // atan(tan(0.5), -f) should be 0.5.\n"
2239 " highp float v = atan(tan(0.5), -f);\n"
2240 " o_color = abs(v - 0.5) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
2241 "}\n";
2242
2243 ANGLE_GL_PROGRAM(prog, vert, frag);
2244 drawQuad(prog.get(), "position", 0.5f);
2245 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2246}
2247
Olli Etuahoda9fb092016-12-09 17:32:29 +00002248// Test that atan(vec2, vec2) calculation is correct.
2249TEST_P(GLSLTest_ES3, AtanVec2)
2250{
2251 const std::string &vert =
2252 "#version 300 es\n"
2253 "in highp vec4 position;\n"
2254 "void main() {\n"
2255 " gl_Position = position;\n"
2256 "}\n";
2257 const std::string &frag =
2258 "#version 300 es\n"
2259 "out highp vec4 o_color;\n"
2260 "void main() {\n"
2261 " highp float f = 1.0;\n"
2262 " // atan(tan(0.5), f) should be 0.5.\n"
2263 " highp vec2 v = atan(vec2(tan(0.5)), vec2(f));\n"
2264 " o_color = (abs(v[0] - 0.5) < 0.001 && abs(v[1] - 0.5) < 0.001) ? vec4(0, 1, 0, 1) : "
2265 "vec4(1, 0, 0, 1);\n"
2266 "}\n";
2267
2268 ANGLE_GL_PROGRAM(prog, vert, frag);
2269 drawQuad(prog.get(), "position", 0.5f);
2270 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2271}
2272
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002273// Convers a bug with the unary minus operator on signed integer workaround.
2274TEST_P(GLSLTest_ES3, UnaryMinusOperatorSignedInt)
2275{
2276 const std::string &vert =
2277 "#version 300 es\n"
2278 "in highp vec4 position;\n"
2279 "out mediump vec4 v_color;\n"
2280 "uniform int ui_one;\n"
2281 "uniform int ui_two;\n"
2282 "uniform int ui_three;\n"
2283 "void main() {\n"
2284 " int s[3];\n"
2285 " s[0] = ui_one;\n"
2286 " s[1] = -(-(-ui_two + 1) + 1);\n" // s[1] = -ui_two
2287 " s[2] = ui_three;\n"
2288 " int result = 0;\n"
2289 " for (int i = 0; i < ui_three; i++) {\n"
2290 " result += s[i];\n"
2291 " }\n"
2292 " v_color = (result == 2) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
2293 " gl_Position = position;\n"
2294 "}\n";
2295 const std::string &frag =
2296 "#version 300 es\n"
2297 "in mediump vec4 v_color;\n"
2298 "layout(location=0) out mediump vec4 o_color;\n"
2299 "void main() {\n"
2300 " o_color = v_color;\n"
2301 "}\n";
2302
2303 ANGLE_GL_PROGRAM(prog, vert, frag);
2304
Jamie Madille1faacb2016-12-13 12:42:14 -05002305 GLint oneIndex = glGetUniformLocation(prog.get(), "ui_one");
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002306 ASSERT_NE(-1, oneIndex);
Jamie Madille1faacb2016-12-13 12:42:14 -05002307 GLint twoIndex = glGetUniformLocation(prog.get(), "ui_two");
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002308 ASSERT_NE(-1, twoIndex);
Jamie Madille1faacb2016-12-13 12:42:14 -05002309 GLint threeIndex = glGetUniformLocation(prog.get(), "ui_three");
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002310 ASSERT_NE(-1, threeIndex);
2311 glUseProgram(prog.get());
2312 glUniform1i(oneIndex, 1);
2313 glUniform1i(twoIndex, 2);
2314 glUniform1i(threeIndex, 3);
2315
2316 drawQuad(prog.get(), "position", 0.5f);
2317 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2318}
2319
2320// Convers a bug with the unary minus operator on unsigned integer workaround.
2321TEST_P(GLSLTest_ES3, UnaryMinusOperatorUnsignedInt)
2322{
2323 const std::string &vert =
2324 "#version 300 es\n"
2325 "in highp vec4 position;\n"
2326 "out mediump vec4 v_color;\n"
2327 "uniform uint ui_one;\n"
2328 "uniform uint ui_two;\n"
2329 "uniform uint ui_three;\n"
2330 "void main() {\n"
2331 " uint s[3];\n"
2332 " s[0] = ui_one;\n"
2333 " s[1] = -(-(-ui_two + 1u) + 1u);\n" // s[1] = -ui_two
2334 " s[2] = ui_three;\n"
2335 " uint result = 0u;\n"
2336 " for (uint i = 0u; i < ui_three; i++) {\n"
2337 " result += s[i];\n"
2338 " }\n"
2339 " v_color = (result == 2u) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
2340 " gl_Position = position;\n"
2341 "}\n";
2342 const std::string &frag =
2343 "#version 300 es\n"
2344 "in mediump vec4 v_color;\n"
2345 "layout(location=0) out mediump vec4 o_color;\n"
2346 "void main() {\n"
2347 " o_color = v_color;\n"
2348 "}\n";
2349
2350 ANGLE_GL_PROGRAM(prog, vert, frag);
2351
Jamie Madille1faacb2016-12-13 12:42:14 -05002352 GLint oneIndex = glGetUniformLocation(prog.get(), "ui_one");
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002353 ASSERT_NE(-1, oneIndex);
Jamie Madille1faacb2016-12-13 12:42:14 -05002354 GLint twoIndex = glGetUniformLocation(prog.get(), "ui_two");
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002355 ASSERT_NE(-1, twoIndex);
Jamie Madille1faacb2016-12-13 12:42:14 -05002356 GLint threeIndex = glGetUniformLocation(prog.get(), "ui_three");
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002357 ASSERT_NE(-1, threeIndex);
2358 glUseProgram(prog.get());
2359 glUniform1ui(oneIndex, 1u);
2360 glUniform1ui(twoIndex, 2u);
2361 glUniform1ui(threeIndex, 3u);
2362
2363 drawQuad(prog.get(), "position", 0.5f);
2364 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2365}
2366
Olli Etuahoab481642016-08-26 12:09:10 +03002367// Test a nested sequence operator with a ternary operator inside. The ternary operator is
2368// intended to be such that it gets converted to an if statement on the HLSL backend.
2369TEST_P(GLSLTest, NestedSequenceOperatorWithTernaryInside)
2370{
2371 const std::string &vert =
2372 "attribute vec2 position;\n"
2373 "void main()\n"
2374 "{\n"
2375 " gl_Position = vec4(position, 0, 1);\n"
2376 "}";
2377
2378 // Note that the uniform keep_flop_positive doesn't need to be set - the test expects it to have
2379 // its default value false.
2380 const std::string &frag =
2381 "precision mediump float;\n"
2382 "uniform bool keep_flop_positive;\n"
2383 "float flop;\n"
2384 "void main() {\n"
2385 " flop = -1.0,\n"
2386 " (flop *= -1.0,\n"
2387 " keep_flop_positive ? 0.0 : flop *= -1.0),\n"
2388 " gl_FragColor = vec4(0, -flop, 0, 1);\n"
2389 "}";
2390
2391 ANGLE_GL_PROGRAM(prog, vert, frag);
2392 drawQuad(prog.get(), "position", 0.5f);
2393 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2394}
2395
Geoff Lang28a97ee2016-09-22 13:01:26 -04002396// Test that using a sampler2D and samplerExternalOES in the same shader works (anglebug.com/1534)
2397TEST_P(GLSLTest, ExternalAnd2DSampler)
2398{
2399 if (!extensionEnabled("GL_OES_EGL_image_external"))
2400 {
2401 std::cout << "Test skipped because GL_OES_EGL_image_external is not available."
2402 << std::endl;
2403 return;
2404 }
2405
2406 const std::string fragmentShader =
2407 "precision mediump float;\n"
2408 "uniform samplerExternalOES tex0;\n"
2409 "uniform sampler2D tex1;\n"
2410 "void main(void)\n"
2411 "{\n"
2412 " vec2 uv = vec2(0.0, 0.0);"
2413 " gl_FragColor = texture2D(tex0, uv) + texture2D(tex1, uv);\n"
2414 "}\n";
2415
2416 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2417}
2418
Olli Etuaho56a2f952016-12-08 12:16:27 +00002419// Test that literal infinity can be written out from the shader translator.
2420// A similar test can't be made for NaNs, since ESSL 3.00.6 requirements for NaNs are very loose.
2421TEST_P(GLSLTest_ES3, LiteralInfinityOutput)
2422{
2423 const std::string &fragmentShader =
2424 "#version 300 es\n"
2425 "precision highp float;\n"
2426 "out vec4 out_color;\n"
2427 "uniform float u;\n"
2428 "void main()\n"
2429 "{\n"
2430 " float infVar = 1.0e40 - u;\n"
2431 " bool correct = isinf(infVar) && infVar > 0.0;\n"
2432 " out_color = correct ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
2433 "}\n";
2434
2435 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2436 drawQuad(program.get(), "inputAttribute", 0.5f);
2437 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2438}
2439
2440// Test that literal negative infinity can be written out from the shader translator.
2441// A similar test can't be made for NaNs, since ESSL 3.00.6 requirements for NaNs are very loose.
2442TEST_P(GLSLTest_ES3, LiteralNegativeInfinityOutput)
2443{
2444 const std::string &fragmentShader =
2445 "#version 300 es\n"
2446 "precision highp float;\n"
2447 "out vec4 out_color;\n"
2448 "uniform float u;\n"
2449 "void main()\n"
2450 "{\n"
2451 " float infVar = -1.0e40 + u;\n"
2452 " bool correct = isinf(infVar) && infVar < 0.0;\n"
2453 " out_color = correct ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
2454 "}\n";
2455
2456 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2457 drawQuad(program.get(), "inputAttribute", 0.5f);
2458 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2459}
2460
Corentin Wallez36fd1002016-12-08 11:30:44 -05002461// The following MultipleDeclaration* tests are testing TranslatorHLSL specific simplification
2462// passes. Because the interaction of multiple passes must be tested, it is difficult to write
2463// a unittest for them. Instead we add the tests as end2end so will in particular test
2464// TranslatorHLSL when run on Windows.
2465
2466// Test that passes splitting multiple declarations and comma operators are correctly ordered.
2467TEST_P(GLSLTest_ES3, MultipleDeclarationWithCommaOperator)
2468{
2469 const std::string &fragmentShader =
2470 "#version 300 es\n"
2471 "precision mediump float;\n"
2472 "out vec4 color;\n"
2473 "void main(void)\n"
2474 "{\n"
2475 " float a = 0.0, b = ((gl_FragCoord.x < 0.5 ? a : 0.0), 1.0);\n"
2476 " color = vec4(b);\n"
2477 "}\n";
2478
2479 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2480}
2481
2482// Test that passes splitting multiple declarations and comma operators and for loops are
2483// correctly ordered.
2484TEST_P(GLSLTest_ES3, MultipleDeclarationWithCommaOperatorInForLoop)
2485{
2486 const std::string &fragmentShader =
2487 "#version 300 es\n"
2488 "precision mediump float;\n"
2489 "out vec4 color;\n"
2490 "void main(void)\n"
2491 "{\n"
2492 " for(float a = 0.0, b = ((gl_FragCoord.x < 0.5 ? a : 0.0), 1.0); a < 10.0; a++)\n"
2493 " {\n"
2494 " b += 1.0;\n"
2495 " color = vec4(b);\n"
2496 " }\n"
2497 "}\n";
2498
2499 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2500}
2501
2502// Test that splitting multiple declaration in for loops works with no loop condition
2503TEST_P(GLSLTest_ES3, MultipleDeclarationInForLoopEmptyCondition)
2504{
2505 const std::string &fragmentShader =
2506 "#version 300 es\n"
2507 "precision mediump float;\n"
2508 "out vec4 color;\n"
2509 "void main(void)\n"
2510 "{\n"
2511 " for(float a = 0.0, b = 1.0;; a++)\n"
2512 " {\n"
2513 " b += 1.0;\n"
2514 " if (a > 10.0) {break;}\n"
2515 " color = vec4(b);\n"
2516 " }\n"
2517 "}\n";
2518
2519 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2520}
2521
2522// Test that splitting multiple declaration in for loops works with no loop expression
2523TEST_P(GLSLTest_ES3, MultipleDeclarationInForLoopEmptyExpression)
2524{
2525 const std::string &fragmentShader =
2526 "#version 300 es\n"
2527 "precision mediump float;\n"
2528 "out vec4 color;\n"
2529 "void main(void)\n"
2530 "{\n"
2531 " for(float a = 0.0, b = 1.0; a < 10.0;)\n"
2532 " {\n"
2533 " b += 1.0;\n"
2534 " a += 1.0;\n"
2535 " color = vec4(b);\n"
2536 " }\n"
2537 "}\n";
2538
2539 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2540}
2541
Olli Etuaho8f6eb2a2017-01-12 17:04:58 +00002542// Test that dynamic indexing of a matrix inside a dynamic indexing of a vector in an l-value works
2543// correctly.
2544TEST_P(GLSLTest_ES3, NestedDynamicIndexingInLValue)
2545{
2546 const std::string &fragmentShader =
2547 "#version 300 es\n"
2548 "precision mediump float;\n"
2549 "out vec4 my_FragColor;\n"
2550 "uniform int u_zero;\n"
2551 "void main() {\n"
2552 " mat2 m = mat2(0.0, 0.0, 0.0, 0.0);\n"
2553 " m[u_zero + 1][u_zero + 1] = float(u_zero + 1);\n"
2554 " float f = m[1][1];\n"
2555 " my_FragColor = vec4(1.0 - f, f, 0.0, 1.0);\n"
2556 "}\n";
2557
2558 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2559 drawQuad(program.get(), "inputAttribute", 0.5f);
2560 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2561}
2562
Jamie Madill192745a2016-12-22 15:58:21 -05002563class WebGLGLSLTest : public GLSLTest
2564{
2565 protected:
2566 WebGLGLSLTest() { setWebGLCompatibilityEnabled(true); }
2567};
2568
2569TEST_P(WebGLGLSLTest, MaxVaryingVec4PlusFragCoord)
2570{
2571 GLint maxVaryings = 0;
2572 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2573
2574 // Generate shader code that uses gl_FragCoord, a special fragment shader variables.
2575 // This test should fail, since we are really using (maxVaryings + 1) varyings.
2576 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, true, false, false, false);
2577}
2578
2579TEST_P(WebGLGLSLTest, MaxVaryingVec4PlusPointCoord)
2580{
2581 GLint maxVaryings = 0;
2582 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2583
2584 // Generate shader code that uses gl_FragCoord, a special fragment shader variables.
2585 // This test should fail, since we are really using (maxVaryings + 1) varyings.
2586 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, false, true, false, false);
2587}
2588
2589TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec3)
2590{
2591 GLint maxVaryings = 0;
2592 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2593
2594 VaryingTestBase(0, 0, 0, 0, maxVaryings + 1, 0, 0, 0, false, false, false, false);
2595}
2596
2597TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec3Array)
2598{
2599 GLint maxVaryings = 0;
2600 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2601
2602 VaryingTestBase(0, 0, 0, 0, 0, maxVaryings / 2 + 1, 0, 0, false, false, false, false);
2603}
2604
2605TEST_P(WebGLGLSLTest, MaxVaryingVec3AndOneVec2)
2606{
2607 GLint maxVaryings = 0;
2608 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2609
2610 VaryingTestBase(0, 0, 1, 0, maxVaryings, 0, 0, 0, false, false, false, false);
2611}
2612
2613TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec2)
2614{
2615 GLint maxVaryings = 0;
2616 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2617
2618 VaryingTestBase(0, 0, 2 * maxVaryings + 1, 0, 0, 0, 0, 0, false, false, false, false);
2619}
2620
2621TEST_P(WebGLGLSLTest, MaxVaryingVec3ArrayAndMaxPlusOneFloatArray)
2622{
2623 GLint maxVaryings = 0;
2624 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2625
2626 VaryingTestBase(0, maxVaryings / 2 + 1, 0, 0, 0, 0, 0, maxVaryings / 2, false, false, false,
2627 false);
2628}
2629
Jamie Madill6c9503e2016-08-16 14:06:32 -04002630} // anonymous namespace
2631
Olli Etuaho9250cb22017-01-21 10:51:27 +00002632// Test that FindLSB and FindMSB return correct values in their corner cases.
2633TEST_P(GLSLTest_ES31, FindMSBAndFindLSBCornerCases)
2634{
Olli Etuaho61bd9fe2017-01-27 14:20:34 -08002635 // Suspecting AMD driver bug - failure seen on bots running on AMD R5 230.
2636 if (IsAMD() && IsOpenGL() && IsLinux())
2637 {
2638 std::cout << "Test skipped on AMD OpenGL Linux" << std::endl;
2639 return;
2640 }
2641
Olli Etuaho9250cb22017-01-21 10:51:27 +00002642 const std::string &fragmentShader =
2643 "#version 310 es\n"
2644 "precision mediump float;\n"
2645 "out vec4 my_FragColor;\n"
2646 "uniform int u_zero;\n"
2647 "void main() {\n"
2648 " if (findLSB(u_zero) == -1 && findMSB(u_zero) == -1 && findMSB(u_zero - 1) == -1)\n"
2649 " {\n"
2650 " my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
2651 " }\n"
2652 " else\n"
2653 " {\n"
2654 " my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
2655 " }\n"
2656 "}\n";
2657
2658 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2659 drawQuad(program.get(), "inputAttribute", 0.5f);
2660 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2661}
2662
Olli Etuahoc9da71f2017-03-06 16:28:54 +00002663// Test that writing into a swizzled vector that is dynamically indexed succeeds.
2664TEST_P(GLSLTest_ES3, WriteIntoDynamicIndexingOfSwizzledVector)
2665{
Corentin Wallez6445ddf2017-03-08 19:00:32 -05002666 if (IsOpenGL())
Olli Etuahoc9da71f2017-03-06 16:28:54 +00002667 {
2668 // http://anglebug.com/1924
Corentin Wallez6445ddf2017-03-08 19:00:32 -05002669 std::cout << "Test skipped on all OpenGL configurations because it has incorrect results"
2670 << std::endl;
Olli Etuahoc9da71f2017-03-06 16:28:54 +00002671 return;
2672 }
2673
2674 // The shader first assigns v.x to v.z (1.0)
2675 // Then v.y to v.y (2.0)
2676 // Then v.z to v.x (1.0)
2677 const std::string &fragmentShader =
2678 "#version 300 es\n"
2679 "precision highp float;\n"
2680 "out vec4 my_FragColor;\n"
2681 "void main() {\n"
2682 " vec3 v = vec3(1.0, 2.0, 3.0);\n"
2683 " for (int i = 0; i < 3; i++) {\n"
2684 " v.zyx[i] = v[i];\n"
2685 " }\n"
2686 " my_FragColor = distance(v, vec3(1.0, 2.0, 1.0)) < 0.01 ? vec4(0, 1, 0, 1) : vec4(1, "
2687 "0, 0, 1);\n"
2688 "}\n";
2689
2690 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2691 drawQuad(program.get(), "inputAttribute", 0.5f);
2692 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2693}
2694
Jamie Madill8aeeed62017-03-15 18:09:26 -04002695// This test covers a bug (and associated workaround) with nested sampling operations in the HLSL
2696// compiler DLL.
2697TEST_P(GLSLTest_ES3, NestedSamplingOperation)
2698{
2699 // This seems to be bugged on some version of Android. Might not affect the newest versions.
2700 // TODO(jmadill): Lift suppression when Chromium bots are upgraded.
2701 if (IsAndroid() && IsOpenGLES())
2702 {
2703 std::cout << "Test skipped on Android because of bug with Nexus 5X." << std::endl;
2704 return;
2705 }
2706
2707 const std::string &vertexShader =
2708 "#version 300 es\n"
2709 "out vec2 texCoord;\n"
2710 "in vec2 position;\n"
2711 "void main()\n"
2712 "{\n"
2713 " gl_Position = vec4(position, 0, 1);\n"
2714 " texCoord = position * 0.5 + vec2(0.5);\n"
2715 "}\n";
2716
2717 const std::string &simpleFragmentShader =
2718 "#version 300 es\n"
2719 "in mediump vec2 texCoord;\n"
2720 "out mediump vec4 fragColor;\n"
2721 "void main()\n"
2722 "{\n"
2723 " fragColor = vec4(texCoord, 0, 1);\n"
2724 "}\n";
2725
2726 const std::string &nestedFragmentShader =
2727 "#version 300 es\n"
2728 "uniform mediump sampler2D samplerA;\n"
2729 "uniform mediump sampler2D samplerB;\n"
2730 "in mediump vec2 texCoord;\n"
2731 "out mediump vec4 fragColor;\n"
2732 "void main ()\n"
2733 "{\n"
2734 " fragColor = texture(samplerB, texture(samplerA, texCoord).xy);\n"
2735 "}\n";
2736
2737 ANGLE_GL_PROGRAM(initProg, vertexShader, simpleFragmentShader);
2738 ANGLE_GL_PROGRAM(nestedProg, vertexShader, nestedFragmentShader);
2739
2740 // Initialize a first texture with default texCoord data.
2741 GLTexture texA;
2742 glActiveTexture(GL_TEXTURE0);
2743 glBindTexture(GL_TEXTURE_2D, texA);
2744 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
2745 GL_UNSIGNED_BYTE, nullptr);
2746 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2747 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2748
2749 GLFramebuffer fbo;
2750 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2751 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texA, 0);
2752
2753 drawQuad(initProg, "position", 0.5f);
2754 ASSERT_GL_NO_ERROR();
2755
2756 // Initialize a second texture with a simple color pattern.
2757 GLTexture texB;
2758 glActiveTexture(GL_TEXTURE1);
2759 glBindTexture(GL_TEXTURE_2D, texB);
2760
2761 std::array<GLColor, 4> simpleColors = {
2762 {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
2763 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2764 simpleColors.data());
2765 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2766 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2767
2768 // Draw with the nested program, using the first texture to index the second.
2769 glBindFramebuffer(GL_FRAMEBUFFER, 0);
2770 glUseProgram(nestedProg);
2771 GLint samplerALoc = glGetUniformLocation(nestedProg, "samplerA");
2772 ASSERT_NE(-1, samplerALoc);
2773 glUniform1i(samplerALoc, 0);
2774 GLint samplerBLoc = glGetUniformLocation(nestedProg, "samplerB");
2775 ASSERT_NE(-1, samplerBLoc);
2776 glUniform1i(samplerBLoc, 1);
2777
2778 drawQuad(nestedProg, "position", 0.5f);
2779 ASSERT_GL_NO_ERROR();
2780
2781 // Compute four texel centers.
2782 Vector2 windowSize(getWindowWidth(), getWindowHeight());
2783 Vector2 quarterWindowSize = windowSize / 4;
2784 Vector2 ul = quarterWindowSize;
2785 Vector2 ur(windowSize.x() - quarterWindowSize.x(), quarterWindowSize.y());
2786 Vector2 ll(quarterWindowSize.x(), windowSize.y() - quarterWindowSize.y());
2787 Vector2 lr = windowSize - quarterWindowSize;
2788
2789 EXPECT_PIXEL_COLOR_EQ_VEC2(ul, simpleColors[0]);
2790 EXPECT_PIXEL_COLOR_EQ_VEC2(ur, simpleColors[1]);
2791 EXPECT_PIXEL_COLOR_EQ_VEC2(ll, simpleColors[2]);
2792 EXPECT_PIXEL_COLOR_EQ_VEC2(lr, simpleColors[3]);
2793}
2794
Olli Etuaho81629262017-04-19 11:56:01 +03002795// Tests that using a constant declaration as the only statement in a for loop without curly braces
2796// doesn't crash.
2797TEST_P(GLSLTest, ConstantStatementInForLoop)
2798{
2799 const std::string &vertexShader =
2800 "void main()\n"
2801 "{\n"
2802 " for (int i = 0; i < 10; ++i)\n"
2803 " const int b = 0;\n"
2804 "}\n";
2805
2806 GLuint shader = CompileShader(GL_VERTEX_SHADER, vertexShader);
2807 EXPECT_NE(0u, shader);
2808 glDeleteShader(shader);
2809}
2810
2811// Tests that using a constant declaration as a loop init expression doesn't crash. Note that this
2812// test doesn't work on D3D9 due to looping limitations, so it is only run on ES3.
2813TEST_P(GLSLTest_ES3, ConstantStatementAsLoopInit)
2814{
2815 const std::string &vertexShader =
2816 "void main()\n"
2817 "{\n"
2818 " for (const int i = 0; i < 0;) {}\n"
2819 "}\n";
2820
2821 GLuint shader = CompileShader(GL_VERTEX_SHADER, vertexShader);
2822 EXPECT_NE(0u, shader);
2823 glDeleteShader(shader);
2824}
2825
Olli Etuaho9733cee2017-05-11 19:14:35 +03002826// Test that uninitialized local variables are initialized to 0.
2827TEST_P(GLSLTest_ES3, InitUninitializedLocals)
2828{
2829 if (IsAndroid() && IsOpenGLES())
2830 {
2831 // http://anglebug.com/2046
2832 std::cout
2833 << "Test skipped on Android GLES because local variable initialization is disabled."
2834 << std::endl;
2835 return;
2836 }
2837
2838 if (IsOSX() && IsOpenGL())
2839 {
2840 // http://anglebug.com/2041
2841 std::cout << "Test skipped on Mac OpenGL because local variable initialization is disabled."
2842 << std::endl;
2843 return;
2844 }
2845
2846 const std::string &fragmentShader =
2847 "#version 300 es\n"
2848 "precision mediump float;\n"
2849 "out vec4 my_FragColor;\n"
2850 "int result = 0;\n"
2851 "void main()\n"
2852 "{\n"
2853 " int u;\n"
2854 " result += u;\n"
2855 " int k = 0;\n"
2856 " for (int i[2], j = i[0] + 1; k < 2; ++k)\n"
2857 " {\n"
2858 " result += j;\n"
2859 " }\n"
2860 " if (result == 2)\n"
2861 " {\n"
2862 " my_FragColor = vec4(0, 1, 0, 1);\n"
2863 " }\n"
2864 " else\n"
2865 " {\n"
2866 " my_FragColor = vec4(1, 0, 0, 1);\n"
2867 " }\n"
2868 "}\n";
2869
2870 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2871 drawQuad(program.get(), "inputAttribute", 0.5f);
2872 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2873}
2874
2875// Test that uninitialized structs containing arrays of structs are initialized to 0. This
2876// specifically tests with two different struct variables declared in the same block.
2877TEST_P(GLSLTest, InitUninitializedStructContainingArrays)
2878{
2879 if (IsAndroid() && IsOpenGLES())
2880 {
2881 // http://anglebug.com/2046
2882 std::cout
2883 << "Test skipped on Android GLES because local variable initialization is disabled."
2884 << std::endl;
2885 return;
2886 }
2887
2888 if (IsOSX() && IsOpenGL())
2889 {
2890 // http://anglebug.com/2041
2891 std::cout << "Test skipped on Mac OpenGL because local variable initialization is disabled."
2892 << std::endl;
2893 return;
2894 }
2895
2896 const std::string &fragmentShader =
2897 "precision mediump float;\n"
2898 "struct T\n"
2899 "{\n"
2900 " int a[2];\n"
2901 "};\n"
2902 "struct S\n"
2903 "{\n"
2904 " T t[2];\n"
2905 "};\n"
2906 "void main()\n"
2907 "{\n"
2908 " S s;\n"
2909 " S s2;\n"
2910 " if (s.t[1].a[1] == 0 && s2.t[1].a[1] == 0)\n"
2911 " {\n"
2912 " gl_FragColor = vec4(0, 1, 0, 1);\n"
2913 " }\n"
2914 " else\n"
2915 " {\n"
2916 " gl_FragColor = vec4(1, 0, 0, 1);\n"
2917 " }\n"
2918 "}\n";
2919
2920 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2921 drawQuad(program.get(), "inputAttribute", 0.5f);
2922 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2923}
2924
2925// Test that an uninitialized nameless struct inside a for loop init statement works.
2926TEST_P(GLSLTest_ES3, UninitializedNamelessStructInForInitStatement)
2927{
2928 if (IsAndroid() && IsOpenGLES())
2929 {
2930 // http://anglebug.com/2046
2931 std::cout
2932 << "Test skipped on Android GLES because local variable initialization is disabled."
2933 << std::endl;
2934 return;
2935 }
2936
2937 if (IsOSX() && IsOpenGL())
2938 {
2939 // http://anglebug.com/2041
2940 std::cout << "Test skipped on Mac OpenGL because local variable initialization is disabled."
2941 << std::endl;
2942 return;
2943 }
2944
2945 const std::string &fragmentShader =
2946 "#version 300 es\n"
2947 "precision highp float;\n"
2948 "out vec4 my_FragColor;\n"
2949 "void main()\n"
2950 "{\n"
2951 " my_FragColor = vec4(1, 0, 0, 1);\n"
2952 " for (struct { float q; } b; b.q < 2.0; b.q++) {\n"
2953 " my_FragColor = vec4(0, 1, 0, 1);\n"
2954 " }\n"
2955 "}\n";
2956
2957 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2958 drawQuad(program.get(), "inputAttribute", 0.5f);
2959 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2960}
2961
Jamie Madillfa05f602015-05-07 13:47:11 -04002962// 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 -05002963ANGLE_INSTANTIATE_TEST(GLSLTest,
2964 ES2_D3D9(),
2965 ES2_D3D11(),
2966 ES2_D3D11_FL9_3(),
2967 ES2_OPENGL(),
2968 ES3_OPENGL(),
2969 ES2_OPENGLES(),
2970 ES3_OPENGLES());
Jamie Madillfa05f602015-05-07 13:47:11 -04002971
2972// 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 -05002973ANGLE_INSTANTIATE_TEST(GLSLTest_ES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
Jamie Madill192745a2016-12-22 15:58:21 -05002974
2975ANGLE_INSTANTIATE_TEST(WebGLGLSLTest, ES2_D3D11(), ES2_OPENGL(), ES2_OPENGLES());
Olli Etuaho9250cb22017-01-21 10:51:27 +00002976
2977ANGLE_INSTANTIATE_TEST(GLSLTest_ES31, ES31_D3D11(), ES31_OPENGL(), ES31_OPENGLES());