blob: 9282ef9be7ab68a2d48ab86d474bd3a92357c62a [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
Jamie Madill2f348d22017-06-05 10:50:59 -0400714// Test that we can release the shader compiler and still compile things properly.
715TEST_P(GLSLTest, ReleaseCompilerThenCompile)
716{
717 const std::string &simpleVS =
718 "attribute vec4 position; void main() { gl_Position = position; }";
719 const std::string &simpleFS = "void main() { gl_FragColor = vec4(1, 0, 0, 1); }";
720
721 // Draw with the first program.
722 ANGLE_GL_PROGRAM(program1, simpleVS, simpleFS);
723 drawQuad(program1, "position", 0.5f);
724 ASSERT_GL_NO_ERROR();
725 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
726
727 // Clear and release shader compiler.
728 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
729 glClear(GL_COLOR_BUFFER_BIT);
730 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
731 glReleaseShaderCompiler();
732 ASSERT_GL_NO_ERROR();
733
734 // Draw with a second program.
735 ANGLE_GL_PROGRAM(program2, simpleVS, simpleFS);
736 drawQuad(program2, "position", 0.5f);
737 ASSERT_GL_NO_ERROR();
738 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
739}
740
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400741// Verify that linking shaders declaring different shading language versions fails.
742TEST_P(GLSLTest_ES3, VersionMismatch)
743{
744 const std::string fragmentShaderSource100 =
745 "precision mediump float;\n"
746 "varying float v_varying;\n"
747 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
748
749 const std::string vertexShaderSource100 =
750 "attribute vec4 a_position;\n"
751 "varying float v_varying;\n"
752 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
753
754 const std::string fragmentShaderSource300 =
755 "#version 300 es\n"
756 "precision mediump float;\n"
757 "in float v_varying;\n"
758 "out vec4 my_FragColor;\n"
759 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
760
761 const std::string vertexShaderSource300 =
762 "#version 300 es\n"
763 "in vec4 a_position;\n"
764 "out float v_varying;\n"
765 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
766
767 GLuint program = CompileProgram(vertexShaderSource300, fragmentShaderSource100);
768 EXPECT_EQ(0u, program);
769
770 program = CompileProgram(vertexShaderSource100, fragmentShaderSource300);
771 EXPECT_EQ(0u, program);
772}
773
774// Verify that declaring varying as invariant only in vertex shader fails in ESSL 1.00.
775TEST_P(GLSLTest, InvariantVaryingOut)
776{
777 const std::string fragmentShaderSource =
778 "precision mediump float;\n"
779 "varying float v_varying;\n"
780 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
781
782 const std::string vertexShaderSource =
783 "attribute vec4 a_position;\n"
784 "invariant varying float v_varying;\n"
785 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
786
787 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
788 EXPECT_EQ(0u, program);
789}
790
791// Verify that declaring varying as invariant only in vertex shader succeeds in ESSL 3.00.
792TEST_P(GLSLTest_ES3, InvariantVaryingOut)
793{
794 // TODO: ESSL 3.00 -> GLSL 1.20 translation should add "invariant" in fragment shader
795 // for varyings which are invariant in vertex shader (http://anglebug.com/1293)
Corentin Wallezc7f59d02016-06-20 10:12:08 -0400796 if (IsDesktopOpenGL())
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400797 {
798 std::cout << "Test disabled on OpenGL." << std::endl;
799 return;
800 }
801
802 const std::string fragmentShaderSource =
803 "#version 300 es\n"
804 "precision mediump float;\n"
805 "in float v_varying;\n"
806 "out vec4 my_FragColor;\n"
807 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
808
809 const std::string vertexShaderSource =
810 "#version 300 es\n"
811 "in vec4 a_position;\n"
812 "invariant out float v_varying;\n"
813 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
814
815 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
816 EXPECT_NE(0u, program);
817}
818
819// Verify that declaring varying as invariant only in fragment shader fails in ESSL 1.00.
Jamie Madillfa05f602015-05-07 13:47:11 -0400820TEST_P(GLSLTest, InvariantVaryingIn)
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400821{
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400822 const std::string fragmentShaderSource =
823 "precision mediump float;\n"
824 "invariant varying float v_varying;\n"
825 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
Geoff Lange0cc2a42016-01-20 10:58:17 -0500826
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400827 const std::string vertexShaderSource =
828 "attribute vec4 a_position;\n"
829 "varying float v_varying;\n"
830 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400831
Jamie Madill5599c8f2014-08-26 13:16:39 -0400832 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400833 EXPECT_EQ(0u, program);
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400834}
835
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400836// Verify that declaring varying as invariant only in fragment shader fails in ESSL 3.00.
837TEST_P(GLSLTest_ES3, InvariantVaryingIn)
838{
839 const std::string fragmentShaderSource =
840 "#version 300 es\n"
841 "precision mediump float;\n"
842 "invariant in float v_varying;\n"
843 "out vec4 my_FragColor;\n"
844 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
845
846 const std::string vertexShaderSource =
847 "#version 300 es\n"
848 "in vec4 a_position;\n"
849 "out float v_varying;\n"
850 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
851
852 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
853 EXPECT_EQ(0u, program);
854}
855
856// Verify that declaring varying as invariant in both shaders succeeds in ESSL 1.00.
Jamie Madillfa05f602015-05-07 13:47:11 -0400857TEST_P(GLSLTest, InvariantVaryingBoth)
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400858{
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400859 const std::string fragmentShaderSource =
860 "precision mediump float;\n"
861 "invariant varying float v_varying;\n"
862 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400863
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400864 const std::string vertexShaderSource =
865 "attribute vec4 a_position;\n"
866 "invariant varying float v_varying;\n"
867 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400868
Jamie Madill5599c8f2014-08-26 13:16:39 -0400869 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400870 EXPECT_NE(0u, program);
871}
872
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400873// Verify that declaring varying as invariant in both shaders fails in ESSL 3.00.
874TEST_P(GLSLTest_ES3, InvariantVaryingBoth)
875{
876 const std::string fragmentShaderSource =
877 "#version 300 es\n"
878 "precision mediump float;\n"
879 "invariant in float v_varying;\n"
880 "out vec4 my_FragColor;\n"
881 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
882
883 const std::string vertexShaderSource =
884 "#version 300 es\n"
885 "in vec4 a_position;\n"
886 "invariant out float v_varying;\n"
887 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
888
889 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
890 EXPECT_EQ(0u, program);
891}
892
893// Verify that declaring gl_Position as invariant succeeds in ESSL 1.00.
Jamie Madillfa05f602015-05-07 13:47:11 -0400894TEST_P(GLSLTest, InvariantGLPosition)
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400895{
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400896 const std::string fragmentShaderSource =
897 "precision mediump float;\n"
898 "varying float v_varying;\n"
899 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400900
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400901 const std::string vertexShaderSource =
902 "attribute vec4 a_position;\n"
903 "invariant gl_Position;\n"
904 "varying float v_varying;\n"
905 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400906
Jamie Madill5599c8f2014-08-26 13:16:39 -0400907 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400908 EXPECT_NE(0u, program);
909}
910
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400911// Verify that declaring gl_Position as invariant succeeds in ESSL 3.00.
912TEST_P(GLSLTest_ES3, InvariantGLPosition)
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400913{
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400914 const std::string fragmentShaderSource =
915 "#version 300 es\n"
916 "precision mediump float;\n"
917 "in float v_varying;\n"
918 "out vec4 my_FragColor;\n"
919 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
920
921 const std::string vertexShaderSource =
922 "#version 300 es\n"
923 "in vec4 a_position;\n"
924 "invariant gl_Position;\n"
925 "out float v_varying;\n"
926 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
927
928 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
929 EXPECT_NE(0u, program);
930}
931
932// Verify that using invariant(all) in both shaders succeeds in ESSL 1.00.
933TEST_P(GLSLTest, InvariantAllBoth)
934{
935 // TODO: ESSL 1.00 -> GLSL 1.20 translation should add "invariant" in fragment shader
936 // for varyings which are invariant in vertex shader individually,
937 // and remove invariant(all) from fragment shader (http://anglebug.com/1293)
Corentin Wallezc7f59d02016-06-20 10:12:08 -0400938 if (IsDesktopOpenGL())
Geoff Lange0cc2a42016-01-20 10:58:17 -0500939 {
940 std::cout << "Test disabled on OpenGL." << std::endl;
941 return;
942 }
943
Yuly Novikova1f6dc92016-06-15 23:27:04 -0400944 const std::string fragmentShaderSource =
945 "#pragma STDGL invariant(all)\n"
946 "precision mediump float;\n"
947 "varying float v_varying;\n"
948 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400949
950 const std::string vertexShaderSource =
951 "#pragma STDGL invariant(all)\n"
952 "attribute vec4 a_position;\n"
953 "varying float v_varying;\n"
954 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
955
Jamie Madill5599c8f2014-08-26 13:16:39 -0400956 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400957 EXPECT_NE(0u, program);
958}
Austin Kinrossaf875522014-08-25 21:06:07 -0700959
Geoff Lang156d7192016-07-21 16:11:00 -0400960// Verify that functions without return statements still compile
961TEST_P(GLSLTest, MissingReturnFloat)
962{
963 const std::string vertexShaderSource =
964 "varying float v_varying;\n"
965 "float f() { if (v_varying > 0.0) return 1.0; }\n"
966 "void main() { gl_Position = vec4(f(), 0, 0, 1); }\n";
967
968 const std::string fragmentShaderSource =
969 "precision mediump float;\n"
970 "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
971
972 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
973 EXPECT_NE(0u, program);
974}
975
976// Verify that functions without return statements still compile
977TEST_P(GLSLTest, MissingReturnVec2)
978{
979 const std::string vertexShaderSource =
980 "varying float v_varying;\n"
981 "vec2 f() { if (v_varying > 0.0) return vec2(1.0, 1.0); }\n"
982 "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
983
984 const std::string fragmentShaderSource =
985 "precision mediump float;\n"
986 "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
987
988 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
989 EXPECT_NE(0u, program);
990}
991
992// Verify that functions without return statements still compile
993TEST_P(GLSLTest, MissingReturnVec3)
994{
995 const std::string vertexShaderSource =
996 "varying float v_varying;\n"
997 "vec3 f() { if (v_varying > 0.0) return vec3(1.0, 1.0, 1.0); }\n"
998 "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
999
1000 const std::string fragmentShaderSource =
1001 "precision mediump float;\n"
1002 "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
1003
1004 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1005 EXPECT_NE(0u, program);
1006}
1007
1008// Verify that functions without return statements still compile
1009TEST_P(GLSLTest, MissingReturnVec4)
1010{
1011 const std::string vertexShaderSource =
1012 "varying float v_varying;\n"
1013 "vec4 f() { if (v_varying > 0.0) return vec4(1.0, 1.0, 1.0, 1.0); }\n"
1014 "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
1015
1016 const std::string fragmentShaderSource =
1017 "precision mediump float;\n"
1018 "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
1019
1020 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1021 EXPECT_NE(0u, program);
1022}
1023
1024// Verify that functions without return statements still compile
1025TEST_P(GLSLTest, MissingReturnIVec4)
1026{
1027 const std::string vertexShaderSource =
1028 "varying float v_varying;\n"
1029 "ivec4 f() { if (v_varying > 0.0) return ivec4(1, 1, 1, 1); }\n"
1030 "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
1031
1032 const std::string fragmentShaderSource =
1033 "precision mediump float;\n"
1034 "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
1035
1036 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1037 EXPECT_NE(0u, program);
1038}
1039
1040// Verify that functions without return statements still compile
1041TEST_P(GLSLTest, MissingReturnMat4)
1042{
1043 const std::string vertexShaderSource =
1044 "varying float v_varying;\n"
1045 "mat4 f() { if (v_varying > 0.0) return mat4(1.0); }\n"
1046 "void main() { gl_Position = vec4(f()[0][0], 0, 0, 1); }\n";
1047
1048 const std::string fragmentShaderSource =
1049 "precision mediump float;\n"
1050 "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
1051
1052 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1053 EXPECT_NE(0u, program);
1054}
1055
1056// Verify that functions without return statements still compile
1057TEST_P(GLSLTest, MissingReturnStruct)
1058{
1059 const std::string vertexShaderSource =
1060 "varying float v_varying;\n"
1061 "struct s { float a; int b; vec2 c; };\n"
1062 "s f() { if (v_varying > 0.0) return s(1.0, 1, vec2(1.0, 1.0)); }\n"
1063 "void main() { gl_Position = vec4(f().a, 0, 0, 1); }\n";
1064
1065 const std::string fragmentShaderSource =
1066 "precision mediump float;\n"
1067 "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
1068
1069 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1070 EXPECT_NE(0u, program);
1071}
1072
1073// Verify that functions without return statements still compile
1074TEST_P(GLSLTest_ES3, MissingReturnArray)
1075{
1076 const std::string vertexShaderSource =
1077 "#version 300 es\n"
1078 "in float v_varying;\n"
1079 "vec2[2] f() { if (v_varying > 0.0) { return vec2[2](vec2(1.0, 1.0), vec2(1.0, 1.0)); } }\n"
1080 "void main() { gl_Position = vec4(f()[0].x, 0, 0, 1); }\n";
1081
1082 const std::string fragmentShaderSource =
1083 "#version 300 es\n"
1084 "precision mediump float;\n"
1085 "out vec4 my_FragColor;\n"
1086 "void main() { my_FragColor = vec4(0, 0, 0, 1); }\n";
1087
1088 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1089 EXPECT_NE(0u, program);
1090}
1091
1092// Verify that functions without return statements still compile
1093TEST_P(GLSLTest_ES3, MissingReturnArrayOfStructs)
1094{
1095 const std::string vertexShaderSource =
1096 "#version 300 es\n"
1097 "in float v_varying;\n"
1098 "struct s { float a; int b; vec2 c; };\n"
1099 "s[2] f() { if (v_varying > 0.0) { return s[2](s(1.0, 1, vec2(1.0, 1.0)), s(1.0, 1, "
1100 "vec2(1.0, 1.0))); } }\n"
1101 "void main() { gl_Position = vec4(f()[0].a, 0, 0, 1); }\n";
1102
1103 const std::string fragmentShaderSource =
1104 "#version 300 es\n"
1105 "precision mediump float;\n"
1106 "out vec4 my_FragColor;\n"
1107 "void main() { my_FragColor = vec4(0, 0, 0, 1); }\n";
1108
1109 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1110 EXPECT_NE(0u, program);
1111}
1112
Corentin Wallez509e4562016-08-25 14:55:44 -04001113// Verify that functions without return statements still compile
1114TEST_P(GLSLTest_ES3, MissingReturnStructOfArrays)
1115{
Olli Etuahodf7d13e2017-05-30 13:53:45 +03001116 // TODO(cwallez) remove the suppression once NVIDIA drivers are updated across trybots, drivers
1117 // since late 2016 should have the fix. Last check on 2017-05-30 revealed that the Windows
1118 // Server 2008 bots still had the old, failing drivers.
Corentin Wallez509e4562016-08-25 14:55:44 -04001119 if (IsNVIDIA() && IsOpenGLES())
1120 {
1121 std::cout << "Test skipped on NVIDIA OpenGL ES because it disallows returning "
1122 "structure of arrays"
1123 << std::endl;
1124 return;
1125 }
1126
1127 const std::string vertexShaderSource =
1128 "#version 300 es\n"
1129 "in float v_varying;\n"
1130 "struct s { float a[2]; int b[2]; vec2 c[2]; };\n"
1131 "s f() { if (v_varying > 0.0) { return s(float[2](1.0, 1.0), int[2](1, 1),"
1132 "vec2[2](vec2(1.0, 1.0), vec2(1.0, 1.0))); } }\n"
1133 "void main() { gl_Position = vec4(f().a[0], 0, 0, 1); }\n";
1134
1135 const std::string fragmentShaderSource =
1136 "#version 300 es\n"
1137 "precision mediump float;\n"
1138 "out vec4 my_FragColor;\n"
1139 "void main() { my_FragColor = vec4(0, 0, 0, 1); }\n";
1140
1141 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1142 EXPECT_NE(0u, program);
1143}
1144
Yuly Novikova1f6dc92016-06-15 23:27:04 -04001145// Verify that using invariant(all) in both shaders fails in ESSL 3.00.
1146TEST_P(GLSLTest_ES3, InvariantAllBoth)
1147{
1148 const std::string fragmentShaderSource =
1149 "#version 300 es\n"
1150 "#pragma STDGL invariant(all)\n"
1151 "precision mediump float;\n"
1152 "in float v_varying;\n"
1153 "out vec4 my_FragColor;\n"
1154 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1155
1156 const std::string vertexShaderSource =
1157 "#version 300 es\n"
1158 "#pragma STDGL invariant(all)\n"
1159 "in vec4 a_position;\n"
1160 "out float v_varying;\n"
1161 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1162
1163 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1164 EXPECT_EQ(0u, program);
1165}
1166
1167// Verify that using invariant(all) only in fragment shader fails in ESSL 1.00.
1168TEST_P(GLSLTest, InvariantAllIn)
1169{
1170 const std::string fragmentShaderSource =
1171 "#pragma STDGL invariant(all)\n"
1172 "precision mediump float;\n"
1173 "varying float v_varying;\n"
1174 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1175
1176 const std::string vertexShaderSource =
1177 "attribute vec4 a_position;\n"
1178 "varying float v_varying;\n"
1179 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1180
1181 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1182 EXPECT_EQ(0u, program);
1183}
1184
1185// Verify that using invariant(all) only in fragment shader fails in ESSL 3.00.
1186TEST_P(GLSLTest_ES3, InvariantAllIn)
1187{
1188 const std::string fragmentShaderSource =
1189 "#version 300 es\n"
1190 "#pragma STDGL invariant(all)\n"
1191 "precision mediump float;\n"
1192 "in float v_varying;\n"
1193 "out vec4 my_FragColor;\n"
1194 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1195
1196 const std::string vertexShaderSource =
1197 "#version 300 es\n"
1198 "in vec4 a_position;\n"
1199 "out float v_varying;\n"
1200 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1201
1202 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1203 EXPECT_EQ(0u, program);
1204}
1205
1206// Verify that using invariant(all) only in vertex shader fails in ESSL 1.00.
1207TEST_P(GLSLTest, InvariantAllOut)
1208{
1209 const std::string fragmentShaderSource =
1210 "precision mediump float;\n"
1211 "varying float v_varying;\n"
1212 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1213
1214 const std::string vertexShaderSource =
1215 "#pragma STDGL invariant(all)\n"
1216 "attribute vec4 a_position;\n"
1217 "varying float v_varying;\n"
1218 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1219
1220 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1221 EXPECT_EQ(0u, program);
1222}
1223
1224// Verify that using invariant(all) only in vertex shader succeeds in ESSL 3.00.
1225TEST_P(GLSLTest_ES3, InvariantAllOut)
1226{
1227 // TODO: ESSL 3.00 -> GLSL 1.20 translation should add "invariant" in fragment shader
1228 // for varyings which are invariant in vertex shader,
1229 // because of invariant(all) being used in vertex shader (http://anglebug.com/1293)
Corentin Wallezc7f59d02016-06-20 10:12:08 -04001230 if (IsDesktopOpenGL())
Yuly Novikova1f6dc92016-06-15 23:27:04 -04001231 {
1232 std::cout << "Test disabled on OpenGL." << std::endl;
1233 return;
1234 }
1235
1236 const std::string fragmentShaderSource =
1237 "#version 300 es\n"
1238 "precision mediump float;\n"
1239 "in float v_varying;\n"
1240 "out vec4 my_FragColor;\n"
1241 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1242
1243 const std::string vertexShaderSource =
1244 "#version 300 es\n"
1245 "#pragma STDGL invariant(all)\n"
1246 "in vec4 a_position;\n"
1247 "out float v_varying;\n"
1248 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1249
1250 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1251 EXPECT_NE(0u, program);
1252}
1253
Jamie Madillfa05f602015-05-07 13:47:11 -04001254TEST_P(GLSLTest, MaxVaryingVec4)
Austin Kinross8b695ee2015-03-12 13:12:20 -07001255{
Geoff Lang69accbd2016-01-25 16:22:32 -05001256#if defined(__APPLE__)
1257 // TODO(geofflang): Find out why this doesn't compile on Apple AND OpenGL drivers
1258 // (http://anglebug.com/1291)
Jamie Madill518b9fa2016-03-02 11:26:02 -05001259 if (IsAMD() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
Geoff Lang69accbd2016-01-25 16:22:32 -05001260 {
1261 std::cout << "Test disabled on Apple AMD OpenGL." << std::endl;
1262 return;
1263 }
1264#endif
1265
Austin Kinross8b695ee2015-03-12 13:12:20 -07001266 GLint maxVaryings = 0;
1267 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1268
1269 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, false, false, false, true);
1270}
1271
Jamie Madillfa05f602015-05-07 13:47:11 -04001272TEST_P(GLSLTest, MaxMinusTwoVaryingVec4PlusTwoSpecialVariables)
Austin Kinross8b695ee2015-03-12 13:12:20 -07001273{
1274 GLint maxVaryings = 0;
1275 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1276
1277 // Generate shader code that uses gl_FragCoord and gl_PointCoord, two special fragment shader variables.
1278 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 2, 0, true, true, false, true);
1279}
1280
Jamie Madillfa05f602015-05-07 13:47:11 -04001281TEST_P(GLSLTest, MaxMinusTwoVaryingVec4PlusThreeSpecialVariables)
Austin Kinross8b695ee2015-03-12 13:12:20 -07001282{
Geoff Lange0cc2a42016-01-20 10:58:17 -05001283 // TODO(geofflang): Figure out why this fails on OpenGL AMD (http://anglebug.com/1291)
Jamie Madill518b9fa2016-03-02 11:26:02 -05001284 if (IsAMD() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
Geoff Lange0cc2a42016-01-20 10:58:17 -05001285 {
1286 std::cout << "Test disabled on OpenGL." << std::endl;
1287 return;
1288 }
1289
Austin Kinross8b695ee2015-03-12 13:12:20 -07001290 GLint maxVaryings = 0;
1291 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1292
1293 // Generate shader code that uses gl_FragCoord, gl_PointCoord and gl_PointSize.
1294 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 2, 0, true, true, true, true);
1295}
1296
Jamie Madillfa05f602015-05-07 13:47:11 -04001297TEST_P(GLSLTest, MaxVaryingVec3)
Austin Kinrossaf875522014-08-25 21:06:07 -07001298{
1299 GLint maxVaryings = 0;
1300 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1301
Austin Kinross8b695ee2015-03-12 13:12:20 -07001302 VaryingTestBase(0, 0, 0, 0, maxVaryings, 0, 0, 0, false, false, false, true);
Austin Kinrossaf875522014-08-25 21:06:07 -07001303}
1304
Jamie Madillfa05f602015-05-07 13:47:11 -04001305TEST_P(GLSLTest, MaxVaryingVec3Array)
Austin Kinrossaf875522014-08-25 21:06:07 -07001306{
1307 GLint maxVaryings = 0;
1308 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1309
Austin Kinross8b695ee2015-03-12 13:12:20 -07001310 VaryingTestBase(0, 0, 0, 0, 0, maxVaryings / 2, 0, 0, false, false, false, true);
Austin Kinrossaf875522014-08-25 21:06:07 -07001311}
1312
Jamie Madillbee59e02014-10-02 10:44:18 -04001313// Disabled because of a failure in D3D9
Jamie Madill9fc36822015-11-18 13:08:07 -05001314TEST_P(GLSLTest, MaxVaryingVec3AndOneFloat)
Austin Kinrossaf875522014-08-25 21:06:07 -07001315{
Jamie Madill518b9fa2016-03-02 11:26:02 -05001316 if (IsD3D9())
Jamie Madill9fc36822015-11-18 13:08:07 -05001317 {
1318 std::cout << "Test disabled on D3D9." << std::endl;
1319 return;
1320 }
1321
Austin Kinrossaf875522014-08-25 21:06:07 -07001322 GLint maxVaryings = 0;
1323 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1324
Austin Kinross8b695ee2015-03-12 13:12:20 -07001325 VaryingTestBase(1, 0, 0, 0, maxVaryings, 0, 0, 0, false, false, false, true);
Austin Kinrossaf875522014-08-25 21:06:07 -07001326}
1327
Jamie Madillbee59e02014-10-02 10:44:18 -04001328// Disabled because of a failure in D3D9
Jamie Madill9fc36822015-11-18 13:08:07 -05001329TEST_P(GLSLTest, MaxVaryingVec3ArrayAndOneFloatArray)
Austin Kinrossaf875522014-08-25 21:06:07 -07001330{
Jamie Madill518b9fa2016-03-02 11:26:02 -05001331 if (IsD3D9())
Jamie Madill9fc36822015-11-18 13:08:07 -05001332 {
1333 std::cout << "Test disabled on D3D9." << std::endl;
1334 return;
1335 }
1336
Austin Kinrossaf875522014-08-25 21:06:07 -07001337 GLint maxVaryings = 0;
1338 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1339
Austin Kinross8b695ee2015-03-12 13:12:20 -07001340 VaryingTestBase(0, 1, 0, 0, 0, maxVaryings / 2, 0, 0, false, false, false, true);
Austin Kinrossaf875522014-08-25 21:06:07 -07001341}
1342
Jamie Madillbee59e02014-10-02 10:44:18 -04001343// Disabled because of a failure in D3D9
Jamie Madill9fc36822015-11-18 13:08:07 -05001344TEST_P(GLSLTest, TwiceMaxVaryingVec2)
Austin Kinrossaf875522014-08-25 21:06:07 -07001345{
Jamie Madill518b9fa2016-03-02 11:26:02 -05001346 if (IsD3D9())
Jamie Madill9fc36822015-11-18 13:08:07 -05001347 {
1348 std::cout << "Test disabled on D3D9." << std::endl;
1349 return;
1350 }
1351
Geoff Lange0cc2a42016-01-20 10:58:17 -05001352 if (getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
1353 {
1354 // TODO(geofflang): Figure out why this fails on NVIDIA's GLES driver
1355 std::cout << "Test disabled on OpenGL ES." << std::endl;
1356 return;
1357 }
1358
Geoff Lang69accbd2016-01-25 16:22:32 -05001359#if defined(__APPLE__)
1360 // TODO(geofflang): Find out why this doesn't compile on Apple AND OpenGL drivers
1361 // (http://anglebug.com/1291)
Jamie Madill518b9fa2016-03-02 11:26:02 -05001362 if (IsAMD() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
Geoff Lang69accbd2016-01-25 16:22:32 -05001363 {
1364 std::cout << "Test disabled on Apple AMD OpenGL." << std::endl;
1365 return;
1366 }
1367#endif
1368
Austin Kinrossaf875522014-08-25 21:06:07 -07001369 GLint maxVaryings = 0;
1370 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1371
Austin Kinross8b695ee2015-03-12 13:12:20 -07001372 VaryingTestBase(0, 0, 2 * maxVaryings, 0, 0, 0, 0, 0, false, false, false, true);
Austin Kinrossaf875522014-08-25 21:06:07 -07001373}
1374
Jamie Madillbee59e02014-10-02 10:44:18 -04001375// Disabled because of a failure in D3D9
Jamie Madill9fc36822015-11-18 13:08:07 -05001376TEST_P(GLSLTest, MaxVaryingVec2Arrays)
Austin Kinrossaf875522014-08-25 21:06:07 -07001377{
Jamie Madill518b9fa2016-03-02 11:26:02 -05001378 if (IsD3DSM3())
Jamie Madill9fc36822015-11-18 13:08:07 -05001379 {
1380 std::cout << "Test disabled on SM3." << std::endl;
1381 return;
1382 }
1383
Geoff Lange0cc2a42016-01-20 10:58:17 -05001384 if (getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
1385 {
1386 // TODO(geofflang): Figure out why this fails on NVIDIA's GLES driver
1387 std::cout << "Test disabled on OpenGL ES." << std::endl;
1388 return;
1389 }
1390
Geoff Lang69accbd2016-01-25 16:22:32 -05001391#if defined(__APPLE__)
1392 // TODO(geofflang): Find out why this doesn't compile on Apple AND OpenGL drivers
1393 // (http://anglebug.com/1291)
Jamie Madill518b9fa2016-03-02 11:26:02 -05001394 if (IsAMD() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
Geoff Lang69accbd2016-01-25 16:22:32 -05001395 {
1396 std::cout << "Test disabled on Apple AMD OpenGL." << std::endl;
1397 return;
1398 }
1399#endif
1400
Austin Kinrossaf875522014-08-25 21:06:07 -07001401 GLint maxVaryings = 0;
1402 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
1403
Jamie Madill192745a2016-12-22 15:58:21 -05001404 // Special case: because arrays of mat2 are packed as small grids of two rows by two columns,
1405 // we should be aware that when we're packing into an odd number of varying registers the
1406 // last row will be empty and can not fit the final vec2 arrary.
1407 GLint maxVec2Arrays = (maxVaryings >> 1) << 1;
1408
1409 VaryingTestBase(0, 0, 0, maxVec2Arrays, 0, 0, 0, 0, false, false, false, true);
Austin Kinrossaf875522014-08-25 21:06:07 -07001410}
1411
Geoff Langf60fab62014-11-24 11:21:20 -05001412// Verify shader source with a fixed length that is less than the null-terminated length will compile.
Jamie Madillfa05f602015-05-07 13:47:11 -04001413TEST_P(GLSLTest, FixedShaderLength)
Geoff Langf60fab62014-11-24 11:21:20 -05001414{
1415 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1416
1417 const std::string appendGarbage = "abcasdfasdfasdfasdfasdf";
1418 const std::string source = "void main() { gl_FragColor = vec4(0, 0, 0, 0); }" + appendGarbage;
1419 const char *sourceArray[1] = { source.c_str() };
Corentin Wallez973402f2015-05-11 13:42:22 -04001420 GLint lengths[1] = { static_cast<GLint>(source.length() - appendGarbage.length()) };
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001421 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
Geoff Langf60fab62014-11-24 11:21:20 -05001422 glCompileShader(shader);
1423
1424 GLint compileResult;
1425 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1426 EXPECT_NE(compileResult, 0);
1427}
1428
1429// Verify that a negative shader source length is treated as a null-terminated length.
Jamie Madillfa05f602015-05-07 13:47:11 -04001430TEST_P(GLSLTest, NegativeShaderLength)
Geoff Langf60fab62014-11-24 11:21:20 -05001431{
1432 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1433
1434 const char *sourceArray[1] = { "void main() { gl_FragColor = vec4(0, 0, 0, 0); }" };
1435 GLint lengths[1] = { -10 };
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001436 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
Geoff Langf60fab62014-11-24 11:21:20 -05001437 glCompileShader(shader);
1438
1439 GLint compileResult;
1440 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1441 EXPECT_NE(compileResult, 0);
1442}
1443
Corentin Wallez9a9c0482016-04-12 10:36:25 -04001444// Check that having an invalid char after the "." doesn't cause an assert.
1445TEST_P(GLSLTest, InvalidFieldFirstChar)
1446{
1447 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
1448 const char *source = "void main() {vec4 x; x.}";
1449 glShaderSource(shader, 1, &source, 0);
1450 glCompileShader(shader);
1451
1452 GLint compileResult;
1453 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1454 EXPECT_EQ(0, compileResult);
1455}
1456
Geoff Langf60fab62014-11-24 11:21:20 -05001457// Verify that a length array with mixed positive and negative values compiles.
Jamie Madillfa05f602015-05-07 13:47:11 -04001458TEST_P(GLSLTest, MixedShaderLengths)
Geoff Langf60fab62014-11-24 11:21:20 -05001459{
1460 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1461
1462 const char *sourceArray[] =
1463 {
1464 "void main()",
1465 "{",
1466 " gl_FragColor = vec4(0, 0, 0, 0);",
1467 "}",
1468 };
1469 GLint lengths[] =
1470 {
1471 -10,
1472 1,
Corentin Wallez973402f2015-05-11 13:42:22 -04001473 static_cast<GLint>(strlen(sourceArray[2])),
Geoff Langf60fab62014-11-24 11:21:20 -05001474 -1,
1475 };
1476 ASSERT_EQ(ArraySize(sourceArray), ArraySize(lengths));
1477
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001478 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
Geoff Langf60fab62014-11-24 11:21:20 -05001479 glCompileShader(shader);
1480
1481 GLint compileResult;
1482 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1483 EXPECT_NE(compileResult, 0);
1484}
1485
1486// Verify that zero-length shader source does not affect shader compilation.
Jamie Madillfa05f602015-05-07 13:47:11 -04001487TEST_P(GLSLTest, ZeroShaderLength)
Geoff Langf60fab62014-11-24 11:21:20 -05001488{
1489 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1490
1491 const char *sourceArray[] =
1492 {
1493 "adfasdf",
1494 "34534",
1495 "void main() { gl_FragColor = vec4(0, 0, 0, 0); }",
1496 "",
1497 "asdfasdfsdsdf",
1498 };
1499 GLint lengths[] =
1500 {
1501 0,
1502 0,
1503 -1,
1504 0,
1505 0,
1506 };
1507 ASSERT_EQ(ArraySize(sourceArray), ArraySize(lengths));
1508
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001509 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
Geoff Langf60fab62014-11-24 11:21:20 -05001510 glCompileShader(shader);
1511
1512 GLint compileResult;
1513 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1514 EXPECT_NE(compileResult, 0);
1515}
Jamie Madill21c1e452014-12-29 11:33:41 -05001516
1517// Tests that bad index expressions don't crash ANGLE's translator.
1518// https://code.google.com/p/angleproject/issues/detail?id=857
Jamie Madillfa05f602015-05-07 13:47:11 -04001519TEST_P(GLSLTest, BadIndexBug)
Jamie Madill21c1e452014-12-29 11:33:41 -05001520{
1521 const std::string &fragmentShaderSourceVec =
1522 "precision mediump float;\n"
1523 "uniform vec4 uniformVec;\n"
1524 "void main()\n"
1525 "{\n"
1526 " gl_FragColor = vec4(uniformVec[int()]);\n"
1527 "}";
1528
1529 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, fragmentShaderSourceVec);
1530 EXPECT_EQ(0u, shader);
1531
1532 if (shader != 0)
1533 {
1534 glDeleteShader(shader);
1535 }
1536
1537 const std::string &fragmentShaderSourceMat =
1538 "precision mediump float;\n"
1539 "uniform mat4 uniformMat;\n"
1540 "void main()\n"
1541 "{\n"
1542 " gl_FragColor = vec4(uniformMat[int()]);\n"
1543 "}";
1544
1545 shader = CompileShader(GL_FRAGMENT_SHADER, fragmentShaderSourceMat);
1546 EXPECT_EQ(0u, shader);
1547
1548 if (shader != 0)
1549 {
1550 glDeleteShader(shader);
1551 }
1552
1553 const std::string &fragmentShaderSourceArray =
1554 "precision mediump float;\n"
1555 "uniform vec4 uniformArray;\n"
1556 "void main()\n"
1557 "{\n"
1558 " gl_FragColor = vec4(uniformArray[int()]);\n"
1559 "}";
1560
1561 shader = CompileShader(GL_FRAGMENT_SHADER, fragmentShaderSourceArray);
1562 EXPECT_EQ(0u, shader);
1563
1564 if (shader != 0)
1565 {
1566 glDeleteShader(shader);
1567 }
Jamie Madill37997142015-01-28 10:06:34 -05001568}
1569
Jamie Madill2e295e22015-04-29 10:41:33 -04001570// Test that structs defined in uniforms are translated correctly.
Jamie Madillfa05f602015-05-07 13:47:11 -04001571TEST_P(GLSLTest, StructSpecifiersUniforms)
Jamie Madill2e295e22015-04-29 10:41:33 -04001572{
1573 const std::string fragmentShaderSource = SHADER_SOURCE
1574 (
1575 precision mediump float;
1576
1577 uniform struct S { float field;} s;
1578
1579 void main()
1580 {
1581 gl_FragColor = vec4(1, 0, 0, 1);
1582 gl_FragColor.a += s.field;
1583 }
1584 );
1585
1586 GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
1587 EXPECT_NE(0u, program);
1588}
Jamie Madill55def582015-05-04 11:24:57 -04001589
1590// Test that gl_DepthRange is not stored as a uniform location. Since uniforms
1591// beginning with "gl_" are filtered out by our validation logic, we must
1592// bypass the validation to test the behaviour of the implementation.
1593// (note this test is still Impl-independent)
Jamie Madille1faacb2016-12-13 12:42:14 -05001594TEST_P(GLSLTestNoValidation, DepthRangeUniforms)
Jamie Madill55def582015-05-04 11:24:57 -04001595{
1596 const std::string fragmentShaderSource = SHADER_SOURCE
1597 (
1598 precision mediump float;
1599
1600 void main()
1601 {
1602 gl_FragColor = vec4(gl_DepthRange.near, gl_DepthRange.far, gl_DepthRange.diff, 1);
1603 }
1604 );
1605
Jamie Madille1faacb2016-12-13 12:42:14 -05001606 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShaderSource);
Jamie Madill55def582015-05-04 11:24:57 -04001607
Jamie Madille1faacb2016-12-13 12:42:14 -05001608 // We need to bypass validation for this call.
1609 GLint nearIndex = glGetUniformLocation(program.get(), "gl_DepthRange.near");
Jamie Madill55def582015-05-04 11:24:57 -04001610 EXPECT_EQ(-1, nearIndex);
1611
1612 // Test drawing does not throw an exception.
Jamie Madille1faacb2016-12-13 12:42:14 -05001613 drawQuad(program.get(), "inputAttribute", 0.5f);
Jamie Madill55def582015-05-04 11:24:57 -04001614
1615 EXPECT_GL_NO_ERROR();
Jamie Madill55def582015-05-04 11:24:57 -04001616}
Jamie Madill4052dfc2015-05-06 15:18:49 -04001617
Jamie Madill6c9503e2016-08-16 14:06:32 -04001618std::string GenerateSmallPowShader(double base, double exponent)
1619{
1620 std::stringstream stream;
1621
1622 stream.precision(8);
1623
1624 double result = pow(base, exponent);
1625
1626 stream << "precision highp float;\n"
1627 << "float fun(float arg)\n"
1628 << "{\n"
1629 << " return pow(arg, " << std::fixed << exponent << ");\n"
1630 << "}\n"
1631 << "\n"
1632 << "void main()\n"
1633 << "{\n"
1634 << " const float a = " << std::scientific << base << ";\n"
1635 << " float b = fun(a);\n"
1636 << " if (abs(" << result << " - b) < " << std::abs(result * 0.001) << ")\n"
1637 << " {\n"
1638 << " gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
1639 << " }\n"
1640 << " else\n"
1641 << " {\n"
1642 << " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
1643 << " }\n"
1644 << "}\n";
1645
1646 return stream.str();
1647}
1648
Jamie Madill4052dfc2015-05-06 15:18:49 -04001649// Covers the WebGL test 'glsl/bugs/pow-of-small-constant-in-user-defined-function'
Jamie Madill1048e432016-07-23 18:51:28 -04001650// See http://anglebug.com/851
1651TEST_P(GLSLTest, PowOfSmallConstant)
Jamie Madill4052dfc2015-05-06 15:18:49 -04001652{
Jamie Madill6c9503e2016-08-16 14:06:32 -04001653 std::vector<double> bads;
1654 for (int eps = -1; eps <= 1; ++eps)
1655 {
1656 for (int i = -4; i <= 5; ++i)
Jamie Madill4052dfc2015-05-06 15:18:49 -04001657 {
Jamie Madill6c9503e2016-08-16 14:06:32 -04001658 if (i >= -1 && i <= 1)
1659 continue;
1660 const double epsilon = 1.0e-8;
1661 double bad = static_cast<double>(i) + static_cast<double>(eps) * epsilon;
1662 bads.push_back(bad);
Jamie Madill4052dfc2015-05-06 15:18:49 -04001663 }
Jamie Madill6c9503e2016-08-16 14:06:32 -04001664 }
Jamie Madill4052dfc2015-05-06 15:18:49 -04001665
Jamie Madill6c9503e2016-08-16 14:06:32 -04001666 for (double bad : bads)
1667 {
1668 const std::string &fragmentShaderSource = GenerateSmallPowShader(1.0e-6, bad);
Jamie Madill4052dfc2015-05-06 15:18:49 -04001669
Jamie Madill6c9503e2016-08-16 14:06:32 -04001670 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShaderSource);
Jamie Madill4052dfc2015-05-06 15:18:49 -04001671
Jamie Madill6c9503e2016-08-16 14:06:32 -04001672 drawQuad(program.get(), "inputAttribute", 0.5f);
1673
1674 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1675 EXPECT_GL_NO_ERROR();
1676 }
Jamie Madill4052dfc2015-05-06 15:18:49 -04001677}
Jamie Madillfa05f602015-05-07 13:47:11 -04001678
Cooper Partina5ef8d82015-08-19 14:52:21 -07001679// Test that fragment shaders which contain non-constant loop indexers and compiled for FL9_3 and
1680// below
1681// fail with a specific error message.
1682// Additionally test that the same fragment shader compiles successfully with feature levels greater
1683// than FL9_3.
1684TEST_P(GLSLTest, LoopIndexingValidation)
1685{
1686 const std::string fragmentShaderSource = SHADER_SOURCE
1687 (
1688 precision mediump float;
1689
1690 uniform float loopMax;
1691
1692 void main()
1693 {
1694 gl_FragColor = vec4(1, 0, 0, 1);
1695 for (float l = 0.0; l < loopMax; l++)
1696 {
1697 if (loopMax > 3.0)
1698 {
1699 gl_FragColor.a += 0.1;
1700 }
1701 }
1702 }
1703 );
1704
1705 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
1706
1707 const char *sourceArray[1] = {fragmentShaderSource.c_str()};
1708 glShaderSource(shader, 1, sourceArray, nullptr);
1709 glCompileShader(shader);
1710
1711 GLint compileResult;
1712 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
1713
1714 // If the test is configured to run limited to Feature Level 9_3, then it is
1715 // assumed that shader compilation will fail with an expected error message containing
1716 // "Loop index cannot be compared with non-constant expression"
Olli Etuaho814a54d2015-08-27 16:23:09 +03001717 if ((GetParam() == ES2_D3D11_FL9_3() || GetParam() == ES2_D3D9()))
Cooper Partina5ef8d82015-08-19 14:52:21 -07001718 {
1719 if (compileResult != 0)
1720 {
1721 FAIL() << "Shader compilation succeeded, expected failure";
1722 }
1723 else
1724 {
1725 GLint infoLogLength;
1726 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
1727
1728 std::string infoLog;
1729 infoLog.resize(infoLogLength);
Yunchao Hef81ce4a2017-04-24 10:49:17 +08001730 glGetShaderInfoLog(shader, static_cast<GLsizei>(infoLog.size()), nullptr, &infoLog[0]);
Cooper Partina5ef8d82015-08-19 14:52:21 -07001731
1732 if (infoLog.find("Loop index cannot be compared with non-constant expression") ==
1733 std::string::npos)
1734 {
1735 FAIL() << "Shader compilation failed with unexpected error message";
1736 }
1737 }
1738 }
1739 else
1740 {
1741 EXPECT_NE(0, compileResult);
1742 }
1743
1744 if (shader != 0)
1745 {
1746 glDeleteShader(shader);
1747 }
1748}
1749
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001750// Tests that the maximum uniforms count returned from querying GL_MAX_VERTEX_UNIFORM_VECTORS
1751// can actually be used.
1752TEST_P(GLSLTest, VerifyMaxVertexUniformVectors)
1753{
Zhenyao Mo1a256722017-01-12 11:52:57 -08001754 if (IsLinux() && IsIntel())
1755 {
1756 std::cout << "Test timed out on Linux Intel. See crbug.com/680631." << std::endl;
1757 return;
1758 }
1759
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001760 int maxUniforms = 10000;
1761 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
1762 EXPECT_GL_NO_ERROR();
1763 std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS = " << maxUniforms << std::endl;
1764
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001765 CompileGLSLWithUniformsAndSamplers(maxUniforms, 0, 0, 0, true);
1766}
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001767
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001768// Tests that the maximum uniforms count returned from querying GL_MAX_VERTEX_UNIFORM_VECTORS
1769// can actually be used along with the maximum number of texture samplers.
1770TEST_P(GLSLTest, VerifyMaxVertexUniformVectorsWithSamplers)
1771{
Geoff Lange0cc2a42016-01-20 10:58:17 -05001772 if (GetParam().eglParameters.renderer == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE ||
1773 GetParam().eglParameters.renderer == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
1774 {
1775 std::cout << "Test disabled on OpenGL." << std::endl;
1776 return;
1777 }
1778
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001779 int maxUniforms = 10000;
1780 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
1781 EXPECT_GL_NO_ERROR();
1782 std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS = " << maxUniforms << std::endl;
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001783
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001784 int maxTextureImageUnits = 0;
1785 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001786
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001787 CompileGLSLWithUniformsAndSamplers(maxUniforms, 0, maxTextureImageUnits, 0, true);
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001788}
1789
1790// Tests that the maximum uniforms count + 1 from querying GL_MAX_VERTEX_UNIFORM_VECTORS
1791// fails shader compilation.
1792TEST_P(GLSLTest, VerifyMaxVertexUniformVectorsExceeded)
1793{
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001794 int maxUniforms = 10000;
1795 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
1796 EXPECT_GL_NO_ERROR();
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001797 std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS + 1 = " << maxUniforms + 1 << std::endl;
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001798
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001799 CompileGLSLWithUniformsAndSamplers(maxUniforms + 1, 0, 0, 0, false);
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001800}
1801
1802// Tests that the maximum uniforms count returned from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
1803// can actually be used.
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001804TEST_P(GLSLTest, VerifyMaxFragmentUniformVectors)
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001805{
Zhenyao Mo1a256722017-01-12 11:52:57 -08001806 if (IsLinux() && IsIntel())
1807 {
1808 std::cout << "Test timed out on Linux Intel. See crbug.com/680631." << std::endl;
1809 return;
1810 }
1811
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001812 int maxUniforms = 10000;
1813 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
1814 EXPECT_GL_NO_ERROR();
1815 std::cout << "Validating GL_MAX_FRAGMENT_UNIFORM_VECTORS = " << maxUniforms << std::endl;
1816
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001817 CompileGLSLWithUniformsAndSamplers(0, maxUniforms, 0, 0, true);
1818}
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001819
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001820// Tests that the maximum uniforms count returned from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
1821// can actually be used along with the maximum number of texture samplers.
1822TEST_P(GLSLTest, VerifyMaxFragmentUniformVectorsWithSamplers)
1823{
Geoff Lange0cc2a42016-01-20 10:58:17 -05001824 if (GetParam().eglParameters.renderer == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE ||
1825 GetParam().eglParameters.renderer == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
1826 {
1827 std::cout << "Test disabled on OpenGL." << std::endl;
1828 return;
1829 }
1830
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001831 int maxUniforms = 10000;
1832 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
1833 EXPECT_GL_NO_ERROR();
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001834
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001835 int maxTextureImageUnits = 0;
1836 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001837
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001838 CompileGLSLWithUniformsAndSamplers(0, maxUniforms, 0, maxTextureImageUnits, true);
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001839}
1840
1841// Tests that the maximum uniforms count + 1 from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
1842// fails shader compilation.
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001843TEST_P(GLSLTest, VerifyMaxFragmentUniformVectorsExceeded)
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001844{
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001845 int maxUniforms = 10000;
1846 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
1847 EXPECT_GL_NO_ERROR();
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001848 std::cout << "Validating GL_MAX_FRAGMENT_UNIFORM_VECTORS + 1 = " << maxUniforms + 1
1849 << std::endl;
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001850
Austin Kinross7a3e8e22015-10-08 15:50:06 -07001851 CompileGLSLWithUniformsAndSamplers(0, maxUniforms + 1, 0, 0, false);
Cooper Partin69f9b2c2015-08-20 13:25:41 -07001852}
1853
Geoff Langba992ab2017-04-19 11:18:14 -04001854// Test compiling shaders using the GL_EXT_shader_texture_lod extension
1855TEST_P(GLSLTest, TextureLOD)
1856{
1857 if (!extensionEnabled("GL_EXT_shader_texture_lod"))
1858 {
1859 std::cout << "Test skipped due to missing GL_EXT_shader_texture_lod." << std::endl;
1860 return;
1861 }
1862
1863 const std::string source =
1864 "#extension GL_EXT_shader_texture_lod : require\n"
1865 "uniform sampler2D u_texture;\n"
1866 "void main() {\n"
1867 " gl_FragColor = texture2DGradEXT(u_texture, vec2(0.0, 0.0), vec2(0.0, 0.0), vec2(0.0, "
1868 "0.0));\n"
1869 "}\n";
1870
1871 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, source);
1872 ASSERT_NE(0u, shader);
1873 glDeleteShader(shader);
1874}
1875
Olli Etuahobe59c2f2016-03-07 11:32:34 +02001876// Test that two constructors which have vec4 and mat2 parameters get disambiguated (issue in
1877// HLSL).
1878TEST_P(GLSLTest_ES3, AmbiguousConstructorCall2x2)
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 vec4 a_vec;\n"
1893 "in mat2 a_mat;\n"
1894 "void main()\n"
1895 "{\n"
1896 " gl_Position = vec4(a_vec) + vec4(a_mat);\n"
1897 "}";
1898
1899 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1900 EXPECT_NE(0u, program);
1901}
1902
1903// Test that two constructors which have mat2x3 and mat3x2 parameters get disambiguated.
1904// This was suspected to be an issue in HLSL, but HLSL seems to be able to natively choose between
1905// the function signatures in this case.
1906TEST_P(GLSLTest_ES3, AmbiguousConstructorCall2x3)
1907{
1908 const std::string fragmentShaderSource =
1909 "#version 300 es\n"
1910 "precision highp float;\n"
1911 "out vec4 my_FragColor;\n"
1912 "void main()\n"
1913 "{\n"
1914 " my_FragColor = vec4(0.0);\n"
1915 "}";
1916
1917 const std::string vertexShaderSource =
1918 "#version 300 es\n"
1919 "precision highp float;\n"
1920 "in mat3x2 a_matA;\n"
1921 "in mat2x3 a_matB;\n"
1922 "void main()\n"
1923 "{\n"
1924 " gl_Position = vec4(a_matA) + vec4(a_matB);\n"
1925 "}";
1926
1927 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1928 EXPECT_NE(0u, program);
1929}
1930
1931// Test that two functions which have vec4 and mat2 parameters get disambiguated (issue in HLSL).
1932TEST_P(GLSLTest_ES3, AmbiguousFunctionCall2x2)
1933{
1934 const std::string fragmentShaderSource =
1935 "#version 300 es\n"
1936 "precision highp float;\n"
1937 "out vec4 my_FragColor;\n"
1938 "void main()\n"
1939 "{\n"
1940 " my_FragColor = vec4(0.0);\n"
1941 "}";
1942
1943 const std::string vertexShaderSource =
1944 "#version 300 es\n"
1945 "precision highp float;\n"
1946 "in vec4 a_vec;\n"
1947 "in mat2 a_mat;\n"
1948 "vec4 foo(vec4 a)\n"
1949 "{\n"
1950 " return a;\n"
1951 "}\n"
1952 "vec4 foo(mat2 a)\n"
1953 "{\n"
1954 " return vec4(a[0][0]);\n"
1955 "}\n"
1956 "void main()\n"
1957 "{\n"
1958 " gl_Position = foo(a_vec) + foo(a_mat);\n"
1959 "}";
1960
1961 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
1962 EXPECT_NE(0u, program);
1963}
1964
1965// Test that an user-defined function with a large number of float4 parameters doesn't fail due to
1966// the function name being too long.
1967TEST_P(GLSLTest_ES3, LargeNumberOfFloat4Parameters)
1968{
1969 const std::string fragmentShaderSource =
1970 "#version 300 es\n"
1971 "precision highp float;\n"
1972 "out vec4 my_FragColor;\n"
1973 "void main()\n"
1974 "{\n"
1975 " my_FragColor = vec4(0.0);\n"
1976 "}";
1977
1978 std::stringstream vertexShaderStream;
1979 const unsigned int paramCount = 1024u;
1980
1981 vertexShaderStream << "#version 300 es\n"
1982 "precision highp float;\n"
1983 "in vec4 a_vec;\n"
1984 "vec4 lotsOfVec4Parameters(";
1985 for (unsigned int i = 0; i < paramCount; ++i)
1986 {
1987 vertexShaderStream << "vec4 a" << i << ", ";
1988 }
1989 vertexShaderStream << "vec4 aLast)\n"
1990 "{\n"
1991 " return ";
1992 for (unsigned int i = 0; i < paramCount; ++i)
1993 {
1994 vertexShaderStream << "a" << i << " + ";
1995 }
1996 vertexShaderStream << "aLast;\n"
1997 "}\n"
1998 "void main()\n"
1999 "{\n"
2000 " gl_Position = lotsOfVec4Parameters(";
2001 for (unsigned int i = 0; i < paramCount; ++i)
2002 {
2003 vertexShaderStream << "a_vec, ";
2004 }
2005 vertexShaderStream << "a_vec);\n"
2006 "}";
2007
2008 GLuint program = CompileProgram(vertexShaderStream.str(), fragmentShaderSource);
2009 EXPECT_NE(0u, program);
2010}
2011
Olli Etuahod4f4c112016-04-15 15:11:24 +03002012// This test was written specifically to stress DeferGlobalInitializers AST transformation.
2013// Test a shader where a global constant array is initialized with an expression containing array
2014// indexing. This initializer is tricky to constant fold, so if it's not constant folded it needs to
2015// be handled in a way that doesn't generate statements in the global scope in HLSL output.
2016// Also includes multiple array initializers in one declaration, where only the second one has
2017// array indexing. This makes sure that the qualifier for the declaration is set correctly if
2018// transformations are applied to the declaration also in the case of ESSL output.
2019TEST_P(GLSLTest_ES3, InitGlobalArrayWithArrayIndexing)
2020{
Yuly Novikov41db2242016-06-25 00:14:28 -04002021 // TODO(ynovikov): re-enable once root cause of http://anglebug.com/1428 is fixed
2022 if (IsAndroid() && IsAdreno() && IsOpenGLES())
2023 {
2024 std::cout << "Test skipped on Adreno OpenGLES on Android." << std::endl;
2025 return;
2026 }
2027
Olli Etuahod4f4c112016-04-15 15:11:24 +03002028 const std::string vertexShaderSource =
2029 "#version 300 es\n"
2030 "precision highp float;\n"
2031 "in vec4 a_vec;\n"
2032 "void main()\n"
2033 "{\n"
2034 " gl_Position = vec4(a_vec);\n"
2035 "}";
2036
2037 const std::string fragmentShaderSource =
2038 "#version 300 es\n"
2039 "precision highp float;\n"
2040 "out vec4 my_FragColor;\n"
2041 "const highp float f[2] = float[2](0.1, 0.2);\n"
2042 "const highp float[2] g = float[2](0.3, 0.4), h = float[2](0.5, f[1]);\n"
2043 "void main()\n"
2044 "{\n"
2045 " my_FragColor = vec4(h[1]);\n"
2046 "}";
2047
2048 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
2049 EXPECT_NE(0u, program);
2050}
2051
Corentin Wallez419bfc92016-06-28 10:54:45 -07002052// Test that index-constant sampler array indexing is supported.
2053TEST_P(GLSLTest, IndexConstantSamplerArrayIndexing)
2054{
2055 if (IsD3D11_FL93()) {
2056 std::cout << "Test skipped on D3D11 FL 9.3." << std::endl;
2057 return;
2058 }
2059
2060 const std::string vertexShaderSource =
2061 "attribute vec4 vPosition;\n"
2062 "void main()\n"
2063 "{\n"
2064 " gl_Position = vPosition;\n"
2065 "}";
2066
2067 const std::string fragmentShaderSource =
2068 "precision mediump float;\n"
2069 "uniform sampler2D uni[2];\n"
2070 "\n"
2071 "float zero(int x)\n"
2072 "{\n"
2073 " return float(x) - float(x);\n"
2074 "}\n"
2075 "\n"
2076 "void main()\n"
2077 "{\n"
2078 " vec4 c = vec4(0,0,0,0);\n"
2079 " for (int ii = 1; ii < 3; ++ii) {\n"
2080 " if (c.x > 255.0) {\n"
2081 " c.x = 255.0 + zero(ii);\n"
2082 " break;\n"
2083 " }\n"
2084 // Index the sampler array with a predictable loop index (index-constant) as opposed to
2085 // a true constant. This is valid in OpenGL ES but isn't in many Desktop OpenGL versions,
2086 // without an extension.
2087 " c += texture2D(uni[ii - 1], vec2(0.5, 0.5));\n"
2088 " }\n"
2089 " gl_FragColor = c;\n"
2090 "}";
2091
2092 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
2093 EXPECT_NE(0u, program);
2094}
2095
Corentin Wallezb00dcee2016-07-11 17:42:58 -04002096// Test that the #pragma directive is supported and doesn't trigger a compilation failure on the
2097// native driver. The only pragma that gets passed to the OpenGL driver is "invariant" but we don't
2098// want to test its behavior, so don't use any varyings.
2099TEST_P(GLSLTest, PragmaDirective)
2100{
2101 const std::string vertexShaderSource =
2102 "#pragma STDGL invariant(all)\n"
2103 "void main()\n"
2104 "{\n"
2105 " gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
2106 "}\n";
2107
2108 const std::string fragmentShaderSource =
2109 "precision mediump float;\n"
2110 "void main()\n"
2111 "{\n"
2112 " gl_FragColor = vec4(1.0);\n"
2113 "}\n";
2114
2115 GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
2116 EXPECT_NE(0u, program);
2117}
2118
Olli Etuahoe1d199b2016-07-19 17:14:27 +03002119// Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
2120// The function call that returns the array needs to be evaluated after ++j for the expression to
2121// return the correct value (true).
2122TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderArray)
2123{
2124 const std::string &fragmentShaderSource =
2125 "#version 300 es\n"
2126 "precision mediump float;\n"
2127 "out vec4 my_FragColor; \n"
2128 "int[2] func(int param) {\n"
2129 " return int[2](param, param);\n"
2130 "}\n"
2131 "void main() {\n"
2132 " int a[2]; \n"
2133 " for (int i = 0; i < 2; ++i) {\n"
2134 " a[i] = 1;\n"
2135 " }\n"
2136 " int j = 0; \n"
2137 " bool result = ((++j), (a == func(j)));\n"
2138 " my_FragColor = vec4(0.0, (result ? 1.0 : 0.0), 0.0, 1.0);\n"
2139 "}\n";
2140
2141 GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
2142 ASSERT_NE(0u, program);
2143
2144 drawQuad(program, "inputAttribute", 0.5f);
2145
2146 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2147}
2148
2149// Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
2150// The short-circuiting expression needs to be evaluated after ++j for the expression to return the
2151// correct value (true).
2152TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderShortCircuit)
2153{
2154 const std::string &fragmentShaderSource =
2155 "#version 300 es\n"
2156 "precision mediump float;\n"
2157 "out vec4 my_FragColor; \n"
2158 "void main() {\n"
2159 " int j = 0; \n"
2160 " bool result = ((++j), (j == 1 ? true : (++j == 3)));\n"
2161 " my_FragColor = vec4(0.0, ((result && j == 1) ? 1.0 : 0.0), 0.0, 1.0);\n"
2162 "}\n";
2163
2164 GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
2165 ASSERT_NE(0u, program);
2166
2167 drawQuad(program, "inputAttribute", 0.5f);
2168
2169 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2170}
2171
Jamie Madill666f65a2016-08-26 01:34:37 +00002172// Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
2173// Indexing the vector needs to be evaluated after func() for the right result.
2174TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderDynamicVectorIndexingInLValue)
2175{
2176 const std::string &fragmentShaderSource =
2177 "#version 300 es\n"
2178 "precision mediump float;\n"
2179 "out vec4 my_FragColor;\n"
2180 "uniform int u_zero;\n"
2181 "int sideEffectCount = 0;\n"
2182 "float func() {\n"
2183 " ++sideEffectCount;\n"
2184 " return -1.0;\n"
2185 "}\n"
2186 "void main() {\n"
2187 " vec4 v = vec4(0.0, 2.0, 4.0, 6.0); \n"
2188 " float f = (func(), (++v[u_zero + sideEffectCount]));\n"
2189 " bool green = abs(f - 3.0) < 0.01 && abs(v[1] - 3.0) < 0.01 && sideEffectCount == 1;\n"
2190 " my_FragColor = vec4(0.0, (green ? 1.0 : 0.0), 0.0, 1.0);\n"
2191 "}\n";
2192
2193 GLuint program = CompileProgram(mSimpleVSSource, fragmentShaderSource);
2194 ASSERT_NE(0u, program);
2195
2196 drawQuad(program, "inputAttribute", 0.5f);
2197
2198 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2199}
2200
Jamie Madillc9bde922016-07-24 17:58:50 -04002201// Test that using gl_PointCoord with GL_TRIANGLES doesn't produce a link error.
2202// From WebGL test conformance/rendering/point-specific-shader-variables.html
2203// See http://anglebug.com/1380
2204TEST_P(GLSLTest, RenderTrisWithPointCoord)
2205{
2206 const std::string &vert =
2207 "attribute vec2 aPosition;\n"
2208 "void main()\n"
2209 "{\n"
2210 " gl_Position = vec4(aPosition, 0, 1);\n"
2211 " gl_PointSize = 1.0;\n"
2212 "}";
2213 const std::string &frag =
2214 "void main()\n"
2215 "{\n"
2216 " gl_FragColor = vec4(gl_PointCoord.xy, 0, 1);\n"
2217 " gl_FragColor = vec4(0, 1, 0, 1);\n"
2218 "}";
2219
2220 ANGLE_GL_PROGRAM(prog, vert, frag);
2221 drawQuad(prog.get(), "aPosition", 0.5f);
2222 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2223}
2224
Jamie Madill5655b842016-08-02 11:00:07 -04002225// Convers a bug with the integer pow statement workaround.
2226TEST_P(GLSLTest, NestedPowStatements)
2227{
2228 const std::string &vert =
2229 "attribute vec2 position;\n"
2230 "void main()\n"
2231 "{\n"
2232 " gl_Position = vec4(position, 0, 1);\n"
2233 "}";
2234 const std::string &frag =
2235 "precision mediump float;\n"
2236 "float func(float v)\n"
2237 "{\n"
2238 " float f1 = pow(v, 2.0);\n"
2239 " return pow(f1 + v, 2.0);\n"
2240 "}\n"
2241 "void main()\n"
2242 "{\n"
2243 " float v = func(2.0);\n"
2244 " gl_FragColor = abs(v - 36.0) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
2245 "}";
2246
2247 ANGLE_GL_PROGRAM(prog, vert, frag);
2248 drawQuad(prog.get(), "position", 0.5f);
2249 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2250}
2251
Qiankun Miaof52fe932016-12-07 13:39:15 +08002252// Test that -float calculation is correct.
2253TEST_P(GLSLTest_ES3, UnaryMinusOperatorFloat)
2254{
Qiankun Miaof52fe932016-12-07 13:39:15 +08002255 const std::string &vert =
2256 "#version 300 es\n"
2257 "in highp vec4 position;\n"
2258 "void main() {\n"
2259 " gl_Position = position;\n"
2260 "}\n";
2261 const std::string &frag =
2262 "#version 300 es\n"
2263 "out highp vec4 o_color;\n"
2264 "void main() {\n"
2265 " highp float f = -1.0;\n"
2266 " // atan(tan(0.5), -f) should be 0.5.\n"
2267 " highp float v = atan(tan(0.5), -f);\n"
2268 " o_color = abs(v - 0.5) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
2269 "}\n";
2270
2271 ANGLE_GL_PROGRAM(prog, vert, frag);
2272 drawQuad(prog.get(), "position", 0.5f);
2273 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2274}
2275
Olli Etuahoda9fb092016-12-09 17:32:29 +00002276// Test that atan(vec2, vec2) calculation is correct.
2277TEST_P(GLSLTest_ES3, AtanVec2)
2278{
2279 const std::string &vert =
2280 "#version 300 es\n"
2281 "in highp vec4 position;\n"
2282 "void main() {\n"
2283 " gl_Position = position;\n"
2284 "}\n";
2285 const std::string &frag =
2286 "#version 300 es\n"
2287 "out highp vec4 o_color;\n"
2288 "void main() {\n"
2289 " highp float f = 1.0;\n"
2290 " // atan(tan(0.5), f) should be 0.5.\n"
2291 " highp vec2 v = atan(vec2(tan(0.5)), vec2(f));\n"
2292 " o_color = (abs(v[0] - 0.5) < 0.001 && abs(v[1] - 0.5) < 0.001) ? vec4(0, 1, 0, 1) : "
2293 "vec4(1, 0, 0, 1);\n"
2294 "}\n";
2295
2296 ANGLE_GL_PROGRAM(prog, vert, frag);
2297 drawQuad(prog.get(), "position", 0.5f);
2298 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2299}
2300
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002301// Convers a bug with the unary minus operator on signed integer workaround.
2302TEST_P(GLSLTest_ES3, UnaryMinusOperatorSignedInt)
2303{
2304 const std::string &vert =
2305 "#version 300 es\n"
2306 "in highp vec4 position;\n"
2307 "out mediump vec4 v_color;\n"
2308 "uniform int ui_one;\n"
2309 "uniform int ui_two;\n"
2310 "uniform int ui_three;\n"
2311 "void main() {\n"
2312 " int s[3];\n"
2313 " s[0] = ui_one;\n"
2314 " s[1] = -(-(-ui_two + 1) + 1);\n" // s[1] = -ui_two
2315 " s[2] = ui_three;\n"
2316 " int result = 0;\n"
2317 " for (int i = 0; i < ui_three; i++) {\n"
2318 " result += s[i];\n"
2319 " }\n"
2320 " v_color = (result == 2) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
2321 " gl_Position = position;\n"
2322 "}\n";
2323 const std::string &frag =
2324 "#version 300 es\n"
2325 "in mediump vec4 v_color;\n"
2326 "layout(location=0) out mediump vec4 o_color;\n"
2327 "void main() {\n"
2328 " o_color = v_color;\n"
2329 "}\n";
2330
2331 ANGLE_GL_PROGRAM(prog, vert, frag);
2332
Jamie Madille1faacb2016-12-13 12:42:14 -05002333 GLint oneIndex = glGetUniformLocation(prog.get(), "ui_one");
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002334 ASSERT_NE(-1, oneIndex);
Jamie Madille1faacb2016-12-13 12:42:14 -05002335 GLint twoIndex = glGetUniformLocation(prog.get(), "ui_two");
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002336 ASSERT_NE(-1, twoIndex);
Jamie Madille1faacb2016-12-13 12:42:14 -05002337 GLint threeIndex = glGetUniformLocation(prog.get(), "ui_three");
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002338 ASSERT_NE(-1, threeIndex);
2339 glUseProgram(prog.get());
2340 glUniform1i(oneIndex, 1);
2341 glUniform1i(twoIndex, 2);
2342 glUniform1i(threeIndex, 3);
2343
2344 drawQuad(prog.get(), "position", 0.5f);
2345 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2346}
2347
2348// Convers a bug with the unary minus operator on unsigned integer workaround.
2349TEST_P(GLSLTest_ES3, UnaryMinusOperatorUnsignedInt)
2350{
2351 const std::string &vert =
2352 "#version 300 es\n"
2353 "in highp vec4 position;\n"
2354 "out mediump vec4 v_color;\n"
2355 "uniform uint ui_one;\n"
2356 "uniform uint ui_two;\n"
2357 "uniform uint ui_three;\n"
2358 "void main() {\n"
2359 " uint s[3];\n"
2360 " s[0] = ui_one;\n"
2361 " s[1] = -(-(-ui_two + 1u) + 1u);\n" // s[1] = -ui_two
2362 " s[2] = ui_three;\n"
2363 " uint result = 0u;\n"
2364 " for (uint i = 0u; i < ui_three; i++) {\n"
2365 " result += s[i];\n"
2366 " }\n"
2367 " v_color = (result == 2u) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
2368 " gl_Position = position;\n"
2369 "}\n";
2370 const std::string &frag =
2371 "#version 300 es\n"
2372 "in mediump vec4 v_color;\n"
2373 "layout(location=0) out mediump vec4 o_color;\n"
2374 "void main() {\n"
2375 " o_color = v_color;\n"
2376 "}\n";
2377
2378 ANGLE_GL_PROGRAM(prog, vert, frag);
2379
Jamie Madille1faacb2016-12-13 12:42:14 -05002380 GLint oneIndex = glGetUniformLocation(prog.get(), "ui_one");
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002381 ASSERT_NE(-1, oneIndex);
Jamie Madille1faacb2016-12-13 12:42:14 -05002382 GLint twoIndex = glGetUniformLocation(prog.get(), "ui_two");
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002383 ASSERT_NE(-1, twoIndex);
Jamie Madille1faacb2016-12-13 12:42:14 -05002384 GLint threeIndex = glGetUniformLocation(prog.get(), "ui_three");
Jiawei-Shaoe292e902016-09-07 10:49:01 +08002385 ASSERT_NE(-1, threeIndex);
2386 glUseProgram(prog.get());
2387 glUniform1ui(oneIndex, 1u);
2388 glUniform1ui(twoIndex, 2u);
2389 glUniform1ui(threeIndex, 3u);
2390
2391 drawQuad(prog.get(), "position", 0.5f);
2392 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2393}
2394
Olli Etuahoab481642016-08-26 12:09:10 +03002395// Test a nested sequence operator with a ternary operator inside. The ternary operator is
2396// intended to be such that it gets converted to an if statement on the HLSL backend.
2397TEST_P(GLSLTest, NestedSequenceOperatorWithTernaryInside)
2398{
2399 const std::string &vert =
2400 "attribute vec2 position;\n"
2401 "void main()\n"
2402 "{\n"
2403 " gl_Position = vec4(position, 0, 1);\n"
2404 "}";
2405
2406 // Note that the uniform keep_flop_positive doesn't need to be set - the test expects it to have
2407 // its default value false.
2408 const std::string &frag =
2409 "precision mediump float;\n"
2410 "uniform bool keep_flop_positive;\n"
2411 "float flop;\n"
2412 "void main() {\n"
2413 " flop = -1.0,\n"
2414 " (flop *= -1.0,\n"
2415 " keep_flop_positive ? 0.0 : flop *= -1.0),\n"
2416 " gl_FragColor = vec4(0, -flop, 0, 1);\n"
2417 "}";
2418
2419 ANGLE_GL_PROGRAM(prog, vert, frag);
2420 drawQuad(prog.get(), "position", 0.5f);
2421 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2422}
2423
Geoff Lang28a97ee2016-09-22 13:01:26 -04002424// Test that using a sampler2D and samplerExternalOES in the same shader works (anglebug.com/1534)
2425TEST_P(GLSLTest, ExternalAnd2DSampler)
2426{
2427 if (!extensionEnabled("GL_OES_EGL_image_external"))
2428 {
2429 std::cout << "Test skipped because GL_OES_EGL_image_external is not available."
2430 << std::endl;
2431 return;
2432 }
2433
2434 const std::string fragmentShader =
2435 "precision mediump float;\n"
2436 "uniform samplerExternalOES tex0;\n"
2437 "uniform sampler2D tex1;\n"
2438 "void main(void)\n"
2439 "{\n"
2440 " vec2 uv = vec2(0.0, 0.0);"
2441 " gl_FragColor = texture2D(tex0, uv) + texture2D(tex1, uv);\n"
2442 "}\n";
2443
2444 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2445}
2446
Olli Etuaho56a2f952016-12-08 12:16:27 +00002447// Test that literal infinity can be written out from the shader translator.
2448// A similar test can't be made for NaNs, since ESSL 3.00.6 requirements for NaNs are very loose.
2449TEST_P(GLSLTest_ES3, LiteralInfinityOutput)
2450{
2451 const std::string &fragmentShader =
2452 "#version 300 es\n"
2453 "precision highp float;\n"
2454 "out vec4 out_color;\n"
2455 "uniform float u;\n"
2456 "void main()\n"
2457 "{\n"
2458 " float infVar = 1.0e40 - u;\n"
2459 " bool correct = isinf(infVar) && infVar > 0.0;\n"
2460 " out_color = correct ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
2461 "}\n";
2462
2463 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2464 drawQuad(program.get(), "inputAttribute", 0.5f);
2465 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2466}
2467
2468// Test that literal negative infinity can be written out from the shader translator.
2469// A similar test can't be made for NaNs, since ESSL 3.00.6 requirements for NaNs are very loose.
2470TEST_P(GLSLTest_ES3, LiteralNegativeInfinityOutput)
2471{
2472 const std::string &fragmentShader =
2473 "#version 300 es\n"
2474 "precision highp float;\n"
2475 "out vec4 out_color;\n"
2476 "uniform float u;\n"
2477 "void main()\n"
2478 "{\n"
2479 " float infVar = -1.0e40 + u;\n"
2480 " bool correct = isinf(infVar) && infVar < 0.0;\n"
2481 " out_color = correct ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
2482 "}\n";
2483
2484 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2485 drawQuad(program.get(), "inputAttribute", 0.5f);
2486 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2487}
2488
Corentin Wallez36fd1002016-12-08 11:30:44 -05002489// The following MultipleDeclaration* tests are testing TranslatorHLSL specific simplification
2490// passes. Because the interaction of multiple passes must be tested, it is difficult to write
2491// a unittest for them. Instead we add the tests as end2end so will in particular test
2492// TranslatorHLSL when run on Windows.
2493
2494// Test that passes splitting multiple declarations and comma operators are correctly ordered.
2495TEST_P(GLSLTest_ES3, MultipleDeclarationWithCommaOperator)
2496{
2497 const std::string &fragmentShader =
2498 "#version 300 es\n"
2499 "precision mediump float;\n"
2500 "out vec4 color;\n"
2501 "void main(void)\n"
2502 "{\n"
2503 " float a = 0.0, b = ((gl_FragCoord.x < 0.5 ? a : 0.0), 1.0);\n"
2504 " color = vec4(b);\n"
2505 "}\n";
2506
2507 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2508}
2509
2510// Test that passes splitting multiple declarations and comma operators and for loops are
2511// correctly ordered.
2512TEST_P(GLSLTest_ES3, MultipleDeclarationWithCommaOperatorInForLoop)
2513{
2514 const std::string &fragmentShader =
2515 "#version 300 es\n"
2516 "precision mediump float;\n"
2517 "out vec4 color;\n"
2518 "void main(void)\n"
2519 "{\n"
2520 " for(float a = 0.0, b = ((gl_FragCoord.x < 0.5 ? a : 0.0), 1.0); a < 10.0; a++)\n"
2521 " {\n"
2522 " b += 1.0;\n"
2523 " color = vec4(b);\n"
2524 " }\n"
2525 "}\n";
2526
2527 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2528}
2529
2530// Test that splitting multiple declaration in for loops works with no loop condition
2531TEST_P(GLSLTest_ES3, MultipleDeclarationInForLoopEmptyCondition)
2532{
2533 const std::string &fragmentShader =
2534 "#version 300 es\n"
2535 "precision mediump float;\n"
2536 "out vec4 color;\n"
2537 "void main(void)\n"
2538 "{\n"
2539 " for(float a = 0.0, b = 1.0;; a++)\n"
2540 " {\n"
2541 " b += 1.0;\n"
2542 " if (a > 10.0) {break;}\n"
2543 " color = vec4(b);\n"
2544 " }\n"
2545 "}\n";
2546
2547 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2548}
2549
2550// Test that splitting multiple declaration in for loops works with no loop expression
2551TEST_P(GLSLTest_ES3, MultipleDeclarationInForLoopEmptyExpression)
2552{
2553 const std::string &fragmentShader =
2554 "#version 300 es\n"
2555 "precision mediump float;\n"
2556 "out vec4 color;\n"
2557 "void main(void)\n"
2558 "{\n"
2559 " for(float a = 0.0, b = 1.0; a < 10.0;)\n"
2560 " {\n"
2561 " b += 1.0;\n"
2562 " a += 1.0;\n"
2563 " color = vec4(b);\n"
2564 " }\n"
2565 "}\n";
2566
2567 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2568}
2569
Olli Etuaho8f6eb2a2017-01-12 17:04:58 +00002570// Test that dynamic indexing of a matrix inside a dynamic indexing of a vector in an l-value works
2571// correctly.
2572TEST_P(GLSLTest_ES3, NestedDynamicIndexingInLValue)
2573{
2574 const std::string &fragmentShader =
2575 "#version 300 es\n"
2576 "precision mediump float;\n"
2577 "out vec4 my_FragColor;\n"
2578 "uniform int u_zero;\n"
2579 "void main() {\n"
2580 " mat2 m = mat2(0.0, 0.0, 0.0, 0.0);\n"
2581 " m[u_zero + 1][u_zero + 1] = float(u_zero + 1);\n"
2582 " float f = m[1][1];\n"
2583 " my_FragColor = vec4(1.0 - f, f, 0.0, 1.0);\n"
2584 "}\n";
2585
2586 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2587 drawQuad(program.get(), "inputAttribute", 0.5f);
2588 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2589}
2590
Jamie Madill192745a2016-12-22 15:58:21 -05002591class WebGLGLSLTest : public GLSLTest
2592{
2593 protected:
2594 WebGLGLSLTest() { setWebGLCompatibilityEnabled(true); }
2595};
2596
2597TEST_P(WebGLGLSLTest, MaxVaryingVec4PlusFragCoord)
2598{
2599 GLint maxVaryings = 0;
2600 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2601
2602 // Generate shader code that uses gl_FragCoord, a special fragment shader variables.
2603 // This test should fail, since we are really using (maxVaryings + 1) varyings.
2604 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, true, false, false, false);
2605}
2606
2607TEST_P(WebGLGLSLTest, MaxVaryingVec4PlusPointCoord)
2608{
2609 GLint maxVaryings = 0;
2610 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2611
2612 // Generate shader code that uses gl_FragCoord, a special fragment shader variables.
2613 // This test should fail, since we are really using (maxVaryings + 1) varyings.
2614 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, false, true, false, false);
2615}
2616
2617TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec3)
2618{
2619 GLint maxVaryings = 0;
2620 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2621
2622 VaryingTestBase(0, 0, 0, 0, maxVaryings + 1, 0, 0, 0, false, false, false, false);
2623}
2624
2625TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec3Array)
2626{
2627 GLint maxVaryings = 0;
2628 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2629
2630 VaryingTestBase(0, 0, 0, 0, 0, maxVaryings / 2 + 1, 0, 0, false, false, false, false);
2631}
2632
2633TEST_P(WebGLGLSLTest, MaxVaryingVec3AndOneVec2)
2634{
2635 GLint maxVaryings = 0;
2636 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2637
2638 VaryingTestBase(0, 0, 1, 0, maxVaryings, 0, 0, 0, false, false, false, false);
2639}
2640
2641TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec2)
2642{
2643 GLint maxVaryings = 0;
2644 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2645
2646 VaryingTestBase(0, 0, 2 * maxVaryings + 1, 0, 0, 0, 0, 0, false, false, false, false);
2647}
2648
2649TEST_P(WebGLGLSLTest, MaxVaryingVec3ArrayAndMaxPlusOneFloatArray)
2650{
2651 GLint maxVaryings = 0;
2652 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2653
2654 VaryingTestBase(0, maxVaryings / 2 + 1, 0, 0, 0, 0, 0, maxVaryings / 2, false, false, false,
2655 false);
2656}
2657
Jamie Madill6c9503e2016-08-16 14:06:32 -04002658} // anonymous namespace
2659
Olli Etuaho9250cb22017-01-21 10:51:27 +00002660// Test that FindLSB and FindMSB return correct values in their corner cases.
2661TEST_P(GLSLTest_ES31, FindMSBAndFindLSBCornerCases)
2662{
Olli Etuaho61bd9fe2017-01-27 14:20:34 -08002663 // Suspecting AMD driver bug - failure seen on bots running on AMD R5 230.
2664 if (IsAMD() && IsOpenGL() && IsLinux())
2665 {
2666 std::cout << "Test skipped on AMD OpenGL Linux" << std::endl;
2667 return;
2668 }
2669
Olli Etuaho9250cb22017-01-21 10:51:27 +00002670 const std::string &fragmentShader =
2671 "#version 310 es\n"
2672 "precision mediump float;\n"
2673 "out vec4 my_FragColor;\n"
2674 "uniform int u_zero;\n"
2675 "void main() {\n"
2676 " if (findLSB(u_zero) == -1 && findMSB(u_zero) == -1 && findMSB(u_zero - 1) == -1)\n"
2677 " {\n"
2678 " my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
2679 " }\n"
2680 " else\n"
2681 " {\n"
2682 " my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
2683 " }\n"
2684 "}\n";
2685
2686 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2687 drawQuad(program.get(), "inputAttribute", 0.5f);
2688 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2689}
2690
Olli Etuahoc9da71f2017-03-06 16:28:54 +00002691// Test that writing into a swizzled vector that is dynamically indexed succeeds.
2692TEST_P(GLSLTest_ES3, WriteIntoDynamicIndexingOfSwizzledVector)
2693{
Corentin Wallez6445ddf2017-03-08 19:00:32 -05002694 if (IsOpenGL())
Olli Etuahoc9da71f2017-03-06 16:28:54 +00002695 {
2696 // http://anglebug.com/1924
Corentin Wallez6445ddf2017-03-08 19:00:32 -05002697 std::cout << "Test skipped on all OpenGL configurations because it has incorrect results"
2698 << std::endl;
Olli Etuahoc9da71f2017-03-06 16:28:54 +00002699 return;
2700 }
2701
2702 // The shader first assigns v.x to v.z (1.0)
2703 // Then v.y to v.y (2.0)
2704 // Then v.z to v.x (1.0)
2705 const std::string &fragmentShader =
2706 "#version 300 es\n"
2707 "precision highp float;\n"
2708 "out vec4 my_FragColor;\n"
2709 "void main() {\n"
2710 " vec3 v = vec3(1.0, 2.0, 3.0);\n"
2711 " for (int i = 0; i < 3; i++) {\n"
2712 " v.zyx[i] = v[i];\n"
2713 " }\n"
2714 " my_FragColor = distance(v, vec3(1.0, 2.0, 1.0)) < 0.01 ? vec4(0, 1, 0, 1) : vec4(1, "
2715 "0, 0, 1);\n"
2716 "}\n";
2717
2718 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2719 drawQuad(program.get(), "inputAttribute", 0.5f);
2720 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2721}
2722
Jamie Madill8aeeed62017-03-15 18:09:26 -04002723// This test covers a bug (and associated workaround) with nested sampling operations in the HLSL
2724// compiler DLL.
2725TEST_P(GLSLTest_ES3, NestedSamplingOperation)
2726{
2727 // This seems to be bugged on some version of Android. Might not affect the newest versions.
2728 // TODO(jmadill): Lift suppression when Chromium bots are upgraded.
2729 if (IsAndroid() && IsOpenGLES())
2730 {
2731 std::cout << "Test skipped on Android because of bug with Nexus 5X." << std::endl;
2732 return;
2733 }
2734
2735 const std::string &vertexShader =
2736 "#version 300 es\n"
2737 "out vec2 texCoord;\n"
2738 "in vec2 position;\n"
2739 "void main()\n"
2740 "{\n"
2741 " gl_Position = vec4(position, 0, 1);\n"
2742 " texCoord = position * 0.5 + vec2(0.5);\n"
2743 "}\n";
2744
2745 const std::string &simpleFragmentShader =
2746 "#version 300 es\n"
2747 "in mediump vec2 texCoord;\n"
2748 "out mediump vec4 fragColor;\n"
2749 "void main()\n"
2750 "{\n"
2751 " fragColor = vec4(texCoord, 0, 1);\n"
2752 "}\n";
2753
2754 const std::string &nestedFragmentShader =
2755 "#version 300 es\n"
2756 "uniform mediump sampler2D samplerA;\n"
2757 "uniform mediump sampler2D samplerB;\n"
2758 "in mediump vec2 texCoord;\n"
2759 "out mediump vec4 fragColor;\n"
2760 "void main ()\n"
2761 "{\n"
2762 " fragColor = texture(samplerB, texture(samplerA, texCoord).xy);\n"
2763 "}\n";
2764
2765 ANGLE_GL_PROGRAM(initProg, vertexShader, simpleFragmentShader);
2766 ANGLE_GL_PROGRAM(nestedProg, vertexShader, nestedFragmentShader);
2767
2768 // Initialize a first texture with default texCoord data.
2769 GLTexture texA;
2770 glActiveTexture(GL_TEXTURE0);
2771 glBindTexture(GL_TEXTURE_2D, texA);
2772 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
2773 GL_UNSIGNED_BYTE, nullptr);
2774 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2775 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2776
2777 GLFramebuffer fbo;
2778 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2779 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texA, 0);
2780
2781 drawQuad(initProg, "position", 0.5f);
2782 ASSERT_GL_NO_ERROR();
2783
2784 // Initialize a second texture with a simple color pattern.
2785 GLTexture texB;
2786 glActiveTexture(GL_TEXTURE1);
2787 glBindTexture(GL_TEXTURE_2D, texB);
2788
2789 std::array<GLColor, 4> simpleColors = {
2790 {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
2791 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2792 simpleColors.data());
2793 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2794 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2795
2796 // Draw with the nested program, using the first texture to index the second.
2797 glBindFramebuffer(GL_FRAMEBUFFER, 0);
2798 glUseProgram(nestedProg);
2799 GLint samplerALoc = glGetUniformLocation(nestedProg, "samplerA");
2800 ASSERT_NE(-1, samplerALoc);
2801 glUniform1i(samplerALoc, 0);
2802 GLint samplerBLoc = glGetUniformLocation(nestedProg, "samplerB");
2803 ASSERT_NE(-1, samplerBLoc);
2804 glUniform1i(samplerBLoc, 1);
2805
2806 drawQuad(nestedProg, "position", 0.5f);
2807 ASSERT_GL_NO_ERROR();
2808
2809 // Compute four texel centers.
2810 Vector2 windowSize(getWindowWidth(), getWindowHeight());
2811 Vector2 quarterWindowSize = windowSize / 4;
2812 Vector2 ul = quarterWindowSize;
2813 Vector2 ur(windowSize.x() - quarterWindowSize.x(), quarterWindowSize.y());
2814 Vector2 ll(quarterWindowSize.x(), windowSize.y() - quarterWindowSize.y());
2815 Vector2 lr = windowSize - quarterWindowSize;
2816
2817 EXPECT_PIXEL_COLOR_EQ_VEC2(ul, simpleColors[0]);
2818 EXPECT_PIXEL_COLOR_EQ_VEC2(ur, simpleColors[1]);
2819 EXPECT_PIXEL_COLOR_EQ_VEC2(ll, simpleColors[2]);
2820 EXPECT_PIXEL_COLOR_EQ_VEC2(lr, simpleColors[3]);
2821}
2822
Olli Etuaho81629262017-04-19 11:56:01 +03002823// Tests that using a constant declaration as the only statement in a for loop without curly braces
2824// doesn't crash.
2825TEST_P(GLSLTest, ConstantStatementInForLoop)
2826{
2827 const std::string &vertexShader =
2828 "void main()\n"
2829 "{\n"
2830 " for (int i = 0; i < 10; ++i)\n"
2831 " const int b = 0;\n"
2832 "}\n";
2833
2834 GLuint shader = CompileShader(GL_VERTEX_SHADER, vertexShader);
2835 EXPECT_NE(0u, shader);
2836 glDeleteShader(shader);
2837}
2838
2839// Tests that using a constant declaration as a loop init expression doesn't crash. Note that this
2840// test doesn't work on D3D9 due to looping limitations, so it is only run on ES3.
2841TEST_P(GLSLTest_ES3, ConstantStatementAsLoopInit)
2842{
2843 const std::string &vertexShader =
2844 "void main()\n"
2845 "{\n"
2846 " for (const int i = 0; i < 0;) {}\n"
2847 "}\n";
2848
2849 GLuint shader = CompileShader(GL_VERTEX_SHADER, vertexShader);
2850 EXPECT_NE(0u, shader);
2851 glDeleteShader(shader);
2852}
2853
Olli Etuaho9733cee2017-05-11 19:14:35 +03002854// Test that uninitialized local variables are initialized to 0.
2855TEST_P(GLSLTest_ES3, InitUninitializedLocals)
2856{
2857 if (IsAndroid() && IsOpenGLES())
2858 {
2859 // http://anglebug.com/2046
2860 std::cout
2861 << "Test skipped on Android GLES because local variable initialization is disabled."
2862 << std::endl;
2863 return;
2864 }
2865
2866 if (IsOSX() && IsOpenGL())
2867 {
2868 // http://anglebug.com/2041
2869 std::cout << "Test skipped on Mac OpenGL because local variable initialization is disabled."
2870 << std::endl;
2871 return;
2872 }
2873
2874 const std::string &fragmentShader =
2875 "#version 300 es\n"
2876 "precision mediump float;\n"
2877 "out vec4 my_FragColor;\n"
2878 "int result = 0;\n"
2879 "void main()\n"
2880 "{\n"
2881 " int u;\n"
2882 " result += u;\n"
2883 " int k = 0;\n"
2884 " for (int i[2], j = i[0] + 1; k < 2; ++k)\n"
2885 " {\n"
2886 " result += j;\n"
2887 " }\n"
2888 " if (result == 2)\n"
2889 " {\n"
2890 " my_FragColor = vec4(0, 1, 0, 1);\n"
2891 " }\n"
2892 " else\n"
2893 " {\n"
2894 " my_FragColor = vec4(1, 0, 0, 1);\n"
2895 " }\n"
2896 "}\n";
2897
2898 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2899 drawQuad(program.get(), "inputAttribute", 0.5f);
2900 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2901}
2902
2903// Test that uninitialized structs containing arrays of structs are initialized to 0. This
2904// specifically tests with two different struct variables declared in the same block.
2905TEST_P(GLSLTest, InitUninitializedStructContainingArrays)
2906{
2907 if (IsAndroid() && IsOpenGLES())
2908 {
2909 // http://anglebug.com/2046
2910 std::cout
2911 << "Test skipped on Android GLES because local variable initialization is disabled."
2912 << std::endl;
2913 return;
2914 }
2915
2916 if (IsOSX() && IsOpenGL())
2917 {
2918 // http://anglebug.com/2041
2919 std::cout << "Test skipped on Mac OpenGL because local variable initialization is disabled."
2920 << std::endl;
2921 return;
2922 }
2923
2924 const std::string &fragmentShader =
2925 "precision mediump float;\n"
2926 "struct T\n"
2927 "{\n"
2928 " int a[2];\n"
2929 "};\n"
2930 "struct S\n"
2931 "{\n"
2932 " T t[2];\n"
2933 "};\n"
2934 "void main()\n"
2935 "{\n"
2936 " S s;\n"
2937 " S s2;\n"
2938 " if (s.t[1].a[1] == 0 && s2.t[1].a[1] == 0)\n"
2939 " {\n"
2940 " gl_FragColor = vec4(0, 1, 0, 1);\n"
2941 " }\n"
2942 " else\n"
2943 " {\n"
2944 " gl_FragColor = vec4(1, 0, 0, 1);\n"
2945 " }\n"
2946 "}\n";
2947
2948 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
2949 drawQuad(program.get(), "inputAttribute", 0.5f);
2950 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2951}
2952
Geoff Langbb1e7502017-06-05 16:40:09 -04002953// Verify that two shaders with the same uniform name and members but different structure names will
2954// not link.
2955TEST_P(GLSLTest, StructureNameMatchingTest)
2956{
2957 const char *vsSource =
2958 "// Structures must have the same name, sequence of type names, and\n"
2959 "// type definitions, and field names to be considered the same type.\n"
2960 "// GLSL 1.017 4.2.4\n"
2961 "precision mediump float;\n"
2962 "struct info {\n"
2963 " vec4 pos;\n"
2964 " vec4 color;\n"
2965 "};\n"
2966 "\n"
2967 "uniform info uni;\n"
2968 "void main()\n"
2969 "{\n"
2970 " gl_Position = uni.pos;\n"
2971 "}\n";
2972
2973 GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
2974 ASSERT_NE(0u, vs);
2975 glDeleteShader(vs);
2976
2977 const char *fsSource =
2978 "// Structures must have the same name, sequence of type names, and\n"
2979 "// type definitions, and field names to be considered the same type.\n"
2980 "// GLSL 1.017 4.2.4\n"
2981 "precision mediump float;\n"
2982 "struct info1 {\n"
2983 " vec4 pos;\n"
2984 " vec4 color;\n"
2985 "};\n"
2986 "\n"
2987 "uniform info1 uni;\n"
2988 "void main()\n"
2989 "{\n"
2990 " gl_FragColor = uni.color;\n"
2991 "}\n";
2992
2993 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
2994 ASSERT_NE(0u, fs);
2995 glDeleteShader(fs);
2996
2997 GLuint program = CompileProgram(vsSource, fsSource);
2998 EXPECT_EQ(0u, program);
2999}
3000
Olli Etuaho9733cee2017-05-11 19:14:35 +03003001// Test that an uninitialized nameless struct inside a for loop init statement works.
3002TEST_P(GLSLTest_ES3, UninitializedNamelessStructInForInitStatement)
3003{
3004 if (IsAndroid() && IsOpenGLES())
3005 {
3006 // http://anglebug.com/2046
3007 std::cout
3008 << "Test skipped on Android GLES because local variable initialization is disabled."
3009 << std::endl;
3010 return;
3011 }
3012
3013 if (IsOSX() && IsOpenGL())
3014 {
3015 // http://anglebug.com/2041
3016 std::cout << "Test skipped on Mac OpenGL because local variable initialization is disabled."
3017 << std::endl;
3018 return;
3019 }
3020
3021 const std::string &fragmentShader =
3022 "#version 300 es\n"
3023 "precision highp float;\n"
3024 "out vec4 my_FragColor;\n"
3025 "void main()\n"
3026 "{\n"
3027 " my_FragColor = vec4(1, 0, 0, 1);\n"
3028 " for (struct { float q; } b; b.q < 2.0; b.q++) {\n"
3029 " my_FragColor = vec4(0, 1, 0, 1);\n"
3030 " }\n"
3031 "}\n";
3032
3033 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3034 drawQuad(program.get(), "inputAttribute", 0.5f);
3035 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3036}
3037
Olli Etuaho0ffc4412017-05-19 14:18:55 +03003038// Test that uninitialized global variables are initialized to 0.
3039TEST_P(WebGLGLSLTest, InitUninitializedGlobals)
3040{
3041 const std::string &fragmentShader =
3042 "precision mediump float;\n"
3043 "int result;\n"
3044 "int i[2], j = i[0] + 1;\n"
3045 "void main()\n"
3046 "{\n"
3047 " result += j;\n"
3048 " if (result == 1)\n"
3049 " {\n"
3050 " gl_FragColor = vec4(0, 1, 0, 1);\n"
3051 " }\n"
3052 " else\n"
3053 " {\n"
3054 " gl_FragColor = vec4(1, 0, 0, 1);\n"
3055 " }\n"
3056 "}\n";
3057
3058 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3059 drawQuad(program.get(), "inputAttribute", 0.5f, 1.0f, true);
3060 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3061}
3062
3063// Test that an uninitialized nameless struct in the global scope works.
3064TEST_P(WebGLGLSLTest, UninitializedNamelessStructInGlobalScope)
3065{
3066 const std::string &fragmentShader =
3067 "precision mediump float;\n"
3068 "struct { float q; } b;\n"
3069 "void main()\n"
3070 "{\n"
3071 " gl_FragColor = vec4(1, 0, 0, 1);\n"
3072 " if (b.q == 0.0)\n"
3073 " {\n"
3074 " gl_FragColor = vec4(0, 1, 0, 1);\n"
3075 " }\n"
3076 "}\n";
3077
3078 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3079 drawQuad(program.get(), "inputAttribute", 0.5f, 1.0f, true);
3080 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3081}
3082
Olli Etuaho914b79a2017-06-19 16:03:19 +03003083// Test that a loop condition that has an initializer declares a variable.
3084TEST_P(GLSLTest_ES3, ConditionInitializerDeclaresVariable)
3085{
3086 const std::string &fragmentShader =
3087 "#version 300 es\n"
3088 "precision highp float;\n"
3089 "out vec4 my_FragColor;\n"
3090 "void main()\n"
3091 "{\n"
3092 " float i = 0.0;\n"
3093 " while (bool foo = (i < 1.5))\n"
3094 " {\n"
3095 " if (!foo)\n"
3096 " {\n"
3097 " ++i;\n"
3098 " }\n"
3099 " if (i > 3.5)\n"
3100 " {\n"
3101 " break;\n"
3102 " }\n"
3103 " ++i;\n"
3104 " }\n"
3105 " my_FragColor = vec4(i * 0.5 - 1.0, i * 0.5, 0.0, 1.0);\n"
3106 "}\n";
3107
3108 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3109 drawQuad(program.get(), "inputAttribute", 0.5f);
3110 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3111}
3112
Olli Etuahoff526f12017-06-30 12:26:54 +03003113// Test that a variable hides a user-defined function with the same name after its initializer.
3114// GLSL ES 1.00.17 section 4.2.2: "A variable declaration is visible immediately following the
3115// initializer if present, otherwise immediately following the identifier"
3116TEST_P(GLSLTest, VariableHidesUserDefinedFunctionAfterInitializer)
3117{
3118 const std::string &fragmentShader =
3119 "precision mediump float;\n"
3120 "uniform vec4 u;\n"
3121 "vec4 foo()\n"
3122 "{\n"
3123 " return u;\n"
3124 "}\n"
3125 "void main()\n"
3126 "{\n"
3127 " vec4 foo = foo();\n"
3128 " gl_FragColor = foo + vec4(0, 1, 0, 1);\n"
3129 "}\n";
3130
3131 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3132 drawQuad(program.get(), "inputAttribute", 0.5f);
3133 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3134}
3135
Olli Etuaho088031e2017-07-03 15:59:33 +03003136// Test that structs with identical members are not ambiguous as function arguments.
3137TEST_P(GLSLTest, StructsWithSameMembersDisambiguatedByName)
3138{
3139 const std::string &fragmentShader =
3140 "precision mediump float;\n"
3141 "uniform float u_zero;\n"
3142 "struct S { float foo; };\n"
3143 "struct S2 { float foo; };\n"
3144 "float get(S s) { return s.foo + u_zero; }\n"
3145 "float get(S2 s2) { return 0.25 + s2.foo + u_zero; }\n"
3146 "void main()\n"
3147 "{\n"
3148 " S s;\n"
3149 " s.foo = 0.5;\n"
3150 " S2 s2;\n"
3151 " s2.foo = 0.25;\n"
3152 " gl_FragColor = vec4(0.0, get(s) + get(s2), 0.0, 1.0);\n"
3153 "}\n";
3154
3155 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3156 drawQuad(program.get(), "inputAttribute", 0.5f);
3157 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3158}
3159
Olli Etuaho06a06f52017-07-12 12:22:15 +03003160// Test that a varying struct that's not statically used in the fragment shader works.
3161// GLSL ES 3.00.6 section 4.3.10.
3162TEST_P(GLSLTest_ES3, VaryingStructNotStaticallyUsedInFragmentShader)
3163{
3164 const std::string &vertexShader =
3165 "#version 300 es\n"
3166 "struct S {\n"
3167 " vec4 field;\n"
3168 "};\n"
3169 "out S varStruct;\n"
3170 "void main()\n"
3171 "{\n"
3172 " gl_Position = vec4(1.0);\n"
3173 " varStruct.field = vec4(0.0, 0.5, 0.0, 0.0);\n"
3174 "}\n";
3175
3176 const std::string &fragmentShader =
3177 "#version 300 es\n"
3178 "precision mediump float;\n"
3179 "struct S {\n"
3180 " vec4 field;\n"
3181 "};\n"
3182 "in S varStruct;\n"
3183 "out vec4 col;\n"
3184 "void main()\n"
3185 "{\n"
3186 " col = vec4(1.0);\n"
3187 "}\n";
3188
3189 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3190}
3191
3192// Test that a varying struct that's not declared in the fragment shader links successfully.
3193// GLSL ES 3.00.6 section 4.3.10.
3194TEST_P(GLSLTest_ES3, VaryingStructNotDeclaredInFragmentShader)
3195{
3196 const std::string &vertexShader =
3197 "#version 300 es\n"
3198 "struct S {\n"
3199 " vec4 field;\n"
3200 "};\n"
3201 "out S varStruct;\n"
3202 "void main()\n"
3203 "{\n"
3204 " gl_Position = vec4(1.0);\n"
3205 " varStruct.field = vec4(0.0, 0.5, 0.0, 0.0);\n"
3206 "}\n";
3207
3208 const std::string &fragmentShader =
3209 "#version 300 es\n"
3210 "precision mediump float;\n"
3211 "out vec4 col;\n"
3212 "void main()\n"
3213 "{\n"
3214 " col = vec4(1.0);\n"
3215 "}\n";
3216
3217 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3218}
3219
3220// Test that a varying struct that gets used in the fragment shader works.
3221TEST_P(GLSLTest_ES3, VaryingStructUsedInFragmentShader)
3222{
3223 const std::string &vertexShader =
3224 "#version 300 es\n"
3225 "in vec4 inputAttribute;\n"
3226 "struct S {\n"
3227 " vec4 field;\n"
3228 "};\n"
3229 "out S varStruct;\n"
3230 "void main()\n"
3231 "{\n"
3232 " gl_Position = inputAttribute;\n"
3233 " varStruct.field = vec4(0.0, 1.0, 0.0, 1.0);\n"
3234 "}\n";
3235
3236 const std::string &fragmentShader =
3237 "#version 300 es\n"
3238 "precision mediump float;\n"
3239 "out vec4 col;\n"
3240 "struct S {\n"
3241 " vec4 field;\n"
3242 "};\n"
3243 "in S varStruct;\n"
3244 "void main()\n"
3245 "{\n"
3246 " col = varStruct.field;\n"
3247 "}\n";
3248
3249 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3250 drawQuad(program.get(), "inputAttribute", 0.5f);
3251 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3252}
3253
Olli Etuaho3860b6c2017-07-19 16:17:24 +03003254// This test covers passing an array of structs containing samplers as a function argument.
3255TEST_P(GLSLTest, ArrayOfStructsWithSamplersAsFunctionArg)
3256{
3257 if (IsAndroid() && IsAdreno() && IsOpenGLES())
3258 {
3259 // Shader failed to compile on Android. http://anglebug.com/2114
3260 std::cout << "Test skipped on Adreno OpenGLES on Android." << std::endl;
3261 return;
3262 }
3263
3264 const std::string &vertexShader =
3265 "attribute vec2 position;\n"
3266 "void main()\n"
3267 "{\n"
3268 " gl_Position = vec4(position, 0, 1);\n"
3269 "}\n";
3270
3271 const std::string &fragmentShader =
3272 "precision mediump float;\n"
3273 "struct S\n"
3274 "{\n"
3275 " sampler2D samplerMember; \n"
3276 "};\n"
3277 "uniform S uStructs[2];\n"
3278 "uniform vec2 uTexCoord;\n"
3279 "\n"
3280 "vec4 foo(S[2] structs)\n"
3281 "{\n"
3282 " return texture2D(structs[0].samplerMember, uTexCoord);\n"
3283 "}\n"
3284 "void main()\n"
3285 "{\n"
3286 " gl_FragColor = foo(uStructs);\n"
3287 "}\n";
3288
3289 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3290
3291 // Initialize the texture with green.
3292 GLTexture tex;
3293 glActiveTexture(GL_TEXTURE0);
3294 glBindTexture(GL_TEXTURE_2D, tex);
3295 GLubyte texData[] = {0u, 255u, 0u, 255u};
3296 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
3297 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3298 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3299 ASSERT_GL_NO_ERROR();
3300
3301 // Draw
3302 glUseProgram(program);
3303 GLint samplerMemberLoc = glGetUniformLocation(program, "uStructs[0].samplerMember");
3304 ASSERT_NE(-1, samplerMemberLoc);
3305 glUniform1i(samplerMemberLoc, 0);
3306 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
3307 ASSERT_NE(-1, texCoordLoc);
3308 glUniform2f(texCoordLoc, 0.5f, 0.5f);
3309
3310 drawQuad(program, "position", 0.5f);
3311 ASSERT_GL_NO_ERROR();
3312
3313 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
3314}
3315
Olli Etuaho28839f02017-08-15 11:38:16 +03003316// This test covers passing a struct containing an array of samplers as a function argument.
3317TEST_P(GLSLTest, StructWithSamplerArrayAsFunctionArg)
3318{
3319 if (IsAndroid() && IsAdreno() && IsOpenGLES())
3320 {
3321 // Shader failed to compile on Android. http://anglebug.com/2114
3322 std::cout << "Test skipped on Adreno OpenGLES on Android." << std::endl;
3323 return;
3324 }
3325
3326 const std::string &vertexShader =
3327 "attribute vec2 position;\n"
3328 "void main()\n"
3329 "{\n"
3330 " gl_Position = vec4(position, 0, 1);\n"
3331 "}\n";
3332
3333 const std::string &fragmentShader =
3334 "precision mediump float;\n"
3335 "struct S\n"
3336 "{\n"
3337 " sampler2D samplerMembers[2];\n"
3338 "};\n"
3339 "uniform S uStruct;\n"
3340 "uniform vec2 uTexCoord;\n"
3341 "\n"
3342 "vec4 foo(S str)\n"
3343 "{\n"
3344 " return texture2D(str.samplerMembers[0], uTexCoord);\n"
3345 "}\n"
3346 "void main()\n"
3347 "{\n"
3348 " gl_FragColor = foo(uStruct);\n"
3349 "}\n";
3350
3351 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3352
3353 // Initialize the texture with green.
3354 GLTexture tex;
3355 glActiveTexture(GL_TEXTURE0);
3356 glBindTexture(GL_TEXTURE_2D, tex);
3357 GLubyte texData[] = {0u, 255u, 0u, 255u};
3358 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
3359 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3360 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3361 ASSERT_GL_NO_ERROR();
3362
3363 // Draw
3364 glUseProgram(program);
3365 GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMembers[0]");
3366 ASSERT_NE(-1, samplerMemberLoc);
3367 glUniform1i(samplerMemberLoc, 0);
3368 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
3369 ASSERT_NE(-1, texCoordLoc);
3370 glUniform2f(texCoordLoc, 0.5f, 0.5f);
3371
3372 drawQuad(program, "position", 0.5f);
3373 ASSERT_GL_NO_ERROR();
3374
3375 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
3376}
3377
Olli Etuahoa16a84f2017-09-12 13:49:18 +03003378// Test that a global variable declared after main() works. This is a regression test for an issue
3379// in global variable initialization.
3380TEST_P(WebGLGLSLTest, GlobalVariableDeclaredAfterMain)
3381{
3382 const std::string &fragmentShader =
3383 "precision mediump float;\n"
3384 "int getFoo();\n"
3385 "uniform int u_zero;\n"
3386 "void main()\n"
3387 "{\n"
3388 " gl_FragColor = vec4(1, 0, 0, 1);\n"
3389 " if (getFoo() == 0)\n"
3390 " {\n"
3391 " gl_FragColor = vec4(0, 1, 0, 1);\n"
3392 " }\n"
3393 "}\n"
3394 "int foo;\n"
3395 "int getFoo()\n"
3396 "{\n"
3397 " foo = u_zero;\n"
3398 " return foo;\n"
3399 "}\n";
3400
3401 ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
3402 drawQuad(program.get(), "inputAttribute", 0.5f, 1.0f, true);
3403 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3404}
3405
Jamie Madillfa05f602015-05-07 13:47:11 -04003406// 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 -05003407ANGLE_INSTANTIATE_TEST(GLSLTest,
3408 ES2_D3D9(),
3409 ES2_D3D11(),
3410 ES2_D3D11_FL9_3(),
3411 ES2_OPENGL(),
3412 ES3_OPENGL(),
3413 ES2_OPENGLES(),
3414 ES3_OPENGLES());
Jamie Madillfa05f602015-05-07 13:47:11 -04003415
3416// 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 -05003417ANGLE_INSTANTIATE_TEST(GLSLTest_ES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
Jamie Madill192745a2016-12-22 15:58:21 -05003418
3419ANGLE_INSTANTIATE_TEST(WebGLGLSLTest, ES2_D3D11(), ES2_OPENGL(), ES2_OPENGLES());
Olli Etuaho9250cb22017-01-21 10:51:27 +00003420
3421ANGLE_INSTANTIATE_TEST(GLSLTest_ES31, ES31_D3D11(), ES31_OPENGL(), ES31_OPENGLES());