1 //
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
7 #include "test_utils/ANGLETest.h"
8
9 #include "test_utils/gl_raii.h"
10 #include "util/shader_utils.h"
11
12 using namespace angle;
13
14 namespace
15 {
16 class GLSLTest : public ANGLETest<>
17 {
18 protected:
GLSLTest()19 GLSLTest()
20 {
21 setWindowWidth(128);
22 setWindowHeight(128);
23 setConfigRedBits(8);
24 setConfigGreenBits(8);
25 setConfigBlueBits(8);
26 setConfigAlphaBits(8);
27 }
28
GenerateVaryingType(GLint vectorSize)29 std::string GenerateVaryingType(GLint vectorSize)
30 {
31 char varyingType[10];
32
33 if (vectorSize == 1)
34 {
35 snprintf(varyingType, sizeof(varyingType), "float");
36 }
37 else
38 {
39 snprintf(varyingType, sizeof(varyingType), "vec%d", vectorSize);
40 }
41
42 return std::string(varyingType);
43 }
44
GenerateVectorVaryingDeclaration(GLint vectorSize,GLint arraySize,GLint id)45 std::string GenerateVectorVaryingDeclaration(GLint vectorSize, GLint arraySize, GLint id)
46 {
47 char buff[100];
48
49 if (arraySize == 1)
50 {
51 snprintf(buff, sizeof(buff), "varying %s v%d;\n",
52 GenerateVaryingType(vectorSize).c_str(), id);
53 }
54 else
55 {
56 snprintf(buff, sizeof(buff), "varying %s v%d[%d];\n",
57 GenerateVaryingType(vectorSize).c_str(), id, arraySize);
58 }
59
60 return std::string(buff);
61 }
62
GenerateVectorVaryingSettingCode(GLint vectorSize,GLint arraySize,GLint id)63 std::string GenerateVectorVaryingSettingCode(GLint vectorSize, GLint arraySize, GLint id)
64 {
65 std::string returnString;
66 char buff[100];
67
68 if (arraySize == 1)
69 {
70 snprintf(buff, sizeof(buff), "\t v%d = %s(1.0);\n", id,
71 GenerateVaryingType(vectorSize).c_str());
72 returnString += buff;
73 }
74 else
75 {
76 for (int i = 0; i < arraySize; i++)
77 {
78 snprintf(buff, sizeof(buff), "\t v%d[%d] = %s(1.0);\n", id, i,
79 GenerateVaryingType(vectorSize).c_str());
80 returnString += buff;
81 }
82 }
83
84 return returnString;
85 }
86
GenerateVectorVaryingUseCode(GLint arraySize,GLint id)87 std::string GenerateVectorVaryingUseCode(GLint arraySize, GLint id)
88 {
89 if (arraySize == 1)
90 {
91 char buff[100];
92 snprintf(buff, sizeof(buff), "v%d + ", id);
93 return std::string(buff);
94 }
95 else
96 {
97 std::string returnString;
98 for (int i = 0; i < arraySize; i++)
99 {
100 char buff[100];
101 snprintf(buff, sizeof(buff), "v%d[%d] + ", id, i);
102 returnString += buff;
103 }
104 return returnString;
105 }
106 }
107
GenerateGLSLWithVaryings(GLint floatCount,GLint floatArrayCount,GLint vec2Count,GLint vec2ArrayCount,GLint vec3Count,GLint vec3ArrayCount,GLint vec4Count,GLint vec4ArrayCount,bool useFragCoord,bool usePointCoord,bool usePointSize,std::string * fragmentShader,std::string * vertexShader)108 void GenerateGLSLWithVaryings(GLint floatCount,
109 GLint floatArrayCount,
110 GLint vec2Count,
111 GLint vec2ArrayCount,
112 GLint vec3Count,
113 GLint vec3ArrayCount,
114 GLint vec4Count,
115 GLint vec4ArrayCount,
116 bool useFragCoord,
117 bool usePointCoord,
118 bool usePointSize,
119 std::string *fragmentShader,
120 std::string *vertexShader)
121 {
122 // Generate a string declaring the varyings, to share between the fragment shader and the
123 // vertex shader.
124 std::string varyingDeclaration;
125
126 unsigned int varyingCount = 0;
127
128 for (GLint i = 0; i < floatCount; i++)
129 {
130 varyingDeclaration += GenerateVectorVaryingDeclaration(1, 1, varyingCount);
131 varyingCount += 1;
132 }
133
134 for (GLint i = 0; i < floatArrayCount; i++)
135 {
136 varyingDeclaration += GenerateVectorVaryingDeclaration(1, 2, varyingCount);
137 varyingCount += 1;
138 }
139
140 for (GLint i = 0; i < vec2Count; i++)
141 {
142 varyingDeclaration += GenerateVectorVaryingDeclaration(2, 1, varyingCount);
143 varyingCount += 1;
144 }
145
146 for (GLint i = 0; i < vec2ArrayCount; i++)
147 {
148 varyingDeclaration += GenerateVectorVaryingDeclaration(2, 2, varyingCount);
149 varyingCount += 1;
150 }
151
152 for (GLint i = 0; i < vec3Count; i++)
153 {
154 varyingDeclaration += GenerateVectorVaryingDeclaration(3, 1, varyingCount);
155 varyingCount += 1;
156 }
157
158 for (GLint i = 0; i < vec3ArrayCount; i++)
159 {
160 varyingDeclaration += GenerateVectorVaryingDeclaration(3, 2, varyingCount);
161 varyingCount += 1;
162 }
163
164 for (GLint i = 0; i < vec4Count; i++)
165 {
166 varyingDeclaration += GenerateVectorVaryingDeclaration(4, 1, varyingCount);
167 varyingCount += 1;
168 }
169
170 for (GLint i = 0; i < vec4ArrayCount; i++)
171 {
172 varyingDeclaration += GenerateVectorVaryingDeclaration(4, 2, varyingCount);
173 varyingCount += 1;
174 }
175
176 // Generate the vertex shader
177 vertexShader->clear();
178 vertexShader->append(varyingDeclaration);
179 vertexShader->append("\nvoid main()\n{\n");
180
181 unsigned int currentVSVarying = 0;
182
183 for (GLint i = 0; i < floatCount; i++)
184 {
185 vertexShader->append(GenerateVectorVaryingSettingCode(1, 1, currentVSVarying));
186 currentVSVarying += 1;
187 }
188
189 for (GLint i = 0; i < floatArrayCount; i++)
190 {
191 vertexShader->append(GenerateVectorVaryingSettingCode(1, 2, currentVSVarying));
192 currentVSVarying += 1;
193 }
194
195 for (GLint i = 0; i < vec2Count; i++)
196 {
197 vertexShader->append(GenerateVectorVaryingSettingCode(2, 1, currentVSVarying));
198 currentVSVarying += 1;
199 }
200
201 for (GLint i = 0; i < vec2ArrayCount; i++)
202 {
203 vertexShader->append(GenerateVectorVaryingSettingCode(2, 2, currentVSVarying));
204 currentVSVarying += 1;
205 }
206
207 for (GLint i = 0; i < vec3Count; i++)
208 {
209 vertexShader->append(GenerateVectorVaryingSettingCode(3, 1, currentVSVarying));
210 currentVSVarying += 1;
211 }
212
213 for (GLint i = 0; i < vec3ArrayCount; i++)
214 {
215 vertexShader->append(GenerateVectorVaryingSettingCode(3, 2, currentVSVarying));
216 currentVSVarying += 1;
217 }
218
219 for (GLint i = 0; i < vec4Count; i++)
220 {
221 vertexShader->append(GenerateVectorVaryingSettingCode(4, 1, currentVSVarying));
222 currentVSVarying += 1;
223 }
224
225 for (GLint i = 0; i < vec4ArrayCount; i++)
226 {
227 vertexShader->append(GenerateVectorVaryingSettingCode(4, 2, currentVSVarying));
228 currentVSVarying += 1;
229 }
230
231 if (usePointSize)
232 {
233 vertexShader->append("gl_PointSize = 1.0;\n");
234 }
235
236 vertexShader->append("}\n");
237
238 // Generate the fragment shader
239 fragmentShader->clear();
240 fragmentShader->append("precision highp float;\n");
241 fragmentShader->append(varyingDeclaration);
242 fragmentShader->append("\nvoid main() \n{ \n\tvec4 retColor = vec4(0,0,0,0);\n");
243
244 unsigned int currentFSVarying = 0;
245
246 // Make use of the float varyings
247 fragmentShader->append("\tretColor += vec4(");
248
249 for (GLint i = 0; i < floatCount; i++)
250 {
251 fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying));
252 currentFSVarying += 1;
253 }
254
255 for (GLint i = 0; i < floatArrayCount; i++)
256 {
257 fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying));
258 currentFSVarying += 1;
259 }
260
261 fragmentShader->append("0.0, 0.0, 0.0, 0.0);\n");
262
263 // Make use of the vec2 varyings
264 fragmentShader->append("\tretColor += vec4(");
265
266 for (GLint i = 0; i < vec2Count; i++)
267 {
268 fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying));
269 currentFSVarying += 1;
270 }
271
272 for (GLint i = 0; i < vec2ArrayCount; i++)
273 {
274 fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying));
275 currentFSVarying += 1;
276 }
277
278 fragmentShader->append("vec2(0.0, 0.0), 0.0, 0.0);\n");
279
280 // Make use of the vec3 varyings
281 fragmentShader->append("\tretColor += vec4(");
282
283 for (GLint i = 0; i < vec3Count; i++)
284 {
285 fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying));
286 currentFSVarying += 1;
287 }
288
289 for (GLint i = 0; i < vec3ArrayCount; i++)
290 {
291 fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying));
292 currentFSVarying += 1;
293 }
294
295 fragmentShader->append("vec3(0.0, 0.0, 0.0), 0.0);\n");
296
297 // Make use of the vec4 varyings
298 fragmentShader->append("\tretColor += ");
299
300 for (GLint i = 0; i < vec4Count; i++)
301 {
302 fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying));
303 currentFSVarying += 1;
304 }
305
306 for (GLint i = 0; i < vec4ArrayCount; i++)
307 {
308 fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying));
309 currentFSVarying += 1;
310 }
311
312 fragmentShader->append("vec4(0.0, 0.0, 0.0, 0.0);\n");
313
314 // Set gl_FragColor, and use special variables if requested
315 fragmentShader->append("\tgl_FragColor = retColor");
316
317 if (useFragCoord)
318 {
319 fragmentShader->append(" + gl_FragCoord");
320 }
321
322 if (usePointCoord)
323 {
324 fragmentShader->append(" + vec4(gl_PointCoord, 0.0, 0.0)");
325 }
326
327 fragmentShader->append(";\n}");
328 }
329
VaryingTestBase(GLint floatCount,GLint floatArrayCount,GLint vec2Count,GLint vec2ArrayCount,GLint vec3Count,GLint vec3ArrayCount,GLint vec4Count,GLint vec4ArrayCount,bool useFragCoord,bool usePointCoord,bool usePointSize,bool expectSuccess)330 void VaryingTestBase(GLint floatCount,
331 GLint floatArrayCount,
332 GLint vec2Count,
333 GLint vec2ArrayCount,
334 GLint vec3Count,
335 GLint vec3ArrayCount,
336 GLint vec4Count,
337 GLint vec4ArrayCount,
338 bool useFragCoord,
339 bool usePointCoord,
340 bool usePointSize,
341 bool expectSuccess)
342 {
343 std::string fragmentShaderSource;
344 std::string vertexShaderSource;
345
346 GenerateGLSLWithVaryings(floatCount, floatArrayCount, vec2Count, vec2ArrayCount, vec3Count,
347 vec3ArrayCount, vec4Count, vec4ArrayCount, useFragCoord,
348 usePointCoord, usePointSize, &fragmentShaderSource,
349 &vertexShaderSource);
350
351 GLuint program = CompileProgram(vertexShaderSource.c_str(), fragmentShaderSource.c_str());
352
353 if (expectSuccess)
354 {
355 EXPECT_NE(0u, program);
356 }
357 else
358 {
359 EXPECT_EQ(0u, program);
360 }
361 }
362
CompileGLSLWithUniformsAndSamplers(GLint vertexUniformCount,GLint fragmentUniformCount,GLint vertexSamplersCount,GLint fragmentSamplersCount,bool expectSuccess)363 void CompileGLSLWithUniformsAndSamplers(GLint vertexUniformCount,
364 GLint fragmentUniformCount,
365 GLint vertexSamplersCount,
366 GLint fragmentSamplersCount,
367 bool expectSuccess)
368 {
369 std::stringstream vertexShader;
370 std::stringstream fragmentShader;
371
372 // Generate the vertex shader
373 vertexShader << "precision mediump float;\n";
374
375 for (int i = 0; i < vertexUniformCount; i++)
376 {
377 vertexShader << "uniform vec4 v" << i << ";\n";
378 }
379
380 for (int i = 0; i < vertexSamplersCount; i++)
381 {
382 vertexShader << "uniform sampler2D s" << i << ";\n";
383 }
384
385 vertexShader << "void main()\n{\n";
386
387 for (int i = 0; i < vertexUniformCount; i++)
388 {
389 vertexShader << " gl_Position += v" << i << ";\n";
390 }
391
392 for (int i = 0; i < vertexSamplersCount; i++)
393 {
394 vertexShader << " gl_Position += texture2D(s" << i << ", vec2(0.0, 0.0));\n";
395 }
396
397 if (vertexUniformCount == 0 && vertexSamplersCount == 0)
398 {
399 vertexShader << " gl_Position = vec4(0.0);\n";
400 }
401
402 vertexShader << "}\n";
403
404 // Generate the fragment shader
405 fragmentShader << "precision mediump float;\n";
406
407 for (int i = 0; i < fragmentUniformCount; i++)
408 {
409 fragmentShader << "uniform vec4 v" << i << ";\n";
410 }
411
412 for (int i = 0; i < fragmentSamplersCount; i++)
413 {
414 fragmentShader << "uniform sampler2D s" << i << ";\n";
415 }
416
417 fragmentShader << "void main()\n{\n";
418
419 for (int i = 0; i < fragmentUniformCount; i++)
420 {
421 fragmentShader << " gl_FragColor += v" << i << ";\n";
422 }
423
424 for (int i = 0; i < fragmentSamplersCount; i++)
425 {
426 fragmentShader << " gl_FragColor += texture2D(s" << i << ", vec2(0.0, 0.0));\n";
427 }
428
429 if (fragmentUniformCount == 0 && fragmentSamplersCount == 0)
430 {
431 fragmentShader << " gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n";
432 }
433
434 fragmentShader << "}\n";
435
436 GLuint program = CompileProgram(vertexShader.str().c_str(), fragmentShader.str().c_str());
437
438 if (expectSuccess)
439 {
440 EXPECT_NE(0u, program);
441 }
442 else
443 {
444 EXPECT_EQ(0u, program);
445 }
446 }
447
QueryErrorMessage(GLuint program)448 std::string QueryErrorMessage(GLuint program)
449 {
450 GLint infoLogLength;
451 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);
452 EXPECT_GL_NO_ERROR();
453
454 if (infoLogLength >= 1)
455 {
456 std::vector<GLchar> infoLog(infoLogLength);
457 glGetProgramInfoLog(program, static_cast<GLsizei>(infoLog.size()), nullptr,
458 infoLog.data());
459 EXPECT_GL_NO_ERROR();
460 return infoLog.data();
461 }
462
463 return "";
464 }
465
validateComponentsInErrorMessage(const char * vertexShader,const char * fragmentShader,const char * expectedErrorType,const char * expectedVariableFullName)466 void validateComponentsInErrorMessage(const char *vertexShader,
467 const char *fragmentShader,
468 const char *expectedErrorType,
469 const char *expectedVariableFullName)
470 {
471 GLuint vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
472 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);
473
474 GLuint program = glCreateProgram();
475 glAttachShader(program, vs);
476 glAttachShader(program, fs);
477 glLinkProgram(program);
478
479 glDetachShader(program, vs);
480 glDetachShader(program, fs);
481 glDeleteShader(vs);
482 glDeleteShader(fs);
483
484 const std::string errorMessage = QueryErrorMessage(program);
485 printf("%s\n", errorMessage.c_str());
486
487 EXPECT_NE(std::string::npos, errorMessage.find(expectedErrorType));
488 EXPECT_NE(std::string::npos, errorMessage.find(expectedVariableFullName));
489
490 glDeleteProgram(program);
491 ASSERT_GL_NO_ERROR();
492 }
493
verifyAttachment2DColor(unsigned int index,GLuint textureName,GLenum target,GLint level,GLColor color)494 void verifyAttachment2DColor(unsigned int index,
495 GLuint textureName,
496 GLenum target,
497 GLint level,
498 GLColor color)
499 {
500 glReadBuffer(GL_COLOR_ATTACHMENT0 + index);
501 ASSERT_GL_NO_ERROR();
502
503 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, color)
504 << "index " << index;
505 }
506
ExpectedExtensionMacros(std::vector<std::string> expected)507 std::string ExpectedExtensionMacros(std::vector<std::string> expected)
508 {
509 std::string shader;
510 for (const auto &ext : expected)
511 {
512 if (IsGLExtensionEnabled(ext))
513 {
514 shader += "\n#ifndef " + ext + "\n#error !defined(" + ext + ")\n#endif\n";
515 }
516 }
517 return shader;
518 }
519
UnexpectedExtensionMacros(std::vector<std::string> unexpected)520 std::string UnexpectedExtensionMacros(std::vector<std::string> unexpected)
521 {
522 std::string shader;
523 for (const auto &ext : unexpected)
524 {
525 shader += "\n#ifdef " + ext + "\n#error defined(" + ext + ")\n#endif\n";
526 }
527 return shader;
528 }
529 };
530
531 class GLSLTestNoValidation : public GLSLTest
532 {
533 public:
GLSLTestNoValidation()534 GLSLTestNoValidation() { setNoErrorEnabled(true); }
535 };
536
537 class GLSLTest_ES3 : public GLSLTest
538 {};
539
540 class GLSLTest_ES31 : public GLSLTest
541 {
542 protected:
543 void testArrayOfArrayOfSamplerDynamicIndex(const APIExtensionVersion usedExtension);
544 void testTessellationTextureBufferAccess(const APIExtensionVersion usedExtension);
545 };
546
547 // Tests the "init output variables" ANGLE shader translator option.
548 class GLSLTest_ES31_InitShaderVariables : public GLSLTest
549 {};
550
BuildBigInitialStackShader(int length)551 std::string BuildBigInitialStackShader(int length)
552 {
553 std::string result;
554 result += "void main() { \n";
555 for (int i = 0; i < length; i++)
556 {
557 result += " if (true) { \n";
558 }
559 result += " int temp; \n";
560 for (int i = 0; i <= length; i++)
561 {
562 result += "} \n";
563 }
564 return result;
565 }
566
567 // Tests a shader from conformance.olges/GL/build/build_017_to_024
568 // This shader uses chained assign-equals ops with swizzle, often reusing the same variable
569 // as part of a swizzle.
570
571 // Skipped on NV: angleproject:7029
TEST_P(GLSLTest,SwizzledChainedAssignIncrement)572 TEST_P(GLSLTest, SwizzledChainedAssignIncrement)
573 {
574 constexpr char kFS[] =
575 R"(
576 precision mediump float;
577 void main() {
578 vec2 v = vec2(1,5);
579 // at the end of next statement, values in
580 // v.x = 12, v.y = 12
581 v.xy += v.yx += v.xy;
582 // v1 and v2, both are initialized with (12,12)
583 vec2 v1 = v, v2 = v;
584 v1.xy += v2.yx += ++(v.xy); // v1 = 37, v2 = 25 each
585 v1.xy += v2.yx += (v.xy)++; // v1 = 75, v2 = 38 each
586 gl_FragColor = vec4(v1,v2)/255.; // 75, 75, 38, 38
587 })";
588
589 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
590 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
591 ASSERT_GL_NO_ERROR();
592 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(75, 75, 38, 38));
593 }
594
TEST_P(GLSLTest,NamelessScopedStructs)595 TEST_P(GLSLTest, NamelessScopedStructs)
596 {
597 constexpr char kFS[] = R"(precision mediump float;
598 void main()
599 {
600 struct
601 {
602 float q;
603 } b;
604
605 gl_FragColor = vec4(1, 0, 0, 1);
606 gl_FragColor.a += b.q;
607 })";
608
609 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
610 }
611
TEST_P(GLSLTest_ES3,CompareEqualityOfArrayOfVectors)612 TEST_P(GLSLTest_ES3, CompareEqualityOfArrayOfVectors)
613 {
614 constexpr char kFS[] = R"(#version 300 es
615 precision mediump float;
616 out vec4 fragColor;
617 uniform vec3 a[3];
618 uniform vec3 b[3];
619 void main() {
620 bool same = a == b;
621 fragColor = vec4(0);
622 if (same) {
623 fragColor = vec4(1);
624 }
625 }
626 )";
627
628 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
629 glUseProgram(program);
630
631 GLint aLocation = glGetUniformLocation(program, "a");
632 GLint bLocation = glGetUniformLocation(program, "b");
633 EXPECT_NE(aLocation, -1);
634 EXPECT_NE(bLocation, -1);
635
636 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
637 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
638
639 static float almostZeros[] = {0, 0, 0, 0, 0, 0, 0, 1, 0};
640 glUniform3fv(bLocation, 9, almostZeros);
641
642 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
643 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
644
645 glUniform3fv(aLocation, 9, almostZeros);
646 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
647 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
648
649 ASSERT_GL_NO_ERROR();
650 }
651
TEST_P(GLSLTest_ES3,CompareEqualityOfArrayOfMatrices)652 TEST_P(GLSLTest_ES3, CompareEqualityOfArrayOfMatrices)
653 {
654 constexpr char kFS[] = R"(#version 300 es
655 precision mediump float;
656 out vec4 fragColor;
657 uniform mat3 a[3];
658 uniform mat3 b[3];
659 void main() {
660 bool same = a == b;
661 fragColor = vec4(0);
662 if (same) {
663 fragColor = vec4(1);
664 }
665 }
666 )";
667
668 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
669 glUseProgram(program);
670
671 GLint aLocation = glGetUniformLocation(program, "a");
672 GLint bLocation = glGetUniformLocation(program, "b");
673 EXPECT_NE(aLocation, -1);
674 EXPECT_NE(bLocation, -1);
675
676 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
677 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
678
679 static float almostZeros[] = {
680 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
681 };
682 glUniformMatrix3fv(bLocation, 27, false, almostZeros);
683
684 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
685 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
686
687 glUniformMatrix3fv(aLocation, 27, false, almostZeros);
688 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
689 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
690
691 ASSERT_GL_NO_ERROR();
692 }
693
TEST_P(GLSLTest_ES3,CompareEqualityOfArrayOfFloats)694 TEST_P(GLSLTest_ES3, CompareEqualityOfArrayOfFloats)
695 {
696 constexpr char kFS[] = R"(#version 300 es
697 precision mediump float;
698 out vec4 fragColor;
699 uniform float a[3];
700 uniform float b[3];
701 void main() {
702 bool same = a == b;
703 fragColor = vec4(0);
704 if (same) {
705 fragColor = vec4(1);
706 }
707 }
708 )";
709
710 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
711 glUseProgram(program);
712
713 GLint aLocation = glGetUniformLocation(program, "a");
714 GLint bLocation = glGetUniformLocation(program, "b");
715 EXPECT_NE(aLocation, -1);
716 EXPECT_NE(bLocation, -1);
717
718 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
719 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
720
721 static float almostZeros[] = {
722 0,
723 0,
724 1,
725 };
726 glUniform1fv(bLocation, 3, almostZeros);
727
728 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
729 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
730
731 glUniform1fv(aLocation, 3, almostZeros);
732 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
733 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
734
735 ASSERT_GL_NO_ERROR();
736 }
737
TEST_P(GLSLTest_ES3,CompareInequalityOfArrayOfVectors)738 TEST_P(GLSLTest_ES3, CompareInequalityOfArrayOfVectors)
739 {
740 constexpr char kFS[] = R"(#version 300 es
741 precision mediump float;
742 out vec4 fragColor;
743 uniform vec3 a[3];
744 uniform vec3 b[3];
745 void main() {
746 bool notSame = a != b;
747 fragColor = vec4(0);
748 if (notSame) {
749 fragColor = vec4(1);
750 }
751 }
752 )";
753
754 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
755 glUseProgram(program);
756
757 GLint aLocation = glGetUniformLocation(program, "a");
758 GLint bLocation = glGetUniformLocation(program, "b");
759 EXPECT_NE(aLocation, -1);
760 EXPECT_NE(bLocation, -1);
761
762 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
763 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
764
765 static float almostZeros[] = {0, 0, 0, 0, 0, 0, 0, 1, 0};
766 glUniform3fv(bLocation, 9, almostZeros);
767
768 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
769 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
770
771 glUniform3fv(aLocation, 9, almostZeros);
772 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
773 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
774
775 ASSERT_GL_NO_ERROR();
776 }
777
TEST_P(GLSLTest_ES3,CompareInequalityOfArrayOfMatrices)778 TEST_P(GLSLTest_ES3, CompareInequalityOfArrayOfMatrices)
779 {
780 constexpr char kFS[] = R"(#version 300 es
781 precision mediump float;
782 out vec4 fragColor;
783 uniform mat3 a[3];
784 uniform mat3 b[3];
785 void main() {
786 bool notSame = a != b;
787 fragColor = vec4(0);
788 if (notSame) {
789 fragColor = vec4(1);
790 }
791 }
792 )";
793
794 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
795 glUseProgram(program);
796
797 GLint aLocation = glGetUniformLocation(program, "a");
798 GLint bLocation = glGetUniformLocation(program, "b");
799 EXPECT_NE(aLocation, -1);
800 EXPECT_NE(bLocation, -1);
801
802 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
803 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
804
805 static float almostZeros[] = {
806 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
807 };
808 glUniformMatrix3fv(bLocation, 27, false, almostZeros);
809
810 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
811 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
812
813 glUniformMatrix3fv(aLocation, 27, false, almostZeros);
814 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
815 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
816
817 ASSERT_GL_NO_ERROR();
818 }
819
TEST_P(GLSLTest_ES3,CompareInequalityOfArrayOfFloats)820 TEST_P(GLSLTest_ES3, CompareInequalityOfArrayOfFloats)
821 {
822 constexpr char kFS[] = R"(#version 300 es
823 precision mediump float;
824 out vec4 fragColor;
825 uniform float a[3];
826 uniform float b[3];
827 void main() {
828 bool notSame = a != b;
829 fragColor = vec4(0);
830 if (notSame) {
831 fragColor = vec4(1);
832 }
833 }
834 )";
835
836 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
837 glUseProgram(program);
838
839 GLint aLocation = glGetUniformLocation(program, "a");
840 GLint bLocation = glGetUniformLocation(program, "b");
841 EXPECT_NE(aLocation, -1);
842 EXPECT_NE(bLocation, -1);
843
844 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
845 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
846
847 static float almostZeros[] = {
848 0,
849 0,
850 1,
851 };
852 glUniform1fv(bLocation, 3, almostZeros);
853
854 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
855 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
856
857 glUniform1fv(aLocation, 3, almostZeros);
858 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
859 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
860
861 ASSERT_GL_NO_ERROR();
862 }
863
864 // Test that array of fragment shader outputs is processed properly and draws
865 // E.g. was issue with "out vec4 frag_color[4];"
TEST_P(GLSLTest_ES3,FragmentShaderOutputArray)866 TEST_P(GLSLTest_ES3, FragmentShaderOutputArray)
867 {
868 GLuint fbo;
869 glGenFramebuffers(1, &fbo);
870 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
871
872 GLuint textures[4];
873 glGenTextures(4, textures);
874
875 for (size_t texIndex = 0; texIndex < ArraySize(textures); texIndex++)
876 {
877 glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
878 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
879 GL_UNSIGNED_BYTE, nullptr);
880 }
881
882 GLint maxDrawBuffers;
883 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
884 ASSERT_GE(maxDrawBuffers, 4);
885
886 GLuint readFramebuffer;
887 glGenFramebuffers(1, &readFramebuffer);
888 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFramebuffer);
889
890 constexpr char kFS[] = R"(#version 300 es
891 precision highp float;
892
893 out vec4 frag_color[4];
894
895 void main()
896 {
897 frag_color[0] = vec4(1.0, 0.0, 0.0, 1.0);
898 frag_color[1] = vec4(0.0, 1.0, 0.0, 1.0);
899 frag_color[2] = vec4(0.0, 0.0, 1.0, 1.0);
900 frag_color[3] = vec4(1.0, 1.0, 1.0, 1.0);
901 }
902 )";
903
904 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
905
906 GLenum allBufs[4] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2,
907 GL_COLOR_ATTACHMENT3};
908
909 constexpr GLuint kMaxBuffers = 4;
910
911 // Enable all draw buffers.
912 for (GLuint texIndex = 0; texIndex < kMaxBuffers; texIndex++)
913 {
914 glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
915 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
916 textures[texIndex], 0);
917 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
918 textures[texIndex], 0);
919 }
920 glDrawBuffers(kMaxBuffers, allBufs);
921
922 // Draw with simple program.
923 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
924 ASSERT_GL_NO_ERROR();
925
926 verifyAttachment2DColor(0, textures[0], GL_TEXTURE_2D, 0, GLColor::red);
927 verifyAttachment2DColor(1, textures[1], GL_TEXTURE_2D, 0, GLColor::green);
928 verifyAttachment2DColor(2, textures[2], GL_TEXTURE_2D, 0, GLColor::blue);
929 verifyAttachment2DColor(3, textures[3], GL_TEXTURE_2D, 0, GLColor::white);
930 }
931
932 // Test that inactive fragment shader outputs don't cause a crash.
TEST_P(GLSLTest_ES3,InactiveFragmentShaderOutput)933 TEST_P(GLSLTest_ES3, InactiveFragmentShaderOutput)
934 {
935 constexpr char kFS[] = R"(#version 300 es
936 precision highp float;
937
938 // Make color0 inactive but specify color1 first. The Vulkan backend assigns bogus locations when
939 // compiling and fixes it up in SPIR-V. If color0's location is not fixed, it will return location
940 // 1 (aliasing color1). This will lead to a Vulkan validation warning about attachment 0 not being
941 // written to, which shouldn't be fatal.
942 layout(location = 1) out vec4 color1;
943 layout(location = 0) out vec4 color0;
944
945 void main()
946 {
947 color1 = vec4(0.0, 1.0, 0.0, 1.0);
948 }
949 )";
950
951 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
952
953 constexpr GLint kDrawBufferCount = 2;
954
955 GLint maxDrawBuffers;
956 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
957 ASSERT_GE(maxDrawBuffers, kDrawBufferCount);
958
959 GLTexture textures[kDrawBufferCount];
960
961 for (GLint texIndex = 0; texIndex < kDrawBufferCount; ++texIndex)
962 {
963 glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
964 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
965 GL_UNSIGNED_BYTE, nullptr);
966 }
967
968 GLenum allBufs[kDrawBufferCount] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
969
970 GLFramebuffer fbo;
971 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
972
973 // Enable all draw buffers.
974 for (GLint texIndex = 0; texIndex < kDrawBufferCount; ++texIndex)
975 {
976 glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
977 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
978 textures[texIndex], 0);
979 }
980 glDrawBuffers(kDrawBufferCount, allBufs);
981
982 // Draw with simple program.
983 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
984 ASSERT_GL_NO_ERROR();
985 }
986
TEST_P(GLSLTest,ScopedStructsOrderBug)987 TEST_P(GLSLTest, ScopedStructsOrderBug)
988 {
989 constexpr char kFS[] = R"(precision mediump float;
990
991 struct T
992 {
993 float f;
994 };
995
996 void main()
997 {
998 T a;
999
1000 struct T
1001 {
1002 float q;
1003 };
1004
1005 T b;
1006
1007 gl_FragColor = vec4(1, 0, 0, 1);
1008 gl_FragColor.a += a.f;
1009 gl_FragColor.a += b.q;
1010 })";
1011
1012 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
1013 }
1014
1015 // Test that defining a struct together with an inactive uniform, then using it in a scope that has
1016 // another struct with the same name declared works.
TEST_P(GLSLTest,ScopedStructsOrderBug2)1017 TEST_P(GLSLTest, ScopedStructsOrderBug2)
1018 {
1019 constexpr char kFS[] = R"(precision mediump float;
1020
1021 uniform struct T
1022 {
1023 float f;
1024 } x;
1025
1026 void main()
1027 {
1028 T a;
1029
1030 struct T
1031 {
1032 float q;
1033 };
1034
1035 T b;
1036
1037 gl_FragColor = vec4(1, 0, 0, 1);
1038 gl_FragColor.a += a.f;
1039 gl_FragColor.a += b.q;
1040 })";
1041
1042 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
1043 }
1044
1045 // Test that inactive uniforms of struct type don't cause any errors.
TEST_P(GLSLTest,InactiveStructUniform)1046 TEST_P(GLSLTest, InactiveStructUniform)
1047 {
1048 constexpr char kVS[] = R"(
1049 uniform struct
1050 {
1051 vec4 c;
1052 } s;
1053 void main()
1054 {
1055 })";
1056
1057 ANGLE_GL_PROGRAM(program, kVS, essl1_shaders::fs::Red());
1058 }
1059
1060 // Test that struct with same name can be declared in inner scope.
TEST_P(GLSLTest,SameNameStructInInnerScope)1061 TEST_P(GLSLTest, SameNameStructInInnerScope)
1062 {
1063 constexpr char kVS[] = R"(
1064 void main() {
1065 gl_Position = vec4(0);
1066 })";
1067
1068 constexpr char kFS[] = R"(
1069 struct S
1070 {
1071 mediump float f;
1072 };
1073 void main()
1074 {
1075 struct S
1076 {
1077 S n;
1078 };
1079 })";
1080
1081 ANGLE_GL_PROGRAM(program, kVS, kFS);
1082 }
1083
1084 // Regression test based on WebGL's conformance/glsl/misc/empty-declaration.html
TEST_P(GLSLTest,StructEmptyDeclaratorBug)1085 TEST_P(GLSLTest, StructEmptyDeclaratorBug)
1086 {
1087 constexpr char kVS[] = R"(
1088 struct S {
1089 float member;
1090 }, a;
1091 void main() {
1092 a.member = 0.0;
1093 gl_Position = vec4(a.member);
1094 })";
1095
1096 constexpr char kFS[] = R"(precision mediump float;
1097 void main()
1098 {
1099 gl_FragColor = vec4(1.0,0.0,0.0,1.0);
1100 })";
1101
1102 ANGLE_GL_PROGRAM(program, kVS, kFS);
1103 }
1104
1105 // Regression test based on WebGL's conformance/ogles/GL/build/build_001_to_008.html
TEST_P(GLSLTest,StructConstantFoldingBug)1106 TEST_P(GLSLTest, StructConstantFoldingBug)
1107 {
1108 constexpr char kVS[] = R"(
1109 void main()
1110 {
1111
1112 const struct s2 {
1113 int i;
1114 vec3 v3;
1115 bvec4 bv4;
1116 } s22 = s2(8, vec3(9, 10, 11), bvec4(true, false, true, false));
1117
1118 struct s4 {
1119 int ii;
1120 vec4 v4;
1121 };
1122
1123 const struct s1 {
1124 s2 ss;
1125 int i;
1126 float f;
1127 mat4 m;
1128 s4 s44;
1129 } s11 = s1(s22, 2, 4.0, mat4(5), s4(6, vec4(7, 8, 9, 10))) ;
1130
1131 const int field3 = s11.i * s11.ss.i; // constant folding (int * int)
1132 const vec4 field4 = s11.s44.v4 * s11.s44.v4; // constant folding (vec4 * vec4)
1133 // 49, 64, 81, 100
1134 const vec4 v4 = vec4(s11.ss.v3.y, s11.m[3][3], field3, field4[2]); // 10.0, 5.0, 16.0, 81.0
1135 gl_Position = v4;
1136 })";
1137
1138 constexpr char kFS[] = R"(precision mediump float;
1139 precision mediump float;
1140 void main()
1141 {
1142 gl_FragColor = vec4(1.0,0.0,0.0,1.0);
1143 })";
1144
1145 ANGLE_GL_PROGRAM(program, kVS, kFS);
1146 }
1147
1148 // Test that constant folding doesn't remove struct declaration.
TEST_P(GLSLTest,StructConstantFoldingBug2)1149 TEST_P(GLSLTest, StructConstantFoldingBug2)
1150 {
1151 constexpr char kVS[] = R"(
1152 uniform vec4 u;
1153
1154 void main()
1155 {
1156
1157 const struct s2 {
1158 int i;
1159 vec3 v3;
1160 bvec4 bv4;
1161 } s22 = s2(8, vec3(9, 10, 11), bvec4(true, false, true, false));
1162
1163 s2 x;
1164 x.v3 = u.xyz;
1165
1166 gl_Position = vec4(x.v3, float(s22.i));
1167 })";
1168
1169 constexpr char kFS[] = R"(precision mediump float;
1170 precision mediump float;
1171 void main()
1172 {
1173 gl_FragColor = vec4(1.0,0.0,0.0,1.0);
1174 })";
1175
1176 ANGLE_GL_PROGRAM(program, kVS, kFS);
1177 }
1178
TEST_P(GLSLTest,ScopedStructsBug)1179 TEST_P(GLSLTest, ScopedStructsBug)
1180 {
1181 constexpr char kFS[] = R"(precision mediump float;
1182
1183 struct T_0
1184 {
1185 float f;
1186 };
1187
1188 void main()
1189 {
1190 gl_FragColor = vec4(1, 0, 0, 1);
1191
1192 struct T
1193 {
1194 vec2 v;
1195 };
1196
1197 T_0 a;
1198 T b;
1199
1200 gl_FragColor.a += a.f;
1201 gl_FragColor.a += b.v.x;
1202 })";
1203
1204 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
1205 }
1206
TEST_P(GLSLTest,DxPositionBug)1207 TEST_P(GLSLTest, DxPositionBug)
1208 {
1209 constexpr char kVS[] = R"(attribute vec4 inputAttribute;
1210 varying float dx_Position;
1211 void main()
1212 {
1213 gl_Position = vec4(inputAttribute);
1214 dx_Position = 0.0;
1215 })";
1216
1217 constexpr char kFS[] = R"(precision mediump float;
1218
1219 varying float dx_Position;
1220
1221 void main()
1222 {
1223 gl_FragColor = vec4(dx_Position, 0, 0, 1);
1224 })";
1225
1226 ANGLE_GL_PROGRAM(program, kVS, kFS);
1227 }
1228
1229 // Draw an array of points with the first vertex offset at 0 using gl_VertexID
TEST_P(GLSLTest_ES3,GLVertexIDOffsetZeroDrawArray)1230 TEST_P(GLSLTest_ES3, GLVertexIDOffsetZeroDrawArray)
1231 {
1232 constexpr int kStartIndex = 0;
1233 constexpr int kArrayLength = 5;
1234 constexpr char kVS[] = R"(#version 300 es
1235 precision highp float;
1236 void main() {
1237 gl_Position = vec4(float(gl_VertexID)/10.0, 0, 0, 1);
1238 gl_PointSize = 3.0;
1239 })";
1240
1241 constexpr char kFS[] = R"(#version 300 es
1242 precision highp float;
1243 out vec4 outColor;
1244 void main() {
1245 outColor = vec4(1.0, 0.0, 0.0, 1.0);
1246 })";
1247
1248 ANGLE_GL_PROGRAM(program, kVS, kFS);
1249
1250 glUseProgram(program);
1251 glDrawArrays(GL_POINTS, kStartIndex, kArrayLength);
1252
1253 double pointCenterX = static_cast<double>(getWindowWidth()) / 2.0;
1254 double pointCenterY = static_cast<double>(getWindowHeight()) / 2.0;
1255 for (int i = kStartIndex; i < kStartIndex + kArrayLength; i++)
1256 {
1257 double pointOffsetX = static_cast<double>(i * getWindowWidth()) / 20.0;
1258 EXPECT_PIXEL_COLOR_EQ(static_cast<int>(pointCenterX + pointOffsetX),
1259 static_cast<int>(pointCenterY), GLColor::red);
1260 }
1261 }
1262
GetFirstIntPixelRedValue()1263 GLint GetFirstIntPixelRedValue()
1264 {
1265 GLint pixel[4];
1266 glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_INT, pixel);
1267 return pixel[0];
1268 }
1269
TEST_P(GLSLTest_ES3,GLVertexIDIntegerTextureDrawElements)1270 TEST_P(GLSLTest_ES3, GLVertexIDIntegerTextureDrawElements)
1271 {
1272 constexpr char kVS[] = R"(#version 300 es
1273 flat out highp int vVertexID;
1274
1275 void main() {
1276 vVertexID = gl_VertexID;
1277 gl_PointSize = 1.0;
1278 gl_Position = vec4(0,0,0,1);
1279 })";
1280
1281 constexpr char kFS[] = R"(#version 300 es
1282 flat in highp int vVertexID;
1283 out highp int oVertexID;
1284 void main() {
1285 oVertexID = vVertexID;
1286 })";
1287
1288 ANGLE_GL_PROGRAM(program, kVS, kFS);
1289 glUseProgram(program);
1290 glViewport(0, 0, 1, 1);
1291
1292 GLTexture tex;
1293 glBindTexture(GL_TEXTURE_2D, tex);
1294 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, 1, 1);
1295 GLFramebuffer fb;
1296 glBindFramebuffer(GL_FRAMEBUFFER, fb);
1297 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
1298
1299 EXPECT_GL_NO_ERROR();
1300
1301 GLint clearData[4] = {42};
1302 glClearBufferiv(GL_COLOR, 0, clearData);
1303 EXPECT_EQ(42, GetFirstIntPixelRedValue());
1304
1305 const int kIndexDataSize = 5;
1306 GLushort indexData[] = {1, 2, 5, 3, 10000};
1307 GLBuffer indexBuffer;
1308 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1309 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_STATIC_DRAW);
1310
1311 for (size_t first = 0; first < kIndexDataSize; ++first)
1312 {
1313 for (size_t count = 1; first + count <= kIndexDataSize; ++count)
1314 {
1315 glDrawElements(GL_POINTS, count, GL_UNSIGNED_SHORT,
1316 reinterpret_cast<const void *>(first * 2u));
1317 GLint expected = indexData[first + count - 1];
1318 GLint actual = GetFirstIntPixelRedValue();
1319 EXPECT_EQ(expected, actual);
1320 }
1321 }
1322 EXPECT_GL_NO_ERROR();
1323 }
1324
TEST_P(GLSLTest_ES3,GLVertexIDIntegerTextureDrawElementsU8)1325 TEST_P(GLSLTest_ES3, GLVertexIDIntegerTextureDrawElementsU8)
1326 {
1327 constexpr char kVS[] = R"(#version 300 es
1328 flat out highp int vVertexID;
1329
1330 void main() {
1331 vVertexID = gl_VertexID;
1332 gl_PointSize = 1.0;
1333 gl_Position = vec4(0,0,0,1);
1334 })";
1335
1336 constexpr char kFS[] = R"(#version 300 es
1337 flat in highp int vVertexID;
1338 out highp int oVertexID;
1339 void main() {
1340 oVertexID = vVertexID;
1341 })";
1342
1343 ANGLE_GL_PROGRAM(program, kVS, kFS);
1344 glUseProgram(program);
1345 glViewport(0, 0, 1, 1);
1346
1347 GLTexture tex;
1348 glBindTexture(GL_TEXTURE_2D, tex);
1349 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, 1, 1);
1350 GLFramebuffer fb;
1351 glBindFramebuffer(GL_FRAMEBUFFER, fb);
1352 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
1353
1354 EXPECT_GL_NO_ERROR();
1355
1356 GLint clearData[4] = {42};
1357 glClearBufferiv(GL_COLOR, 0, clearData);
1358 EXPECT_EQ(42, GetFirstIntPixelRedValue());
1359
1360 const int kIndexDataSize = 5;
1361 GLubyte indexData[] = {1, 2, 5, 3, 100};
1362 GLBuffer indexBuffer;
1363 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1364 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_STATIC_DRAW);
1365
1366 for (size_t first = 0; first < kIndexDataSize; ++first)
1367 {
1368 for (size_t count = 1; first + count <= kIndexDataSize; ++count)
1369 {
1370 glDrawElements(GL_POINTS, count, GL_UNSIGNED_BYTE,
1371 reinterpret_cast<const void *>(first));
1372 GLint expected = indexData[first + count - 1];
1373 GLint actual = GetFirstIntPixelRedValue();
1374 EXPECT_EQ(expected, actual);
1375 }
1376 }
1377 EXPECT_GL_NO_ERROR();
1378 }
1379
GLVertexIDIntegerTextureDrawElementsU8Line_Helper(size_t first,const GLubyte * indices)1380 void GLVertexIDIntegerTextureDrawElementsU8Line_Helper(size_t first, const GLubyte *indices)
1381 {
1382 glDrawElements(GL_LINES, 2, GL_UNSIGNED_BYTE, reinterpret_cast<const void *>(first));
1383
1384 GLint pixels[8];
1385 glReadPixels(0, 0, 2, 1, GL_RGBA_INTEGER, GL_INT, pixels);
1386
1387 GLint expected = indices[first + 1];
1388 EXPECT_EQ(expected, pixels[0]);
1389 EXPECT_EQ(expected, pixels[4]);
1390 }
1391
TEST_P(GLSLTest_ES3,GLVertexIDIntegerTextureDrawElementsU8Line)1392 TEST_P(GLSLTest_ES3, GLVertexIDIntegerTextureDrawElementsU8Line)
1393 {
1394 constexpr char kVS[] = R"(#version 300 es
1395 flat out highp int vVertexID;
1396 layout(location = 0) in vec4 position;
1397
1398 void main() {
1399 vVertexID = gl_VertexID;
1400 gl_Position = position;
1401 })";
1402
1403 constexpr char kFS[] = R"(#version 300 es
1404 flat in highp int vVertexID;
1405 out highp int oVertexID;
1406 void main() {
1407 oVertexID = vVertexID;
1408 })";
1409
1410 ANGLE_GL_PROGRAM(program, kVS, kFS);
1411 glUseProgram(program);
1412 glViewport(0, 0, 2, 1);
1413
1414 GLTexture tex;
1415 glBindTexture(GL_TEXTURE_2D, tex);
1416 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, 2, 1);
1417 GLFramebuffer fb;
1418 glBindFramebuffer(GL_FRAMEBUFFER, fb);
1419 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
1420
1421 EXPECT_GL_NO_ERROR();
1422
1423 struct LR
1424 {
1425 LR() : X0(-1.0f), X1(1.0f) {}
1426 float X0;
1427 float X1;
1428 };
1429 constexpr int kNumVertices = 100;
1430 LR vertData[kNumVertices];
1431 GLBuffer buf;
1432 glBindBuffer(GL_ARRAY_BUFFER, buf);
1433 glBufferData(GL_ARRAY_BUFFER, sizeof(vertData), vertData, GL_STATIC_DRAW);
1434 glEnableVertexAttribArray(0);
1435 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
1436
1437 GLint clearData[4] = {42};
1438 glClearBufferiv(GL_COLOR, 0, clearData);
1439 EXPECT_EQ(42, GetFirstIntPixelRedValue());
1440
1441 GLubyte indexData[] = {1, 4, 5, 2, 50, 61};
1442 GLBuffer indexBuffer;
1443 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1444 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_STATIC_DRAW);
1445
1446 GLVertexIDIntegerTextureDrawElementsU8Line_Helper(0, indexData);
1447 GLVertexIDIntegerTextureDrawElementsU8Line_Helper(1, indexData);
1448 GLVertexIDIntegerTextureDrawElementsU8Line_Helper(2, indexData);
1449 GLVertexIDIntegerTextureDrawElementsU8Line_Helper(4, indexData);
1450
1451 EXPECT_GL_NO_ERROR();
1452 }
1453
1454 // Test gl_VertexID works with lines
TEST_P(GLSLTest_ES3,GLVertexIDIntegerTextureDrawElementsU8LineIds)1455 TEST_P(GLSLTest_ES3, GLVertexIDIntegerTextureDrawElementsU8LineIds)
1456 {
1457 // Draws lines via indices (glDrawElements). Each pair of indices
1458 // draws the next consecutive pixel. For 2 points, because we're
1459 // using int attributes, they must be "flat" and so the spec
1460 // says for a given line the value should come from the second
1461 // of the 2 points. (see: OpenGL ES 3.0.2 spec Table 2.12)
1462 // Each line is only 1 pixel long so every other pixel should
1463 // be the default value.
1464 constexpr char kVS[] = R"(#version 300 es
1465 flat out highp int vVertexID;
1466 layout(location = 0) in float position;
1467 uniform float width;
1468
1469 void main() {
1470 vVertexID = gl_VertexID;
1471 gl_Position = vec4(position / width * 2.0 - 1.0, 0, 0, 1);
1472 })";
1473
1474 constexpr char kFS[] = R"(#version 300 es
1475 flat in highp int vVertexID;
1476 out highp int oVertexID;
1477 void main() {
1478 oVertexID = vVertexID;
1479 })";
1480
1481 GLubyte indexData[] = {1, 4, 5, 2, 50, 61, 32, 33};
1482 constexpr size_t kNumIndices = sizeof(indexData) / sizeof(indexData[0]);
1483 GLBuffer indexBuffer;
1484 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1485 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_STATIC_DRAW);
1486
1487 ANGLE_GL_PROGRAM(program, kVS, kFS);
1488 glUseProgram(program);
1489 glUniform1f(glGetUniformLocation(program, "width"), kNumIndices);
1490 glViewport(0, 0, kNumIndices, 1);
1491
1492 GLTexture tex;
1493 glBindTexture(GL_TEXTURE_2D, tex);
1494 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, kNumIndices, 1);
1495 GLFramebuffer fb;
1496 glBindFramebuffer(GL_FRAMEBUFFER, fb);
1497 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
1498
1499 constexpr int kNumVertices = 100;
1500 std::vector<float> vertData(kNumVertices, -1.0f);
1501 {
1502 int i = 0;
1503 for (GLubyte ndx : indexData)
1504 {
1505 vertData[ndx] = i++;
1506 }
1507 }
1508 GLBuffer buf;
1509 glBindBuffer(GL_ARRAY_BUFFER, buf);
1510 glBufferData(GL_ARRAY_BUFFER, vertData.size() * sizeof(float), vertData.data(), GL_STATIC_DRAW);
1511 glEnableVertexAttribArray(0);
1512 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
1513
1514 GLint kDefaultValue = 42;
1515 GLint clearData[4] = {kDefaultValue};
1516 glClearBufferiv(GL_COLOR, 0, clearData);
1517 EXPECT_EQ(kDefaultValue, GetFirstIntPixelRedValue());
1518
1519 EXPECT_GL_NO_ERROR();
1520
1521 glDrawElements(GL_LINES, kNumIndices, GL_UNSIGNED_BYTE, 0);
1522
1523 GLint pixels[kNumIndices * 4];
1524 glReadPixels(0, 0, kNumIndices, 1, GL_RGBA_INTEGER, GL_INT, pixels);
1525
1526 for (size_t i = 0; i < kNumIndices; ++i)
1527 {
1528 const int expected = i % 2 ? kDefaultValue : indexData[i + 1];
1529 const int actual = pixels[i * 4];
1530 EXPECT_EQ(expected, actual);
1531 }
1532
1533 EXPECT_GL_NO_ERROR();
1534 }
1535
1536 // Helper function for the GLVertexIDIntegerTextureDrawArrays test
GLVertexIDIntegerTextureDrawArrays_helper(int first,int count,GLenum err)1537 void GLVertexIDIntegerTextureDrawArrays_helper(int first, int count, GLenum err)
1538 {
1539 glDrawArrays(GL_POINTS, first, count);
1540
1541 int pixel[4];
1542 glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_INT, pixel);
1543 // If we call this function with err as GL_NO_ERROR, then we expect no error and check the
1544 // pixels.
1545 if (err == static_cast<GLenum>(GL_NO_ERROR))
1546 {
1547 EXPECT_GL_NO_ERROR();
1548 EXPECT_EQ(pixel[0], first + count - 1);
1549 }
1550 else
1551 {
1552 // If we call this function with err set, we will allow the error, but check the pixels if
1553 // the error hasn't occurred.
1554 GLenum glError = glGetError();
1555 if (glError == err || glError == static_cast<GLenum>(GL_NO_ERROR))
1556 {
1557 EXPECT_EQ(pixel[0], first + count - 1);
1558 }
1559 }
1560 }
1561
1562 // Ensure gl_VertexID gets passed to an integer texture properly when drawArrays is called. This
1563 // is based off the WebGL test:
1564 // https://github.com/KhronosGroup/WebGL/blob/master/sdk/tests/conformance2/rendering/vertex-id.html
TEST_P(GLSLTest_ES3,GLVertexIDIntegerTextureDrawArrays)1565 TEST_P(GLSLTest_ES3, GLVertexIDIntegerTextureDrawArrays)
1566 {
1567 constexpr char kVS[] = R"(#version 300 es
1568 flat out highp int vVertexID;
1569 void main() {
1570 vVertexID = gl_VertexID;
1571 gl_Position = vec4(0,0,0,1);
1572 gl_PointSize = 1.0;
1573 })";
1574
1575 constexpr char kFS[] = R"(#version 300 es
1576 flat in highp int vVertexID;
1577 out highp int oVertexID;
1578 void main() {
1579 oVertexID = vVertexID;
1580 })";
1581
1582 ANGLE_GL_PROGRAM(program, kVS, kFS);
1583 glUseProgram(program);
1584 glViewport(0, 0, 1, 1);
1585
1586 GLTexture texture;
1587 glBindTexture(GL_TEXTURE_2D, texture);
1588 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, 1, 1);
1589 GLFramebuffer fbo;
1590 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1591 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1592 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1593 EXPECT_GL_NO_ERROR();
1594
1595 // Clear the texture to 42 to ensure the first test case doesn't accidentally pass
1596 GLint val[4] = {42};
1597 glClearBufferiv(GL_COLOR, 0, val);
1598 int pixel[4];
1599 glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_INT, pixel);
1600 EXPECT_EQ(pixel[0], val[0]);
1601
1602 GLVertexIDIntegerTextureDrawArrays_helper(0, 1, GL_NO_ERROR);
1603 GLVertexIDIntegerTextureDrawArrays_helper(1, 1, GL_NO_ERROR);
1604 GLVertexIDIntegerTextureDrawArrays_helper(10000, 1, GL_NO_ERROR);
1605 GLVertexIDIntegerTextureDrawArrays_helper(100000, 1, GL_NO_ERROR);
1606 GLVertexIDIntegerTextureDrawArrays_helper(1000000, 1, GL_NO_ERROR);
1607 GLVertexIDIntegerTextureDrawArrays_helper(0, 2, GL_NO_ERROR);
1608 GLVertexIDIntegerTextureDrawArrays_helper(1, 2, GL_NO_ERROR);
1609 GLVertexIDIntegerTextureDrawArrays_helper(10000, 2, GL_NO_ERROR);
1610 GLVertexIDIntegerTextureDrawArrays_helper(100000, 2, GL_NO_ERROR);
1611 GLVertexIDIntegerTextureDrawArrays_helper(1000000, 2, GL_NO_ERROR);
1612
1613 int32_t int32Max = 0x7FFFFFFF;
1614 GLVertexIDIntegerTextureDrawArrays_helper(int32Max - 2, 1, GL_OUT_OF_MEMORY);
1615 GLVertexIDIntegerTextureDrawArrays_helper(int32Max - 1, 1, GL_OUT_OF_MEMORY);
1616 }
1617
1618 // Draw an array of points with the first vertex offset at 5 using gl_VertexID
TEST_P(GLSLTest_ES3,GLVertexIDOffsetFiveDrawArray)1619 TEST_P(GLSLTest_ES3, GLVertexIDOffsetFiveDrawArray)
1620 {
1621 // Bug in Nexus drivers, offset does not work. (anglebug.com/3264)
1622 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsOpenGLES());
1623
1624 constexpr int kStartIndex = 5;
1625 constexpr int kArrayLength = 5;
1626 constexpr char kVS[] = R"(#version 300 es
1627 precision highp float;
1628 void main() {
1629 gl_Position = vec4(float(gl_VertexID)/10.0, 0, 0, 1);
1630 gl_PointSize = 3.0;
1631 })";
1632
1633 constexpr char kFS[] = R"(#version 300 es
1634 precision highp float;
1635 out vec4 outColor;
1636 void main() {
1637 outColor = vec4(1.0, 0.0, 0.0, 1.0);
1638 })";
1639
1640 ANGLE_GL_PROGRAM(program, kVS, kFS);
1641
1642 glUseProgram(program);
1643 glDrawArrays(GL_POINTS, kStartIndex, kArrayLength);
1644
1645 double pointCenterX = static_cast<double>(getWindowWidth()) / 2.0;
1646 double pointCenterY = static_cast<double>(getWindowHeight()) / 2.0;
1647 for (int i = kStartIndex; i < kStartIndex + kArrayLength; i++)
1648 {
1649 double pointOffsetX = static_cast<double>(i * getWindowWidth()) / 20.0;
1650 EXPECT_PIXEL_COLOR_EQ(static_cast<int>(pointCenterX + pointOffsetX),
1651 static_cast<int>(pointCenterY), GLColor::red);
1652 }
1653 }
1654
TEST_P(GLSLTest,ElseIfRewriting)1655 TEST_P(GLSLTest, ElseIfRewriting)
1656 {
1657 constexpr char kVS[] =
1658 "attribute vec4 a_position;\n"
1659 "varying float v;\n"
1660 "void main() {\n"
1661 " gl_Position = a_position;\n"
1662 " v = 1.0;\n"
1663 " if (a_position.x <= 0.5) {\n"
1664 " v = 0.0;\n"
1665 " } else if (a_position.x >= 0.5) {\n"
1666 " v = 2.0;\n"
1667 " }\n"
1668 "}\n";
1669
1670 constexpr char kFS[] =
1671 "precision highp float;\n"
1672 "varying float v;\n"
1673 "void main() {\n"
1674 " vec4 color = vec4(1.0, 0.0, 0.0, 1.0);\n"
1675 " if (v >= 1.0) color = vec4(0.0, 1.0, 0.0, 1.0);\n"
1676 " if (v >= 2.0) color = vec4(0.0, 0.0, 1.0, 1.0);\n"
1677 " gl_FragColor = color;\n"
1678 "}\n";
1679
1680 ANGLE_GL_PROGRAM(program, kVS, kFS);
1681
1682 drawQuad(program, "a_position", 0.5f);
1683
1684 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
1685 EXPECT_PIXEL_EQ(getWindowWidth() - 1, 0, 0, 255, 0, 255);
1686 }
1687
TEST_P(GLSLTest,TwoElseIfRewriting)1688 TEST_P(GLSLTest, TwoElseIfRewriting)
1689 {
1690 constexpr char kVS[] =
1691 "attribute vec4 a_position;\n"
1692 "varying float v;\n"
1693 "void main() {\n"
1694 " gl_Position = a_position;\n"
1695 " if (a_position.x == 0.0) {\n"
1696 " v = 1.0;\n"
1697 " } else if (a_position.x > 0.5) {\n"
1698 " v = 0.0;\n"
1699 " } else if (a_position.x > 0.75) {\n"
1700 " v = 0.5;\n"
1701 " }\n"
1702 "}\n";
1703
1704 constexpr char kFS[] =
1705 "precision highp float;\n"
1706 "varying float v;\n"
1707 "void main() {\n"
1708 " gl_FragColor = vec4(v, 0.0, 0.0, 1.0);\n"
1709 "}\n";
1710
1711 ANGLE_GL_PROGRAM(program, kVS, kFS);
1712 }
1713
TEST_P(GLSLTest,FrontFacingAndVarying)1714 TEST_P(GLSLTest, FrontFacingAndVarying)
1715 {
1716 EGLPlatformParameters platform = GetParam().eglParameters;
1717
1718 constexpr char kVS[] = R"(attribute vec4 a_position;
1719 varying float v_varying;
1720 void main()
1721 {
1722 v_varying = a_position.x;
1723 gl_Position = a_position;
1724 })";
1725
1726 constexpr char kFS[] = R"(precision mediump float;
1727 varying float v_varying;
1728 void main()
1729 {
1730 vec4 c;
1731
1732 if (gl_FrontFacing)
1733 {
1734 c = vec4(v_varying, 0, 0, 1.0);
1735 }
1736 else
1737 {
1738 c = vec4(0, v_varying, 0, 1.0);
1739 }
1740 gl_FragColor = c;
1741 })";
1742
1743 GLuint program = CompileProgram(kVS, kFS);
1744
1745 // Compilation should fail on D3D11 feature level 9_3, since gl_FrontFacing isn't supported.
1746 if (platform.renderer == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
1747 {
1748 if (platform.majorVersion == 9 && platform.minorVersion == 3)
1749 {
1750 EXPECT_EQ(0u, program);
1751 return;
1752 }
1753 }
1754
1755 // Otherwise, compilation should succeed
1756 EXPECT_NE(0u, program);
1757 }
1758
1759 // Test that we can release the shader compiler and still compile things properly.
TEST_P(GLSLTest,ReleaseCompilerThenCompile)1760 TEST_P(GLSLTest, ReleaseCompilerThenCompile)
1761 {
1762 // Draw with the first program.
1763 ANGLE_GL_PROGRAM(program1, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
1764 drawQuad(program1, essl1_shaders::PositionAttrib(), 0.5f);
1765 ASSERT_GL_NO_ERROR();
1766 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1767
1768 // Clear and release shader compiler.
1769 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
1770 glClear(GL_COLOR_BUFFER_BIT);
1771 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1772 glReleaseShaderCompiler();
1773 ASSERT_GL_NO_ERROR();
1774
1775 // Draw with a second program.
1776 ANGLE_GL_PROGRAM(program2, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
1777 drawQuad(program2, essl1_shaders::PositionAttrib(), 0.5f);
1778 ASSERT_GL_NO_ERROR();
1779 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1780 }
1781
1782 // Verify that linking shaders declaring different shading language versions fails.
TEST_P(GLSLTest_ES3,VersionMismatch)1783 TEST_P(GLSLTest_ES3, VersionMismatch)
1784 {
1785 GLuint program = CompileProgram(essl3_shaders::vs::Simple(), essl1_shaders::fs::Red());
1786 EXPECT_EQ(0u, program);
1787
1788 program = CompileProgram(essl1_shaders::vs::Simple(), essl3_shaders::fs::Red());
1789 EXPECT_EQ(0u, program);
1790 }
1791
1792 // Verify that declaring varying as invariant only in vertex shader fails in ESSL 1.00.
TEST_P(GLSLTest,InvariantVaryingOut)1793 TEST_P(GLSLTest, InvariantVaryingOut)
1794 {
1795 constexpr char kFS[] =
1796 "precision mediump float;\n"
1797 "varying float v_varying;\n"
1798 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1799
1800 constexpr char kVS[] =
1801 "attribute vec4 a_position;\n"
1802 "invariant varying float v_varying;\n"
1803 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1804
1805 GLuint program = CompileProgram(kVS, kFS);
1806 EXPECT_EQ(0u, program);
1807 }
1808
1809 // Verify that declaring varying as invariant only in vertex shader succeeds in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantVaryingOut)1810 TEST_P(GLSLTest_ES3, InvariantVaryingOut)
1811 {
1812 // TODO: ESSL 3.00 -> GLSL 1.20 translation should add "invariant" in fragment shader
1813 // for varyings which are invariant in vertex shader (http://anglebug.com/1293)
1814 ANGLE_SKIP_TEST_IF(IsDesktopOpenGL());
1815
1816 constexpr char kFS[] =
1817 "#version 300 es\n"
1818 "precision mediump float;\n"
1819 "in float v_varying;\n"
1820 "out vec4 my_FragColor;\n"
1821 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1822
1823 constexpr char kVS[] =
1824 "#version 300 es\n"
1825 "in vec4 a_position;\n"
1826 "invariant out float v_varying;\n"
1827 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1828
1829 GLuint program = CompileProgram(kVS, kFS);
1830 EXPECT_NE(0u, program);
1831 }
1832
1833 // Verify that declaring varying as invariant only in fragment shader fails in ESSL 1.00.
TEST_P(GLSLTest,InvariantVaryingIn)1834 TEST_P(GLSLTest, InvariantVaryingIn)
1835 {
1836 constexpr char kFS[] =
1837 "precision mediump float;\n"
1838 "invariant varying float v_varying;\n"
1839 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1840
1841 constexpr char kVS[] =
1842 "attribute vec4 a_position;\n"
1843 "varying float v_varying;\n"
1844 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1845
1846 GLuint program = CompileProgram(kVS, kFS);
1847 EXPECT_EQ(0u, program);
1848 }
1849
1850 // Verify that declaring varying as invariant only in fragment shader fails in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantVaryingIn)1851 TEST_P(GLSLTest_ES3, InvariantVaryingIn)
1852 {
1853 constexpr char kFS[] =
1854 "#version 300 es\n"
1855 "precision mediump float;\n"
1856 "invariant in float v_varying;\n"
1857 "out vec4 my_FragColor;\n"
1858 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1859
1860 constexpr char kVS[] =
1861 "#version 300 es\n"
1862 "in vec4 a_position;\n"
1863 "out float v_varying;\n"
1864 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1865
1866 GLuint program = CompileProgram(kVS, kFS);
1867 EXPECT_EQ(0u, program);
1868 }
1869
1870 // Verify that declaring varying as invariant in both shaders succeeds in ESSL 1.00.
TEST_P(GLSLTest,InvariantVaryingBoth)1871 TEST_P(GLSLTest, InvariantVaryingBoth)
1872 {
1873 constexpr char kFS[] =
1874 "precision mediump float;\n"
1875 "invariant varying float v_varying;\n"
1876 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1877
1878 constexpr char kVS[] =
1879 "attribute vec4 a_position;\n"
1880 "invariant varying float v_varying;\n"
1881 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1882
1883 GLuint program = CompileProgram(kVS, kFS);
1884 EXPECT_NE(0u, program);
1885 }
1886
1887 // Verify that declaring varying as invariant in both shaders fails in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantVaryingBoth)1888 TEST_P(GLSLTest_ES3, InvariantVaryingBoth)
1889 {
1890 constexpr char kFS[] =
1891 "#version 300 es\n"
1892 "precision mediump float;\n"
1893 "invariant in float v_varying;\n"
1894 "out vec4 my_FragColor;\n"
1895 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1896
1897 constexpr char kVS[] =
1898 "#version 300 es\n"
1899 "in vec4 a_position;\n"
1900 "invariant out float v_varying;\n"
1901 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1902
1903 GLuint program = CompileProgram(kVS, kFS);
1904 EXPECT_EQ(0u, program);
1905 }
1906
1907 // Verify that declaring gl_Position as invariant succeeds in ESSL 1.00.
TEST_P(GLSLTest,InvariantGLPosition)1908 TEST_P(GLSLTest, InvariantGLPosition)
1909 {
1910 constexpr char kFS[] =
1911 "precision mediump float;\n"
1912 "varying float v_varying;\n"
1913 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1914
1915 constexpr char kVS[] =
1916 "attribute vec4 a_position;\n"
1917 "invariant gl_Position;\n"
1918 "varying float v_varying;\n"
1919 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1920
1921 GLuint program = CompileProgram(kVS, kFS);
1922 EXPECT_NE(0u, program);
1923 }
1924
1925 // Verify that declaring gl_Position as invariant succeeds in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantGLPosition)1926 TEST_P(GLSLTest_ES3, InvariantGLPosition)
1927 {
1928 constexpr char kFS[] =
1929 "#version 300 es\n"
1930 "precision mediump float;\n"
1931 "in float v_varying;\n"
1932 "out vec4 my_FragColor;\n"
1933 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1934
1935 constexpr char kVS[] =
1936 "#version 300 es\n"
1937 "in vec4 a_position;\n"
1938 "invariant gl_Position;\n"
1939 "out float v_varying;\n"
1940 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1941
1942 GLuint program = CompileProgram(kVS, kFS);
1943 EXPECT_NE(0u, program);
1944 }
1945
1946 // Verify that using invariant(all) in both shaders fails in ESSL 1.00.
TEST_P(GLSLTest,InvariantAllBoth)1947 TEST_P(GLSLTest, InvariantAllBoth)
1948 {
1949 constexpr char kFS[] =
1950 "#pragma STDGL invariant(all)\n"
1951 "precision mediump float;\n"
1952 "varying float v_varying;\n"
1953 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1954
1955 constexpr char kVS[] =
1956 "#pragma STDGL invariant(all)\n"
1957 "attribute vec4 a_position;\n"
1958 "varying float v_varying;\n"
1959 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1960
1961 GLuint program = CompileProgram(kVS, kFS);
1962 EXPECT_EQ(0u, program);
1963 }
1964
1965 // Verify that using a struct as both invariant and non-invariant output works.
TEST_P(GLSLTest_ES31,StructBothInvariantAndNot)1966 TEST_P(GLSLTest_ES31, StructBothInvariantAndNot)
1967 {
1968 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
1969
1970 constexpr char kVS[] = R"(#version 310 es
1971 #extension GL_EXT_shader_io_blocks : require
1972
1973 struct S
1974 {
1975 vec4 s;
1976 };
1977
1978 out Output
1979 {
1980 vec4 x;
1981 invariant S s;
1982 };
1983
1984 out S s2;
1985
1986 void main(){
1987 x = vec4(0);
1988 s.s = vec4(1);
1989 s2.s = vec4(2);
1990 S s3 = s;
1991 s.s = s3.s;
1992 })";
1993
1994 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
1995 EXPECT_NE(0u, shader);
1996 glDeleteShader(shader);
1997 }
1998
1999 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnFloat)2000 TEST_P(GLSLTest, MissingReturnFloat)
2001 {
2002 constexpr char kVS[] =
2003 "varying float v_varying;\n"
2004 "float f() { if (v_varying > 0.0) return 1.0; }\n"
2005 "void main() { gl_Position = vec4(f(), 0, 0, 1); }\n";
2006
2007 GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
2008 EXPECT_NE(0u, program);
2009 }
2010
2011 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnVec2)2012 TEST_P(GLSLTest, MissingReturnVec2)
2013 {
2014 constexpr char kVS[] =
2015 "varying float v_varying;\n"
2016 "vec2 f() { if (v_varying > 0.0) return vec2(1.0, 1.0); }\n"
2017 "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
2018
2019 GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
2020 EXPECT_NE(0u, program);
2021 }
2022
2023 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnVec3)2024 TEST_P(GLSLTest, MissingReturnVec3)
2025 {
2026 constexpr char kVS[] =
2027 "varying float v_varying;\n"
2028 "vec3 f() { if (v_varying > 0.0) return vec3(1.0, 1.0, 1.0); }\n"
2029 "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
2030
2031 GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
2032 EXPECT_NE(0u, program);
2033 }
2034
2035 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnVec4)2036 TEST_P(GLSLTest, MissingReturnVec4)
2037 {
2038 constexpr char kVS[] =
2039 "varying float v_varying;\n"
2040 "vec4 f() { if (v_varying > 0.0) return vec4(1.0, 1.0, 1.0, 1.0); }\n"
2041 "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
2042
2043 GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
2044 EXPECT_NE(0u, program);
2045 }
2046
2047 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnIVec4)2048 TEST_P(GLSLTest, MissingReturnIVec4)
2049 {
2050 constexpr char kVS[] =
2051 "varying float v_varying;\n"
2052 "ivec4 f() { if (v_varying > 0.0) return ivec4(1, 1, 1, 1); }\n"
2053 "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
2054
2055 GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
2056 EXPECT_NE(0u, program);
2057 }
2058
2059 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnMat4)2060 TEST_P(GLSLTest, MissingReturnMat4)
2061 {
2062 constexpr char kVS[] =
2063 "varying float v_varying;\n"
2064 "mat4 f() { if (v_varying > 0.0) return mat4(1.0); }\n"
2065 "void main() { gl_Position = vec4(f()[0][0], 0, 0, 1); }\n";
2066
2067 GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
2068 EXPECT_NE(0u, program);
2069 }
2070
2071 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnStruct)2072 TEST_P(GLSLTest, MissingReturnStruct)
2073 {
2074 constexpr char kVS[] =
2075 "varying float v_varying;\n"
2076 "struct s { float a; int b; vec2 c; };\n"
2077 "s f() { if (v_varying > 0.0) return s(1.0, 1, vec2(1.0, 1.0)); }\n"
2078 "void main() { gl_Position = vec4(f().a, 0, 0, 1); }\n";
2079
2080 GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
2081 EXPECT_NE(0u, program);
2082 }
2083
2084 // Verify that functions without return statements still compile
TEST_P(GLSLTest_ES3,MissingReturnArray)2085 TEST_P(GLSLTest_ES3, MissingReturnArray)
2086 {
2087 constexpr char kVS[] =
2088 "#version 300 es\n"
2089 "in float v_varying;\n"
2090 "vec2[2] f() { if (v_varying > 0.0) { return vec2[2](vec2(1.0, 1.0), vec2(1.0, 1.0)); } }\n"
2091 "void main() { gl_Position = vec4(f()[0].x, 0, 0, 1); }\n";
2092
2093 GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
2094 EXPECT_NE(0u, program);
2095 }
2096
2097 // Verify that functions without return statements still compile
TEST_P(GLSLTest_ES3,MissingReturnArrayOfStructs)2098 TEST_P(GLSLTest_ES3, MissingReturnArrayOfStructs)
2099 {
2100 constexpr char kVS[] =
2101 "#version 300 es\n"
2102 "in float v_varying;\n"
2103 "struct s { float a; int b; vec2 c; };\n"
2104 "s[2] f() { if (v_varying > 0.0) { return s[2](s(1.0, 1, vec2(1.0, 1.0)), s(1.0, 1, "
2105 "vec2(1.0, 1.0))); } }\n"
2106 "void main() { gl_Position = vec4(f()[0].a, 0, 0, 1); }\n";
2107
2108 GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
2109 EXPECT_NE(0u, program);
2110 }
2111
2112 // Verify that functions without return statements still compile
TEST_P(GLSLTest_ES3,MissingReturnStructOfArrays)2113 TEST_P(GLSLTest_ES3, MissingReturnStructOfArrays)
2114 {
2115 // TODO(crbug.com/998505): Test failing on Android FYI Release (NVIDIA Shield TV)
2116 ANGLE_SKIP_TEST_IF(IsNVIDIAShield());
2117
2118 constexpr char kVS[] =
2119 "#version 300 es\n"
2120 "in float v_varying;\n"
2121 "struct s { float a[2]; int b[2]; vec2 c[2]; };\n"
2122 "s f() { if (v_varying > 0.0) { return s(float[2](1.0, 1.0), int[2](1, 1),"
2123 "vec2[2](vec2(1.0, 1.0), vec2(1.0, 1.0))); } }\n"
2124 "void main() { gl_Position = vec4(f().a[0], 0, 0, 1); }\n";
2125
2126 GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
2127 EXPECT_NE(0u, program);
2128 }
2129
2130 // Verify that non-const index used on an array returned by a function compiles
TEST_P(GLSLTest_ES3,ReturnArrayOfStructsThenNonConstIndex)2131 TEST_P(GLSLTest_ES3, ReturnArrayOfStructsThenNonConstIndex)
2132 {
2133 constexpr char kVS[] = R"(#version 300 es
2134 in float v_varying;
2135 struct s { float a; int b; vec2 c; };
2136 s[2] f()
2137 {
2138 return s[2](s(v_varying, 1, vec2(1.0, 1.0)), s(v_varying / 2.0, 1, vec2(1.0, 1.0)));
2139 }
2140 void main()
2141 {
2142 gl_Position = vec4(f()[uint(v_varying)].a, 0, 0, 1);
2143 })";
2144
2145 GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
2146 EXPECT_NE(0u, program);
2147 }
2148
2149 // Verify that using invariant(all) in both shaders fails in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantAllBoth)2150 TEST_P(GLSLTest_ES3, InvariantAllBoth)
2151 {
2152 constexpr char kFS[] =
2153 "#version 300 es\n"
2154 "#pragma STDGL invariant(all)\n"
2155 "precision mediump float;\n"
2156 "in float v_varying;\n"
2157 "out vec4 my_FragColor;\n"
2158 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
2159
2160 constexpr char kVS[] =
2161 "#version 300 es\n"
2162 "#pragma STDGL invariant(all)\n"
2163 "in vec4 a_position;\n"
2164 "out float v_varying;\n"
2165 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
2166
2167 GLuint program = CompileProgram(kVS, kFS);
2168 EXPECT_EQ(0u, program);
2169 }
2170
2171 // Verify that using invariant(all) only in fragment shader succeeds in ESSL 1.00.
TEST_P(GLSLTest,InvariantAllIn)2172 TEST_P(GLSLTest, InvariantAllIn)
2173 {
2174 constexpr char kFS[] =
2175 "#pragma STDGL invariant(all)\n"
2176 "precision mediump float;\n"
2177 "varying float v_varying;\n"
2178 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
2179
2180 constexpr char kVS[] =
2181 "attribute vec4 a_position;\n"
2182 "varying float v_varying;\n"
2183 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
2184
2185 GLuint program = CompileProgram(kVS, kFS);
2186 EXPECT_NE(0u, program);
2187 }
2188
2189 // Verify that using invariant(all) only in fragment shader fails in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantAllIn)2190 TEST_P(GLSLTest_ES3, InvariantAllIn)
2191 {
2192 constexpr char kFS[] =
2193 "#version 300 es\n"
2194 "#pragma STDGL invariant(all)\n"
2195 "precision mediump float;\n"
2196 "in float v_varying;\n"
2197 "out vec4 my_FragColor;\n"
2198 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
2199
2200 constexpr char kVS[] =
2201 "#version 300 es\n"
2202 "in vec4 a_position;\n"
2203 "out float v_varying;\n"
2204 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
2205
2206 GLuint program = CompileProgram(kVS, kFS);
2207 EXPECT_EQ(0u, program);
2208 }
2209
2210 // Verify that using invariant(all) only in vertex shader fails in ESSL 1.00.
TEST_P(GLSLTest,InvariantAllOut)2211 TEST_P(GLSLTest, InvariantAllOut)
2212 {
2213 constexpr char kFS[] =
2214 "precision mediump float;\n"
2215 "varying float v_varying;\n"
2216 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
2217
2218 constexpr char kVS[] =
2219 "#pragma STDGL invariant(all)\n"
2220 "attribute vec4 a_position;\n"
2221 "varying float v_varying;\n"
2222 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
2223
2224 GLuint program = CompileProgram(kVS, kFS);
2225 EXPECT_EQ(0u, program);
2226 }
2227
2228 // Verify that using invariant(all) only in vertex shader succeeds in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantAllOut)2229 TEST_P(GLSLTest_ES3, InvariantAllOut)
2230 {
2231 // TODO: ESSL 3.00 -> GLSL 1.20 translation should add "invariant" in fragment shader
2232 // for varyings which are invariant in vertex shader,
2233 // because of invariant(all) being used in vertex shader (http://anglebug.com/1293)
2234 ANGLE_SKIP_TEST_IF(IsDesktopOpenGL());
2235
2236 constexpr char kFS[] =
2237 "#version 300 es\n"
2238 "precision mediump float;\n"
2239 "in float v_varying;\n"
2240 "out vec4 my_FragColor;\n"
2241 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
2242
2243 constexpr char kVS[] =
2244 "#version 300 es\n"
2245 "#pragma STDGL invariant(all)\n"
2246 "in vec4 a_position;\n"
2247 "out float v_varying;\n"
2248 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
2249
2250 GLuint program = CompileProgram(kVS, kFS);
2251 EXPECT_NE(0u, program);
2252 }
2253
TEST_P(GLSLTest,MaxVaryingVec4)2254 TEST_P(GLSLTest, MaxVaryingVec4)
2255 {
2256 // TODO(geofflang): Find out why this doesn't compile on Apple AMD OpenGL drivers
2257 // (http://anglebug.com/1291)
2258 ANGLE_SKIP_TEST_IF(IsMac() && IsAMD() && IsOpenGL());
2259
2260 GLint maxVaryings = 0;
2261 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2262
2263 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, false, false, false, true);
2264 }
2265
2266 // Verify we can pack registers with one builtin varying.
TEST_P(GLSLTest,MaxVaryingVec4_OneBuiltin)2267 TEST_P(GLSLTest, MaxVaryingVec4_OneBuiltin)
2268 {
2269 GLint maxVaryings = 0;
2270 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2271
2272 // Generate shader code that uses gl_FragCoord.
2273 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 1, 0, true, false, false, true);
2274 }
2275
2276 // Verify we can pack registers with two builtin varyings.
TEST_P(GLSLTest,MaxVaryingVec4_TwoBuiltins)2277 TEST_P(GLSLTest, MaxVaryingVec4_TwoBuiltins)
2278 {
2279 GLint maxVaryings = 0;
2280 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2281
2282 // Generate shader code that uses gl_FragCoord and gl_PointCoord.
2283 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 2, 0, true, true, false, true);
2284 }
2285
2286 // Verify we can pack registers with three builtin varyings.
TEST_P(GLSLTest,MaxVaryingVec4_ThreeBuiltins)2287 TEST_P(GLSLTest, MaxVaryingVec4_ThreeBuiltins)
2288 {
2289 GLint maxVaryings = 0;
2290 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2291
2292 // Generate shader code that uses gl_FragCoord, gl_PointCoord and gl_PointSize.
2293 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 3, 0, true, true, true, true);
2294 }
2295
2296 // This covers a problematic case in D3D9 - we are limited by the number of available semantics,
2297 // rather than total register use.
TEST_P(GLSLTest,MaxVaryingsSpecialCases)2298 TEST_P(GLSLTest, MaxVaryingsSpecialCases)
2299 {
2300 ANGLE_SKIP_TEST_IF(!IsD3D9());
2301
2302 GLint maxVaryings = 0;
2303 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2304
2305 VaryingTestBase(maxVaryings, 0, 0, 0, 0, 0, 0, 0, true, false, false, false);
2306 VaryingTestBase(maxVaryings - 1, 0, 0, 0, 0, 0, 0, 0, true, true, false, false);
2307 VaryingTestBase(maxVaryings - 2, 0, 0, 0, 0, 0, 0, 0, true, true, false, true);
2308
2309 // Special case for gl_PointSize: we get it for free on D3D9.
2310 VaryingTestBase(maxVaryings - 2, 0, 0, 0, 0, 0, 0, 0, true, true, true, true);
2311 }
2312
2313 // This covers a problematic case in D3D9 - we are limited by the number of available semantics,
2314 // rather than total register use.
TEST_P(GLSLTest,MaxMinusTwoVaryingVec2PlusOneSpecialVariable)2315 TEST_P(GLSLTest, MaxMinusTwoVaryingVec2PlusOneSpecialVariable)
2316 {
2317 GLint maxVaryings = 0;
2318 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2319
2320 // Generate shader code that uses gl_FragCoord.
2321 VaryingTestBase(0, 0, maxVaryings, 0, 0, 0, 0, 0, true, false, false, !IsD3D9());
2322 }
2323
TEST_P(GLSLTest,MaxVaryingVec3)2324 TEST_P(GLSLTest, MaxVaryingVec3)
2325 {
2326 GLint maxVaryings = 0;
2327 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2328
2329 VaryingTestBase(0, 0, 0, 0, maxVaryings, 0, 0, 0, false, false, false, true);
2330 }
2331
TEST_P(GLSLTest,MaxVaryingVec3Array)2332 TEST_P(GLSLTest, MaxVaryingVec3Array)
2333 {
2334 GLint maxVaryings = 0;
2335 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2336
2337 VaryingTestBase(0, 0, 0, 0, 0, maxVaryings / 2, 0, 0, false, false, false, true);
2338 }
2339
2340 // Only fails on D3D9 because of packing limitations.
TEST_P(GLSLTest,MaxVaryingVec3AndOneFloat)2341 TEST_P(GLSLTest, MaxVaryingVec3AndOneFloat)
2342 {
2343 GLint maxVaryings = 0;
2344 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2345
2346 VaryingTestBase(1, 0, 0, 0, maxVaryings, 0, 0, 0, false, false, false, !IsD3D9());
2347 }
2348
2349 // Only fails on D3D9 because of packing limitations.
TEST_P(GLSLTest,MaxVaryingVec3ArrayAndOneFloatArray)2350 TEST_P(GLSLTest, MaxVaryingVec3ArrayAndOneFloatArray)
2351 {
2352 GLint maxVaryings = 0;
2353 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2354
2355 VaryingTestBase(0, 1, 0, 0, 0, maxVaryings / 2, 0, 0, false, false, false, !IsD3D9());
2356 }
2357
2358 // Only fails on D3D9 because of packing limitations.
TEST_P(GLSLTest,TwiceMaxVaryingVec2)2359 TEST_P(GLSLTest, TwiceMaxVaryingVec2)
2360 {
2361 // TODO(geofflang): Figure out why this fails on NVIDIA's GLES driver
2362 // (http://anglebug.com/3849)
2363 ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGLES());
2364
2365 // TODO(geofflang): Find out why this doesn't compile on Apple AMD OpenGL drivers
2366 // (http://anglebug.com/1291)
2367 ANGLE_SKIP_TEST_IF(IsMac() && IsAMD() && IsOpenGL());
2368
2369 GLint maxVaryings = 0;
2370 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2371
2372 VaryingTestBase(0, 0, 2 * maxVaryings, 0, 0, 0, 0, 0, false, false, false, !IsD3D9());
2373 }
2374
2375 // Disabled because of a failure in D3D9
TEST_P(GLSLTest,MaxVaryingVec2Arrays)2376 TEST_P(GLSLTest, MaxVaryingVec2Arrays)
2377 {
2378 ANGLE_SKIP_TEST_IF(IsD3D9());
2379
2380 // TODO(geofflang): Figure out why this fails on NVIDIA's GLES driver
2381 ANGLE_SKIP_TEST_IF(IsOpenGLES());
2382
2383 // TODO(geofflang): Find out why this doesn't compile on Apple AMD OpenGL drivers
2384 // (http://anglebug.com/1291)
2385 ANGLE_SKIP_TEST_IF(IsMac() && IsAMD() && IsOpenGL());
2386
2387 GLint maxVaryings = 0;
2388 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2389
2390 // Special case: because arrays of mat2 are packed as small grids of two rows by two columns,
2391 // we should be aware that when we're packing into an odd number of varying registers the
2392 // last row will be empty and can not fit the final vec2 arrary.
2393 GLint maxVec2Arrays = (maxVaryings >> 1) << 1;
2394
2395 VaryingTestBase(0, 0, 0, maxVec2Arrays, 0, 0, 0, 0, false, false, false, true);
2396 }
2397
2398 // Verify max varying with feedback and gl_line enabled
TEST_P(GLSLTest_ES3,MaxVaryingWithFeedbackAndGLline)2399 TEST_P(GLSLTest_ES3, MaxVaryingWithFeedbackAndGLline)
2400 {
2401 // (http://anglebug.com/4439)
2402 ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsVulkan());
2403
2404 // http://anglebug.com/4446
2405 ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
2406
2407 GLint maxVaryings = 0;
2408 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2409
2410 std::stringstream vertexShaderSource;
2411 std::stringstream fragmentShaderSource;
2412
2413 // substract 1 here for gl_PointSize
2414 const GLint vec4Count = maxVaryings - 1;
2415 unsigned int varyingCount = 0;
2416 std::string varyingDeclaration;
2417 for (GLint i = 0; i < vec4Count; i++)
2418 {
2419 varyingDeclaration += GenerateVectorVaryingDeclaration(4, 1, varyingCount);
2420 varyingCount += 1;
2421 }
2422 // Generate the vertex shader
2423 vertexShaderSource.clear();
2424 vertexShaderSource << varyingDeclaration;
2425 vertexShaderSource << "\nattribute vec4 a_position;\n";
2426 vertexShaderSource << "\nvoid main()\n{\n";
2427 unsigned int currentVSVarying = 0;
2428 for (GLint i = 0; i < vec4Count; i++)
2429 {
2430 vertexShaderSource << GenerateVectorVaryingSettingCode(4, 1, currentVSVarying);
2431 currentVSVarying += 1;
2432 }
2433 vertexShaderSource << "\tgl_Position = vec4(a_position.rgb, 1);\n";
2434 vertexShaderSource << "\tgl_PointSize = 1.0;\n";
2435 vertexShaderSource << "}\n";
2436
2437 // Generate the fragment shader
2438 fragmentShaderSource.clear();
2439 fragmentShaderSource << "precision highp float;\n";
2440 fragmentShaderSource << varyingDeclaration;
2441 fragmentShaderSource << "\nvoid main() \n{ \n\tvec4 retColor = vec4(0,0,0,0);\n";
2442 unsigned int currentFSVarying = 0;
2443 // Make use of the vec4 varyings
2444 fragmentShaderSource << "\tretColor += ";
2445 for (GLint i = 0; i < vec4Count; i++)
2446 {
2447 fragmentShaderSource << GenerateVectorVaryingUseCode(1, currentFSVarying);
2448 currentFSVarying += 1;
2449 }
2450 fragmentShaderSource << "vec4(0.0, 0.0, 0.0, 0.0);\n";
2451 constexpr GLuint testValue = 234;
2452 fragmentShaderSource << "\tgl_FragColor = (retColor/vec4(" << std::to_string(currentFSVarying)
2453 << ")) /255.0*" << std::to_string(testValue) << ".0;\n";
2454 fragmentShaderSource << "}\n";
2455
2456 std::vector<std::string> tfVaryings = {"gl_Position", "gl_PointSize"};
2457 ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(program1, vertexShaderSource.str().c_str(),
2458 fragmentShaderSource.str().c_str(), tfVaryings,
2459 GL_INTERLEAVED_ATTRIBS);
2460
2461 GLBuffer xfbBuffer;
2462 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfbBuffer);
2463 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 6 * (sizeof(float[4]) + sizeof(float)), nullptr,
2464 GL_STATIC_DRAW);
2465
2466 GLTransformFeedback xfb;
2467 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, xfb);
2468 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, xfbBuffer);
2469
2470 glUseProgram(program1);
2471
2472 const GLint positionLocation = glGetAttribLocation(program1, essl1_shaders::PositionAttrib());
2473 GLBuffer vertexBuffer;
2474 // need to shift half pixel to make sure the line covers the center of the pixel
2475 const Vector3 vertices[2] = {
2476 {-1.0f, -1.0f + 0.5f / static_cast<float>(getWindowHeight()), 0.0f},
2477 {1.0f, -1.0f + 0.5f / static_cast<float>(getWindowHeight()), 0.0f}};
2478 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
2479 glBufferData(GL_ARRAY_BUFFER, sizeof(*vertices) * 2, vertices, GL_STATIC_DRAW);
2480 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
2481 glEnableVertexAttribArray(positionLocation);
2482
2483 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
2484 glClear(GL_COLOR_BUFFER_BIT);
2485
2486 glBeginTransformFeedback(GL_LINES);
2487 glDrawArrays(GL_LINES, 0, 2);
2488 glEndTransformFeedback();
2489
2490 ASSERT_GL_NO_ERROR();
2491
2492 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(testValue, testValue, testValue, testValue));
2493 }
2494
2495 // Verify shader source with a fixed length that is less than the null-terminated length will
2496 // compile.
TEST_P(GLSLTest,FixedShaderLength)2497 TEST_P(GLSLTest, FixedShaderLength)
2498 {
2499 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
2500
2501 const std::string appendGarbage = "abcdefghijklmnopqrstuvwxyz";
2502 const std::string source = "void main() { gl_FragColor = vec4(0, 0, 0, 0); }" + appendGarbage;
2503 const char *sourceArray[1] = {source.c_str()};
2504 GLint lengths[1] = {static_cast<GLint>(source.length() - appendGarbage.length())};
2505 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
2506 glCompileShader(shader);
2507
2508 GLint compileResult;
2509 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
2510 EXPECT_NE(compileResult, 0);
2511 }
2512
2513 // Verify that a negative shader source length is treated as a null-terminated length.
TEST_P(GLSLTest,NegativeShaderLength)2514 TEST_P(GLSLTest, NegativeShaderLength)
2515 {
2516 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
2517
2518 const char *sourceArray[1] = {essl1_shaders::fs::Red()};
2519 GLint lengths[1] = {-10};
2520 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
2521 glCompileShader(shader);
2522
2523 GLint compileResult;
2524 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
2525 EXPECT_NE(compileResult, 0);
2526 }
2527
2528 // Check that having an invalid char after the "." doesn't cause an assert.
TEST_P(GLSLTest,InvalidFieldFirstChar)2529 TEST_P(GLSLTest, InvalidFieldFirstChar)
2530 {
2531 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
2532 const char *source = "void main() {vec4 x; x.}";
2533 glShaderSource(shader, 1, &source, 0);
2534 glCompileShader(shader);
2535
2536 GLint compileResult;
2537 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
2538 EXPECT_EQ(0, compileResult);
2539 }
2540
2541 // Verify that a length array with mixed positive and negative values compiles.
TEST_P(GLSLTest,MixedShaderLengths)2542 TEST_P(GLSLTest, MixedShaderLengths)
2543 {
2544 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
2545
2546 const char *sourceArray[] = {
2547 "void main()",
2548 "{",
2549 " gl_FragColor = vec4(0, 0, 0, 0);",
2550 "}",
2551 };
2552 GLint lengths[] = {
2553 -10,
2554 1,
2555 static_cast<GLint>(strlen(sourceArray[2])),
2556 -1,
2557 };
2558 ASSERT_EQ(ArraySize(sourceArray), ArraySize(lengths));
2559
2560 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
2561 glCompileShader(shader);
2562
2563 GLint compileResult;
2564 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
2565 EXPECT_NE(compileResult, 0);
2566 }
2567
2568 // Verify that zero-length shader source does not affect shader compilation.
TEST_P(GLSLTest,ZeroShaderLength)2569 TEST_P(GLSLTest, ZeroShaderLength)
2570 {
2571 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
2572
2573 const char *sourceArray[] = {
2574 "abcdefg", "34534", "void main() { gl_FragColor = vec4(0, 0, 0, 0); }", "", "abcdefghijklm",
2575 };
2576 GLint lengths[] = {
2577 0, 0, -1, 0, 0,
2578 };
2579 ASSERT_EQ(ArraySize(sourceArray), ArraySize(lengths));
2580
2581 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
2582 glCompileShader(shader);
2583
2584 GLint compileResult;
2585 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
2586 EXPECT_NE(compileResult, 0);
2587 }
2588
2589 // Tests that bad index expressions don't crash ANGLE's translator.
2590 // https://code.google.com/p/angleproject/issues/detail?id=857
TEST_P(GLSLTest,BadIndexBug)2591 TEST_P(GLSLTest, BadIndexBug)
2592 {
2593 constexpr char kFSSourceVec[] =
2594 "precision mediump float;\n"
2595 "uniform vec4 uniformVec;\n"
2596 "void main()\n"
2597 "{\n"
2598 " gl_FragColor = vec4(uniformVec[int()]);\n"
2599 "}";
2600
2601 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFSSourceVec);
2602 EXPECT_EQ(0u, shader);
2603
2604 if (shader != 0)
2605 {
2606 glDeleteShader(shader);
2607 }
2608
2609 constexpr char kFSSourceMat[] =
2610 "precision mediump float;\n"
2611 "uniform mat4 uniformMat;\n"
2612 "void main()\n"
2613 "{\n"
2614 " gl_FragColor = vec4(uniformMat[int()]);\n"
2615 "}";
2616
2617 shader = CompileShader(GL_FRAGMENT_SHADER, kFSSourceMat);
2618 EXPECT_EQ(0u, shader);
2619
2620 if (shader != 0)
2621 {
2622 glDeleteShader(shader);
2623 }
2624
2625 constexpr char kFSSourceArray[] =
2626 "precision mediump float;\n"
2627 "uniform vec4 uniformArray;\n"
2628 "void main()\n"
2629 "{\n"
2630 " gl_FragColor = vec4(uniformArray[int()]);\n"
2631 "}";
2632
2633 shader = CompileShader(GL_FRAGMENT_SHADER, kFSSourceArray);
2634 EXPECT_EQ(0u, shader);
2635
2636 if (shader != 0)
2637 {
2638 glDeleteShader(shader);
2639 }
2640 }
2641
2642 // Test that structs defined in uniforms are translated correctly.
TEST_P(GLSLTest,StructSpecifiersUniforms)2643 TEST_P(GLSLTest, StructSpecifiersUniforms)
2644 {
2645 constexpr char kFS[] = R"(precision mediump float;
2646
2647 uniform struct S { float field; } s;
2648
2649 void main()
2650 {
2651 gl_FragColor = vec4(1, 0, 0, 1);
2652 gl_FragColor.a += s.field;
2653 })";
2654
2655 GLuint program = CompileProgram(essl1_shaders::vs::Simple(), kFS);
2656 EXPECT_NE(0u, program);
2657 }
2658
2659 // Test that structs declaration followed directly by an initialization is translated correctly.
TEST_P(GLSLTest,StructWithInitializer)2660 TEST_P(GLSLTest, StructWithInitializer)
2661 {
2662 constexpr char kFS[] = R"(precision mediump float;
2663
2664 struct S { float a; } s = S(1.0);
2665
2666 void main()
2667 {
2668 gl_FragColor = vec4(0, 0, 0, 1);
2669 gl_FragColor.r += s.a;
2670 })";
2671
2672 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
2673 glUseProgram(program);
2674
2675 // Test drawing, should be red.
2676 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2677
2678 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2679 EXPECT_GL_NO_ERROR();
2680 }
2681
2682 // Test that structs without initializer, followed by a uniform usage works as expected.
TEST_P(GLSLTest,UniformStructWithoutInitializer)2683 TEST_P(GLSLTest, UniformStructWithoutInitializer)
2684 {
2685 constexpr char kFS[] = R"(precision mediump float;
2686
2687 struct S { float a; };
2688 uniform S u_s;
2689
2690 void main()
2691 {
2692 gl_FragColor = vec4(u_s.a);
2693 })";
2694
2695 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
2696 glUseProgram(program);
2697
2698 // Test drawing, should be red.
2699 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2700
2701 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
2702 EXPECT_GL_NO_ERROR();
2703 }
2704
2705 // Test that structs declaration followed directly by an initialization in a uniform.
TEST_P(GLSLTest,StructWithUniformInitializer)2706 TEST_P(GLSLTest, StructWithUniformInitializer)
2707 {
2708 constexpr char kFS[] = R"(precision mediump float;
2709
2710 struct S { float a; } s = S(1.0);
2711 uniform S us;
2712
2713 void main()
2714 {
2715 gl_FragColor = vec4(0, 0, 0, 1);
2716 gl_FragColor.r += s.a;
2717 gl_FragColor.g += us.a;
2718 })";
2719
2720 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
2721 glUseProgram(program);
2722
2723 // Test drawing, should be red.
2724 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2725
2726 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2727 EXPECT_GL_NO_ERROR();
2728 }
2729
2730 // Test that gl_DepthRange is not stored as a uniform location. Since uniforms
2731 // beginning with "gl_" are filtered out by our validation logic, we must
2732 // bypass the validation to test the behaviour of the implementation.
2733 // (note this test is still Impl-independent)
TEST_P(GLSLTestNoValidation,DepthRangeUniforms)2734 TEST_P(GLSLTestNoValidation, DepthRangeUniforms)
2735 {
2736 constexpr char kFS[] = R"(precision mediump float;
2737
2738 void main()
2739 {
2740 gl_FragColor = vec4(gl_DepthRange.near, gl_DepthRange.far, gl_DepthRange.diff, 1);
2741 })";
2742
2743 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
2744
2745 // We need to bypass validation for this call.
2746 GLint nearIndex = glGetUniformLocation(program, "gl_DepthRange.near");
2747 EXPECT_EQ(-1, nearIndex);
2748
2749 // Test drawing does not throw an exception.
2750 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2751
2752 EXPECT_GL_NO_ERROR();
2753 }
2754
GenerateSmallPowShader(double base,double exponent)2755 std::string GenerateSmallPowShader(double base, double exponent)
2756 {
2757 std::stringstream stream;
2758
2759 stream.precision(8);
2760
2761 double result = pow(base, exponent);
2762
2763 stream << "precision highp float;\n"
2764 << "float fun(float arg)\n"
2765 << "{\n"
2766 << " return pow(arg, " << std::fixed << exponent << ");\n"
2767 << "}\n"
2768 << "\n"
2769 << "void main()\n"
2770 << "{\n"
2771 << " const float a = " << std::scientific << base << ";\n"
2772 << " float b = fun(a);\n"
2773 << " if (abs(" << result << " - b) < " << std::abs(result * 0.001) << ")\n"
2774 << " {\n"
2775 << " gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
2776 << " }\n"
2777 << " else\n"
2778 << " {\n"
2779 << " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
2780 << " }\n"
2781 << "}\n";
2782
2783 return stream.str();
2784 }
2785
2786 // Covers the WebGL test 'glsl/bugs/pow-of-small-constant-in-user-defined-function'
2787 // See http://anglebug.com/851
TEST_P(GLSLTest,PowOfSmallConstant)2788 TEST_P(GLSLTest, PowOfSmallConstant)
2789 {
2790 // Test with problematic exponents that are close to an integer.
2791 std::vector<double> testExponents;
2792 std::array<double, 5> epsilonMultipliers = {-100.0, -1.0, 0.0, 1.0, 100.0};
2793 for (double epsilonMultiplier : epsilonMultipliers)
2794 {
2795 for (int i = -4; i <= 5; ++i)
2796 {
2797 if (i >= -1 && i <= 1)
2798 continue;
2799 const double epsilon = 1.0e-8;
2800 double bad = static_cast<double>(i) + epsilonMultiplier * epsilon;
2801 testExponents.push_back(bad);
2802 }
2803 }
2804
2805 // Also test with a few exponents that are not close to an integer.
2806 testExponents.push_back(3.6);
2807 testExponents.push_back(3.4);
2808
2809 for (double testExponent : testExponents)
2810 {
2811 const std::string &fragmentShaderSource = GenerateSmallPowShader(1.0e-6, testExponent);
2812
2813 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), fragmentShaderSource.c_str());
2814
2815 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2816
2817 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2818 EXPECT_GL_NO_ERROR();
2819 }
2820 }
2821
2822 // Test fragment shaders which contain non-constant loop indexers
TEST_P(GLSLTest,LoopIndexingValidation)2823 TEST_P(GLSLTest, LoopIndexingValidation)
2824 {
2825 constexpr char kFS[] = R"(precision mediump float;
2826
2827 uniform float loopMax;
2828
2829 void main()
2830 {
2831 gl_FragColor = vec4(1, 0, 0, 1);
2832 for (float l = 0.0; l < loopMax; l++)
2833 {
2834 if (loopMax > 3.0)
2835 {
2836 gl_FragColor.a += 0.1;
2837 }
2838 }
2839 })";
2840
2841 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
2842
2843 const char *sourceArray[1] = {kFS};
2844 glShaderSource(shader, 1, sourceArray, nullptr);
2845 glCompileShader(shader);
2846
2847 GLint compileResult;
2848 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
2849
2850 // If the test is configured to run limited to Feature Level 9_3, then it is
2851 // assumed that shader compilation will fail with an expected error message containing
2852 // "Loop index cannot be compared with non-constant expression"
2853 if (GetParam() == ES2_D3D9())
2854 {
2855 if (compileResult != 0)
2856 {
2857 FAIL() << "Shader compilation succeeded, expected failure";
2858 }
2859 else
2860 {
2861 GLint infoLogLength;
2862 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
2863
2864 std::string infoLog;
2865 infoLog.resize(infoLogLength);
2866 glGetShaderInfoLog(shader, static_cast<GLsizei>(infoLog.size()), nullptr, &infoLog[0]);
2867
2868 if (infoLog.find("Loop index cannot be compared with non-constant expression") ==
2869 std::string::npos)
2870 {
2871 FAIL() << "Shader compilation failed with unexpected error message";
2872 }
2873 }
2874 }
2875 else
2876 {
2877 EXPECT_NE(0, compileResult);
2878 }
2879
2880 if (shader != 0)
2881 {
2882 glDeleteShader(shader);
2883 }
2884 }
2885
2886 // Tests that the maximum uniforms count returned from querying GL_MAX_VERTEX_UNIFORM_VECTORS
2887 // can actually be used.
TEST_P(GLSLTest,VerifyMaxVertexUniformVectors)2888 TEST_P(GLSLTest, VerifyMaxVertexUniformVectors)
2889 {
2890 // crbug.com/680631
2891 ANGLE_SKIP_TEST_IF(IsOzone() && IsIntel());
2892
2893 int maxUniforms = 10000;
2894 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
2895 EXPECT_GL_NO_ERROR();
2896 std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS = " << maxUniforms << std::endl;
2897
2898 CompileGLSLWithUniformsAndSamplers(maxUniforms, 0, 0, 0, true);
2899 }
2900
2901 // Tests that the maximum uniforms count returned from querying GL_MAX_VERTEX_UNIFORM_VECTORS
2902 // can actually be used along with the maximum number of texture samplers.
TEST_P(GLSLTest,VerifyMaxVertexUniformVectorsWithSamplers)2903 TEST_P(GLSLTest, VerifyMaxVertexUniformVectorsWithSamplers)
2904 {
2905 ANGLE_SKIP_TEST_IF(IsOpenGL() || IsOpenGLES());
2906
2907 // Times out on D3D11 on test infra. http://anglebug.com/5076
2908 ANGLE_SKIP_TEST_IF(IsD3D11() && IsIntel());
2909
2910 int maxUniforms = 10000;
2911 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
2912 EXPECT_GL_NO_ERROR();
2913 std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS = " << maxUniforms << std::endl;
2914
2915 int maxTextureImageUnits = 0;
2916 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
2917
2918 CompileGLSLWithUniformsAndSamplers(maxUniforms, 0, maxTextureImageUnits, 0, true);
2919 }
2920
2921 // Tests that the maximum uniforms count + 1 from querying GL_MAX_VERTEX_UNIFORM_VECTORS
2922 // fails shader compilation.
TEST_P(GLSLTest,VerifyMaxVertexUniformVectorsExceeded)2923 TEST_P(GLSLTest, VerifyMaxVertexUniformVectorsExceeded)
2924 {
2925 int maxUniforms = 10000;
2926 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
2927 EXPECT_GL_NO_ERROR();
2928 std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS + 1 = " << maxUniforms + 1 << std::endl;
2929
2930 CompileGLSLWithUniformsAndSamplers(maxUniforms + 1, 0, 0, 0, false);
2931 }
2932
2933 // Tests that the maximum uniforms count returned from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
2934 // can actually be used.
TEST_P(GLSLTest,VerifyMaxFragmentUniformVectors)2935 TEST_P(GLSLTest, VerifyMaxFragmentUniformVectors)
2936 {
2937 // crbug.com/680631
2938 ANGLE_SKIP_TEST_IF(IsOzone() && IsIntel());
2939
2940 int maxUniforms = 10000;
2941 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
2942 EXPECT_GL_NO_ERROR();
2943 std::cout << "Validating GL_MAX_FRAGMENT_UNIFORM_VECTORS = " << maxUniforms << std::endl;
2944
2945 CompileGLSLWithUniformsAndSamplers(0, maxUniforms, 0, 0, true);
2946 }
2947
2948 // Tests that the maximum uniforms count returned from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
2949 // can actually be used along with the maximum number of texture samplers.
TEST_P(GLSLTest,VerifyMaxFragmentUniformVectorsWithSamplers)2950 TEST_P(GLSLTest, VerifyMaxFragmentUniformVectorsWithSamplers)
2951 {
2952 ANGLE_SKIP_TEST_IF(IsOpenGL() || IsOpenGLES());
2953
2954 int maxUniforms = 10000;
2955 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
2956 EXPECT_GL_NO_ERROR();
2957
2958 int maxTextureImageUnits = 0;
2959 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
2960
2961 CompileGLSLWithUniformsAndSamplers(0, maxUniforms, 0, maxTextureImageUnits, true);
2962 }
2963
2964 // Tests that the maximum uniforms count + 1 from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
2965 // fails shader compilation.
TEST_P(GLSLTest,VerifyMaxFragmentUniformVectorsExceeded)2966 TEST_P(GLSLTest, VerifyMaxFragmentUniformVectorsExceeded)
2967 {
2968 int maxUniforms = 10000;
2969 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
2970 EXPECT_GL_NO_ERROR();
2971 std::cout << "Validating GL_MAX_FRAGMENT_UNIFORM_VECTORS + 1 = " << maxUniforms + 1
2972 << std::endl;
2973
2974 CompileGLSLWithUniformsAndSamplers(0, maxUniforms + 1, 0, 0, false);
2975 }
2976
2977 // Test compiling shaders using the GL_EXT_shader_texture_lod extension
TEST_P(GLSLTest,TextureLOD)2978 TEST_P(GLSLTest, TextureLOD)
2979 {
2980 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_texture_lod"));
2981
2982 constexpr char kFS[] =
2983 "#extension GL_EXT_shader_texture_lod : require\n"
2984 "uniform sampler2D u_texture;\n"
2985 "void main() {\n"
2986 " gl_FragColor = texture2DGradEXT(u_texture, vec2(0.0, 0.0), vec2(0.0, 0.0), vec2(0.0, "
2987 "0.0));\n"
2988 "}\n";
2989
2990 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
2991 ASSERT_NE(0u, shader);
2992 glDeleteShader(shader);
2993 }
2994
2995 // HLSL generates extra lod0 variants of functions. There was a bug that incorrectly reworte
2996 // function calls to use them in vertex shaders. http://anglebug.com/3471
TEST_P(GLSLTest,TextureLODRewriteInVertexShader)2997 TEST_P(GLSLTest, TextureLODRewriteInVertexShader)
2998 {
2999 constexpr char kVS[] = R"(
3000 precision highp float;
3001 uniform int uni;
3002 uniform sampler2D texture;
3003
3004 vec4 A();
3005
3006 vec4 B() {
3007 vec4 a;
3008 for(int r=0; r<14; r++){
3009 if (r < uni) return vec4(0.0);
3010 a = A();
3011 }
3012 return a;
3013 }
3014
3015 vec4 A() {
3016 return texture2D(texture, vec2(0.0, 0.0));
3017 }
3018
3019 void main() {
3020 gl_Position = B();
3021 })";
3022
3023 constexpr char kFS[] = R"(
3024 void main() { gl_FragColor = vec4(gl_FragCoord.x / 640.0, gl_FragCoord.y / 480.0, 0, 1); }
3025 )";
3026
3027 ANGLE_GL_PROGRAM(program, kVS, kFS);
3028 }
3029
3030 // Test to verify the a shader can have a sampler unused in a vertex shader
3031 // but used in the fragment shader.
TEST_P(GLSLTest,VerifySamplerInBothVertexAndFragmentShaders)3032 TEST_P(GLSLTest, VerifySamplerInBothVertexAndFragmentShaders)
3033 {
3034 constexpr char kVS[] = R"(
3035 attribute vec2 position;
3036 varying mediump vec2 texCoord;
3037 uniform sampler2D tex;
3038 void main()
3039 {
3040 gl_Position = vec4(position, 0, 1);
3041 texCoord = position * 0.5 + vec2(0.5);
3042 })";
3043
3044 constexpr char kFS[] = R"(
3045 varying mediump vec2 texCoord;
3046 uniform sampler2D tex;
3047 void main()
3048 {
3049 gl_FragColor = texture2D(tex, texCoord);
3050 })";
3051
3052 ANGLE_GL_PROGRAM(program, kVS, kFS);
3053
3054 // Initialize basic red texture.
3055 const std::vector<GLColor> redColors(4, GLColor::red);
3056 GLTexture texture;
3057 glBindTexture(GL_TEXTURE_2D, texture);
3058 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, redColors.data());
3059 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3060 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3061 ASSERT_GL_NO_ERROR();
3062
3063 drawQuad(program, "position", 0.0f);
3064
3065 EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::red);
3066 }
3067
3068 // Test that array of structs containing array of samplers work as expected.
TEST_P(GLSLTest,ArrayOfStructContainingArrayOfSamplers)3069 TEST_P(GLSLTest, ArrayOfStructContainingArrayOfSamplers)
3070 {
3071 constexpr char kFS[] =
3072 "precision mediump float;\n"
3073 "struct Data { mediump sampler2D data[2]; };\n"
3074 "uniform Data test[2];\n"
3075 "void main() {\n"
3076 " gl_FragColor = vec4(texture2D(test[1].data[1], vec2(0.0, 0.0)).r,\n"
3077 " texture2D(test[1].data[0], vec2(0.0, 0.0)).r,\n"
3078 " texture2D(test[0].data[1], vec2(0.0, 0.0)).r,\n"
3079 " texture2D(test[0].data[0], vec2(0.0, 0.0)).r);\n"
3080 "}\n";
3081
3082 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
3083 glUseProgram(program);
3084 GLTexture textures[4];
3085 GLColor expected = MakeGLColor(32, 64, 96, 255);
3086 GLubyte data[8] = {}; // 4 bytes of padding, so that texture can be initialized with 4 bytes
3087 memcpy(data, expected.data(), sizeof(expected));
3088 for (int i = 0; i < 4; i++)
3089 {
3090 int outerIdx = i % 2;
3091 int innerIdx = i / 2;
3092 glActiveTexture(GL_TEXTURE0 + i);
3093 glBindTexture(GL_TEXTURE_2D, textures[i]);
3094 // Each element provides two components.
3095 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data + i);
3096 std::stringstream uniformName;
3097 uniformName << "test[" << innerIdx << "].data[" << outerIdx << "]";
3098 // Then send it as a uniform
3099 GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
3100 // The uniform should be active.
3101 EXPECT_NE(uniformLocation, -1);
3102
3103 glUniform1i(uniformLocation, 3 - i);
3104 }
3105 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3106 EXPECT_PIXEL_COLOR_EQ(0, 0, expected);
3107 }
3108
3109 // Test that if a non-preprocessor token is seen in a disabled if-block then it does not disallow
3110 // extension pragmas later
TEST_P(GLSLTest,NonPreprocessorTokensInIfBlocks)3111 TEST_P(GLSLTest, NonPreprocessorTokensInIfBlocks)
3112 {
3113 constexpr const char *kFS = R"(
3114 #if __VERSION__ >= 300
3115 inout mediump vec4 fragData;
3116 #else
3117 #extension GL_EXT_shader_texture_lod :enable
3118 #endif
3119
3120 void main()
3121 {
3122 }
3123 )";
3124
3125 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
3126 EXPECT_NE(0u, shader);
3127 }
3128
3129 // Test that two constructors which have vec4 and mat2 parameters get disambiguated (issue in
3130 // HLSL).
TEST_P(GLSLTest_ES3,AmbiguousConstructorCall2x2)3131 TEST_P(GLSLTest_ES3, AmbiguousConstructorCall2x2)
3132 {
3133 constexpr char kVS[] =
3134 "#version 300 es\n"
3135 "precision highp float;\n"
3136 "in vec4 a_vec;\n"
3137 "in mat2 a_mat;\n"
3138 "void main()\n"
3139 "{\n"
3140 " gl_Position = vec4(a_vec) + vec4(a_mat);\n"
3141 "}";
3142
3143 GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
3144 EXPECT_NE(0u, program);
3145 }
3146
3147 // Test that two constructors which have mat2x3 and mat3x2 parameters get disambiguated.
3148 // This was suspected to be an issue in HLSL, but HLSL seems to be able to natively choose between
3149 // the function signatures in this case.
TEST_P(GLSLTest_ES3,AmbiguousConstructorCall2x3)3150 TEST_P(GLSLTest_ES3, AmbiguousConstructorCall2x3)
3151 {
3152 constexpr char kVS[] =
3153 "#version 300 es\n"
3154 "precision highp float;\n"
3155 "in mat3x2 a_matA;\n"
3156 "in mat2x3 a_matB;\n"
3157 "void main()\n"
3158 "{\n"
3159 " gl_Position = vec4(a_matA) + vec4(a_matB);\n"
3160 "}";
3161
3162 GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
3163 EXPECT_NE(0u, program);
3164 }
3165
3166 // Test that two functions which have vec4 and mat2 parameters get disambiguated (issue in HLSL).
TEST_P(GLSLTest_ES3,AmbiguousFunctionCall2x2)3167 TEST_P(GLSLTest_ES3, AmbiguousFunctionCall2x2)
3168 {
3169 constexpr char kVS[] =
3170 "#version 300 es\n"
3171 "precision highp float;\n"
3172 "in vec4 a_vec;\n"
3173 "in mat2 a_mat;\n"
3174 "vec4 foo(vec4 a)\n"
3175 "{\n"
3176 " return a;\n"
3177 "}\n"
3178 "vec4 foo(mat2 a)\n"
3179 "{\n"
3180 " return vec4(a[0][0]);\n"
3181 "}\n"
3182 "void main()\n"
3183 "{\n"
3184 " gl_Position = foo(a_vec) + foo(a_mat);\n"
3185 "}";
3186
3187 GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
3188 EXPECT_NE(0u, program);
3189 }
3190
3191 // Test that constructing matrices from non-float types works.
TEST_P(GLSLTest_ES3,ConstructMatrixFromNonFloat)3192 TEST_P(GLSLTest_ES3, ConstructMatrixFromNonFloat)
3193 {
3194 constexpr char kFS[] = R"(#version 300 es
3195 precision highp float;
3196 out vec4 color;
3197
3198 uniform int i;
3199 uniform uint u;
3200 uniform bool b;
3201
3202 void main()
3203 {
3204 mat3x2 mi = mat3x2(i);
3205 mat4 mu = mat4(u);
3206 mat2x4 mb = mat2x4(b);
3207
3208 mat3x2 m = mat3x2(ivec2(i), uvec2(u), bvec2(b));
3209
3210 color = vec4(mi[0][0] == -123.0 ? 1 : 0,
3211 mu[2][2] == 456.0 ? 1 : 0,
3212 mb[1][1] == 1.0 ? 1 : 0,
3213 m[0][1] == -123.0 && m[1][0] == 456.0 && m[2][0] == 1.0 ? 1 : 0);
3214 })";
3215
3216 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3217 glUseProgram(program);
3218
3219 GLint iloc = glGetUniformLocation(program, "i");
3220 GLint uloc = glGetUniformLocation(program, "u");
3221 GLint bloc = glGetUniformLocation(program, "b");
3222 ASSERT_NE(iloc, -1);
3223 ASSERT_NE(uloc, -1);
3224 ASSERT_NE(bloc, -1);
3225 glUniform1i(iloc, -123);
3226 glUniform1ui(uloc, 456);
3227 glUniform1ui(bloc, 1);
3228
3229 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3230 EXPECT_GL_NO_ERROR();
3231
3232 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
3233 }
3234
3235 // Test that constructing vectors from non-float types works.
TEST_P(GLSLTest_ES3,ConstructVectorFromNonFloat)3236 TEST_P(GLSLTest_ES3, ConstructVectorFromNonFloat)
3237 {
3238 constexpr char kFS[] = R"(#version 300 es
3239 precision highp float;
3240 out vec4 color;
3241
3242 uniform ivec2 i;
3243 uniform uvec2 u;
3244 uniform bvec2 b;
3245
3246 void main()
3247 {
3248 vec2 v2 = vec2(i.x, b);
3249 vec3 v3 = vec3(b, u);
3250 vec4 v4 = vec4(i, u);
3251
3252 color = vec4(v2.x == -123.0 && v2.y == 1.0 ? 1 : 0,
3253 v3.x == 1.0 && v3.y == 0.0 && v3.z == 456.0 ? 1 : 0,
3254 v4.x == -123.0 && v4.y == -23.0 && v4.z == 456.0 && v4.w == 76.0 ? 1 : 0,
3255 1);
3256 })";
3257
3258 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3259 glUseProgram(program);
3260
3261 GLint iloc = glGetUniformLocation(program, "i");
3262 GLint uloc = glGetUniformLocation(program, "u");
3263 GLint bloc = glGetUniformLocation(program, "b");
3264 ASSERT_NE(iloc, -1);
3265 ASSERT_NE(uloc, -1);
3266 ASSERT_NE(bloc, -1);
3267 glUniform2i(iloc, -123, -23);
3268 glUniform2ui(uloc, 456, 76);
3269 glUniform2ui(bloc, 1, 0);
3270
3271 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3272 EXPECT_GL_NO_ERROR();
3273
3274 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
3275 }
3276
3277 // Test that constructing non-float vectors from matrix types works.
TEST_P(GLSLTest_ES3,ConstructNonFloatVectorFromMatrix)3278 TEST_P(GLSLTest_ES3, ConstructNonFloatVectorFromMatrix)
3279 {
3280 constexpr char kFS[] = R"(#version 300 es
3281 precision highp float;
3282 out vec4 color;
3283
3284 uniform float f;
3285
3286 void main()
3287 {
3288 mat4 m = mat4(f);
3289 ivec3 vi = ivec3(m);
3290 uvec2 vu = uvec2(m);
3291 bvec4 vb = bvec4(m);
3292 bvec2 vb2 = bvec2(vi.x, m);
3293
3294 color = vec4(vi.x == int(f) ? 1 : 0,
3295 vu.x == uint(f) ? 1 : 0,
3296 vb.x == bool(f) ? 1 : 0,
3297 vb2.x == bool(f) && vb2.y == bool(f) ? 1 : 0);
3298 })";
3299
3300 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3301 glUseProgram(program);
3302
3303 GLint floc = glGetUniformLocation(program, "f");
3304 ASSERT_NE(floc, -1);
3305 glUniform1f(floc, 123);
3306
3307 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3308 EXPECT_GL_NO_ERROR();
3309
3310 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
3311 }
3312
3313 // Test that == and != for vector and matrix types work.
TEST_P(GLSLTest_ES3,NonScalarEqualOperator)3314 TEST_P(GLSLTest_ES3, NonScalarEqualOperator)
3315 {
3316 constexpr char kFS[] = R"(#version 300 es
3317 precision highp float;
3318 out vec4 color;
3319
3320 uniform float f;
3321 uniform int i;
3322 uniform uint u;
3323
3324 void main()
3325 {
3326 mat3x2 m32_1 = mat3x2(vec2(f), vec2(i), vec2(u));
3327 mat3x2 m32_2 = mat3x2(m32_1);
3328 mat3x2 m32_3 = mat3x2(vec2(i), vec2(u), vec2(f));
3329 mat2x3 m23_1 = mat2x3(vec3(f), vec3(i));
3330 mat2x3 m23_2 = mat2x3(m23_1);
3331 mat2x3 m23_3 = mat2x3(vec3(i), vec3(u));
3332 vec2 v2_1 = m32_1[0];
3333 vec2 v2_2 = m32_2[0];
3334 ivec3 v3_1 = ivec3(transpose(m32_1)[0]);
3335 ivec3 v3_2 = ivec3(transpose(m32_2)[0]);
3336 uvec4 v4_1 = uvec4(m32_1[1], m32_1[2]);
3337 uvec4 v4_2 = uvec4(m32_2[1], m32_2[2]);
3338
3339 color = vec4((m32_1 == m32_2 ? 0.5 : 0.0) + (m23_1 == m23_2 ? 0.5 : 0.0),
3340 v2_1 == v2_2 ? 1 : 0,
3341 (v3_1 == v3_2 ? 0.5 : 0.0) +
3342 (v4_1 == v4_2 ? 0.5 : 0.0),
3343 (m32_1 != m32_3 ? 0.125 : 0.0) +
3344 (m23_1 != m23_3 ? 0.125 : 0.0) +
3345 (v2_1 != vec2(v3_2) ? 0.25 : 0.0) +
3346 (v3_1 != ivec3(v4_2) ? 0.25 : 0.0) +
3347 (v4_1 != uvec4(v2_1, v2_2) ? 0.25 : 0.0));
3348 })";
3349
3350 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3351 glUseProgram(program);
3352
3353 GLint floc = glGetUniformLocation(program, "f");
3354 GLint iloc = glGetUniformLocation(program, "i");
3355 GLint uloc = glGetUniformLocation(program, "u");
3356 ASSERT_NE(floc, -1);
3357 ASSERT_NE(iloc, -1);
3358 ASSERT_NE(uloc, -1);
3359 glUniform1f(floc, 1.5);
3360 glUniform1i(iloc, -123);
3361 glUniform1ui(uloc, 456);
3362
3363 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3364 EXPECT_GL_NO_ERROR();
3365
3366 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
3367 }
3368
3369 // Test that == and != for structs and array types work.
TEST_P(GLSLTest_ES31,StructAndArrayEqualOperator)3370 TEST_P(GLSLTest_ES31, StructAndArrayEqualOperator)
3371 {
3372 constexpr char kFS[] = R"(#version 310 es
3373 precision highp float;
3374 out vec4 color;
3375
3376 uniform float f;
3377 uniform int i;
3378 uniform uint u;
3379
3380 struct S
3381 {
3382 float f;
3383 int i;
3384 uint u;
3385 vec4 v;
3386 ivec3 iv;
3387 uvec2 uv;
3388 mat3x2 m32;
3389 mat2x3 m23;
3390 float fa[3][4][5];
3391 int ia[4];
3392 uint ua[6][2];
3393 };
3394
3395 struct T
3396 {
3397 S s1;
3398 S s2[3][2];
3399 };
3400
3401 void main()
3402 {
3403 float fa[5] = float[5](f, f, f, f, f);
3404 int ia[4] = int[4](i, i, i, i);
3405 uint ua[2] = uint[2](u, u);
3406
3407 S s1 = S(f, i, u, vec4(f), ivec3(i), uvec2(u),
3408 mat3x2(vec2(f), vec2(i), vec2(u)),
3409 mat2x3(vec3(f), vec3(i)),
3410 float[3][4][5](
3411 float[4][5](fa, fa, fa, fa),
3412 float[4][5](fa, fa, fa, fa),
3413 float[4][5](fa, fa, fa, fa)),
3414 ia,
3415 uint[6][2](ua, ua, ua, ua, ua, ua));
3416
3417 S s2[2] = S[2](s1, s1);
3418 s2[1].fa[0][1][2] = float(i);
3419
3420 T t1 = T(s1, S[3][2](s2, s2, s2));
3421 T t2 = T(s2[1], S[3][2](s2, s2, s2));
3422
3423 T ta1[2] = T[2](t1, t2);
3424 T ta2[2] = T[2](t1, t2);
3425 T ta3[2] = T[2](t2, t1);
3426
3427 color = vec4((s1 == s2[0] ? 0.5 : 0.0) + (s1 != s2[1] ? 0.5 : 0.0),
3428 (s1.fa[0] == s2[0].fa[0] ? 0.5 : 0.0) + (s1.fa[0] != s2[1].fa[0] ? 0.5 : 0.0),
3429 (ta1[0] == t1 ? 0.5 : 0.0) + (ta1[1] != t1 ? 0.5 : 0.0),
3430 (ta1 == ta2 ? 0.5 : 0.0) + (ta1 != ta3 ? 0.5 : 0.0));
3431 })";
3432
3433 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
3434 glUseProgram(program);
3435
3436 GLint floc = glGetUniformLocation(program, "f");
3437 GLint iloc = glGetUniformLocation(program, "i");
3438 GLint uloc = glGetUniformLocation(program, "u");
3439 ASSERT_NE(floc, -1);
3440 ASSERT_NE(iloc, -1);
3441 ASSERT_NE(uloc, -1);
3442 glUniform1f(floc, 1.5);
3443 glUniform1i(iloc, -123);
3444 glUniform1ui(uloc, 456);
3445
3446 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3447 EXPECT_GL_NO_ERROR();
3448
3449 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
3450 }
3451
3452 // Test that an user-defined function with a large number of float4 parameters doesn't fail due to
3453 // the function name being too long.
TEST_P(GLSLTest_ES3,LargeNumberOfFloat4Parameters)3454 TEST_P(GLSLTest_ES3, LargeNumberOfFloat4Parameters)
3455 {
3456 std::stringstream vertexShaderStream;
3457 // Note: SPIR-V doesn't allow more than 255 parameters to a function.
3458 const unsigned int paramCount = (IsVulkan() || IsMetal()) ? 255u : 1024u;
3459
3460 vertexShaderStream << "#version 300 es\n"
3461 "precision highp float;\n"
3462 "in vec4 a_vec;\n"
3463 "vec4 lotsOfVec4Parameters(";
3464 for (unsigned int i = 0; i < paramCount - 1; ++i)
3465 {
3466 vertexShaderStream << "vec4 a" << i << ", ";
3467 }
3468 vertexShaderStream << "vec4 aLast)\n"
3469 "{\n"
3470 " vec4 sum = vec4(0.0, 0.0, 0.0, 0.0);\n";
3471 for (unsigned int i = 0; i < paramCount - 1; ++i)
3472 {
3473 vertexShaderStream << " sum += a" << i << ";\n";
3474 }
3475 vertexShaderStream << " sum += aLast;\n"
3476 " return sum;\n "
3477 "}\n"
3478 "void main()\n"
3479 "{\n"
3480 " gl_Position = lotsOfVec4Parameters(";
3481 for (unsigned int i = 0; i < paramCount - 1; ++i)
3482 {
3483 vertexShaderStream << "a_vec, ";
3484 }
3485 vertexShaderStream << "a_vec);\n"
3486 "}";
3487
3488 GLuint program = CompileProgram(vertexShaderStream.str().c_str(), essl3_shaders::fs::Red());
3489 EXPECT_NE(0u, program);
3490 }
3491
3492 // This test was written specifically to stress DeferGlobalInitializers AST transformation.
3493 // Test a shader where a global constant array is initialized with an expression containing array
3494 // indexing. This initializer is tricky to constant fold, so if it's not constant folded it needs to
3495 // be handled in a way that doesn't generate statements in the global scope in HLSL output.
3496 // Also includes multiple array initializers in one declaration, where only the second one has
3497 // array indexing. This makes sure that the qualifier for the declaration is set correctly if
3498 // transformations are applied to the declaration also in the case of ESSL output.
TEST_P(GLSLTest_ES3,InitGlobalArrayWithArrayIndexing)3499 TEST_P(GLSLTest_ES3, InitGlobalArrayWithArrayIndexing)
3500 {
3501 // TODO(ynovikov): re-enable once root cause of http://anglebug.com/1428 is fixed
3502 ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
3503
3504 constexpr char kFS[] =
3505 "#version 300 es\n"
3506 "precision highp float;\n"
3507 "out vec4 my_FragColor;\n"
3508 "const highp float f[2] = float[2](0.1, 0.2);\n"
3509 "const highp float[2] g = float[2](0.3, 0.4), h = float[2](0.5, f[1]);\n"
3510 "void main()\n"
3511 "{\n"
3512 " my_FragColor = vec4(h[1]);\n"
3513 "}";
3514
3515 GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS);
3516 EXPECT_NE(0u, program);
3517 }
3518
3519 // Test that constant global matrix array with an initializer compiles.
TEST_P(GLSLTest_ES3,InitConstantMatrixArray)3520 TEST_P(GLSLTest_ES3, InitConstantMatrixArray)
3521 {
3522 constexpr char kFS[] = R"(#version 300 es
3523 precision highp float;
3524 uniform int index;
3525
3526 const mat4 matrix = mat4(1.0);
3527 const mat4 array[1] = mat4[1](matrix);
3528 out vec4 my_FragColor;
3529 void main() {
3530 my_FragColor = vec4(array[index][1].rgb, 1.0);
3531 })";
3532
3533 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3534
3535 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3536 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3537 }
3538
3539 // Test that index-constant sampler array indexing is supported.
TEST_P(GLSLTest,IndexConstantSamplerArrayIndexing)3540 TEST_P(GLSLTest, IndexConstantSamplerArrayIndexing)
3541 {
3542 constexpr char kFS[] =
3543 "precision mediump float;\n"
3544 "uniform sampler2D uni[2];\n"
3545 "\n"
3546 "float zero(int x)\n"
3547 "{\n"
3548 " return float(x) - float(x);\n"
3549 "}\n"
3550 "\n"
3551 "void main()\n"
3552 "{\n"
3553 " vec4 c = vec4(0,0,0,0);\n"
3554 " for (int ii = 1; ii < 3; ++ii) {\n"
3555 " if (c.x > 255.0) {\n"
3556 " c.x = 255.0 + zero(ii);\n"
3557 " break;\n"
3558 " }\n"
3559 // Index the sampler array with a predictable loop index (index-constant) as opposed to
3560 // a true constant. This is valid in OpenGL ES but isn't in many Desktop OpenGL versions,
3561 // without an extension.
3562 " c += texture2D(uni[ii - 1], vec2(0.5, 0.5));\n"
3563 " }\n"
3564 " gl_FragColor = c;\n"
3565 "}";
3566
3567 GLuint program = CompileProgram(essl1_shaders::vs::Simple(), kFS);
3568 EXPECT_NE(0u, program);
3569 }
3570
3571 // Test that the #pragma directive is supported and doesn't trigger a compilation failure on the
3572 // native driver. The only pragma that gets passed to the OpenGL driver is "invariant" but we don't
3573 // want to test its behavior, so don't use any varyings.
TEST_P(GLSLTest,PragmaDirective)3574 TEST_P(GLSLTest, PragmaDirective)
3575 {
3576 constexpr char kVS[] =
3577 "#pragma STDGL invariant(all)\n"
3578 "void main()\n"
3579 "{\n"
3580 " gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
3581 "}\n";
3582
3583 GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
3584 EXPECT_NE(0u, program);
3585 }
3586
3587 // Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
3588 // The function call that returns the array needs to be evaluated after ++j for the expression to
3589 // return the correct value (true).
TEST_P(GLSLTest_ES3,SequenceOperatorEvaluationOrderArray)3590 TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderArray)
3591 {
3592 constexpr char kFS[] =
3593 "#version 300 es\n"
3594 "precision mediump float;\n"
3595 "out vec4 my_FragColor; \n"
3596 "int[2] func(int param) {\n"
3597 " return int[2](param, param);\n"
3598 "}\n"
3599 "void main() {\n"
3600 " int a[2]; \n"
3601 " for (int i = 0; i < 2; ++i) {\n"
3602 " a[i] = 1;\n"
3603 " }\n"
3604 " int j = 0; \n"
3605 " bool result = ((++j), (a == func(j)));\n"
3606 " my_FragColor = vec4(0.0, (result ? 1.0 : 0.0), 0.0, 1.0);\n"
3607 "}\n";
3608
3609 GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS);
3610 ASSERT_NE(0u, program);
3611
3612 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3613
3614 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3615 }
3616
3617 // Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
3618 // The short-circuiting expression needs to be evaluated after ++j for the expression to return the
3619 // correct value (true).
TEST_P(GLSLTest_ES3,SequenceOperatorEvaluationOrderShortCircuit)3620 TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderShortCircuit)
3621 {
3622 constexpr char kFS[] =
3623 "#version 300 es\n"
3624 "precision mediump float;\n"
3625 "out vec4 my_FragColor; \n"
3626 "void main() {\n"
3627 " int j = 0; \n"
3628 " bool result = ((++j), (j == 1 ? true : (++j == 3)));\n"
3629 " my_FragColor = vec4(0.0, ((result && j == 1) ? 1.0 : 0.0), 0.0, 1.0);\n"
3630 "}\n";
3631
3632 GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS);
3633 ASSERT_NE(0u, program);
3634
3635 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3636
3637 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3638 }
3639
3640 // Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
3641 // Indexing the vector needs to be evaluated after func() for the right result.
TEST_P(GLSLTest_ES3,SequenceOperatorEvaluationOrderDynamicVectorIndexingInLValue)3642 TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderDynamicVectorIndexingInLValue)
3643 {
3644 constexpr char kFS[] =
3645 "#version 300 es\n"
3646 "precision mediump float;\n"
3647 "out vec4 my_FragColor;\n"
3648 "uniform int u_zero;\n"
3649 "int sideEffectCount = 0;\n"
3650 "float func() {\n"
3651 " ++sideEffectCount;\n"
3652 " return -1.0;\n"
3653 "}\n"
3654 "void main() {\n"
3655 " vec4 v = vec4(0.0, 2.0, 4.0, 6.0); \n"
3656 " float f = (func(), (++v[u_zero + sideEffectCount]));\n"
3657 " bool green = abs(f - 3.0) < 0.01 && abs(v[1] - 3.0) < 0.01 && sideEffectCount == 1;\n"
3658 " my_FragColor = vec4(0.0, (green ? 1.0 : 0.0), 0.0, 1.0);\n"
3659 "}\n";
3660
3661 GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS);
3662 ASSERT_NE(0u, program);
3663
3664 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3665
3666 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3667 }
3668
3669 // Test that using gl_PointCoord with GL_TRIANGLES doesn't produce a link error.
3670 // From WebGL test conformance/rendering/point-specific-shader-variables.html
3671 // See http://anglebug.com/1380
TEST_P(GLSLTest,RenderTrisWithPointCoord)3672 TEST_P(GLSLTest, RenderTrisWithPointCoord)
3673 {
3674 constexpr char kVS[] =
3675 "attribute vec2 aPosition;\n"
3676 "void main()\n"
3677 "{\n"
3678 " gl_Position = vec4(aPosition, 0, 1);\n"
3679 " gl_PointSize = 1.0;\n"
3680 "}";
3681 constexpr char kFS[] =
3682 "void main()\n"
3683 "{\n"
3684 " gl_FragColor = vec4(gl_PointCoord.xy, 0, 1);\n"
3685 " gl_FragColor = vec4(0, 1, 0, 1);\n"
3686 "}";
3687
3688 ANGLE_GL_PROGRAM(prog, kVS, kFS);
3689 drawQuad(prog, "aPosition", 0.5f);
3690 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3691 }
3692
3693 // Convers a bug with the integer pow statement workaround.
TEST_P(GLSLTest,NestedPowStatements)3694 TEST_P(GLSLTest, NestedPowStatements)
3695 {
3696 // https://crbug.com/1127866 - possible NVIDIA driver issue
3697 ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsVulkan() && IsWindows());
3698
3699 constexpr char kFS[] =
3700 "precision mediump float;\n"
3701 "float func(float v)\n"
3702 "{\n"
3703 " float f1 = pow(v, 2.0);\n"
3704 " return pow(f1 + v, 2.0);\n"
3705 "}\n"
3706 "void main()\n"
3707 "{\n"
3708 " float v = func(2.0);\n"
3709 " gl_FragColor = abs(v - 36.0) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
3710 "}";
3711
3712 ANGLE_GL_PROGRAM(prog, essl1_shaders::vs::Simple(), kFS);
3713 drawQuad(prog, essl1_shaders::PositionAttrib(), 0.5f);
3714 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3715 }
3716
3717 // This test covers a crash seen in an application during SPIR-V compilation
TEST_P(GLSLTest_ES3,NestedPowFromUniform)3718 TEST_P(GLSLTest_ES3, NestedPowFromUniform)
3719 {
3720 constexpr char kVS[] = R"(#version 300 es
3721 in vec2 position;
3722 void main()
3723 {
3724 gl_Position = vec4(position, 0, 1);
3725 })";
3726
3727 constexpr char kFS[] = R"(#version 300 es
3728 precision mediump float;
3729 precision mediump int;
3730
3731 uniform highp vec4 scale;
3732 out mediump vec4 out_FragColor;
3733 void main()
3734 {
3735 highp vec4 v0;
3736 v0 = scale;
3737 highp vec3 v1;
3738 v1.xyz = v0.xyz;
3739 if ((v0.y!=1.0))
3740 {
3741 vec3 v3;
3742 v3.xyz = pow(v0.xyz,v0.xxx);
3743 float h0;
3744 if ((v3.x < 3.13))
3745 {
3746 h0 = (v3.x * 1.29);
3747 }
3748 else
3749 {
3750 h0 = ((pow(v3.x,4.16)*1.055)+-5.5);
3751 }
3752 float h1;
3753 if ((v3.y<3.13))
3754 {
3755 h1 = (v3.y*1.29);
3756 }
3757 else
3758 {
3759 h1 = ((pow(v3.y,4.16)*1.055)+-5.5);
3760 }
3761 float h2;
3762 if ((v3.z<3.13))
3763 {
3764 h2 = (v3.z*1.29);
3765 }
3766 else
3767 {
3768 h2 = ((pow(v3.z,4.16)*1.055)+-5.5);
3769 }
3770 v1.xyz = vec3(h0, h1, h2);
3771 }
3772 out_FragColor = vec4(v1, v0.w);
3773 }
3774 )";
3775
3776 ANGLE_GL_PROGRAM(prog, kVS, kFS);
3777
3778 GLint scaleIndex = glGetUniformLocation(prog, "scale");
3779 ASSERT_NE(-1, scaleIndex);
3780
3781 glUseProgram(prog);
3782 glUniform4f(scaleIndex, 0.5, 0.5, 0.5, 0.5);
3783
3784 // Don't crash
3785 drawQuad(prog, "position", 0.5f);
3786 }
3787
3788 // Test that -float calculation is correct.
TEST_P(GLSLTest_ES3,UnaryMinusOperatorFloat)3789 TEST_P(GLSLTest_ES3, UnaryMinusOperatorFloat)
3790 {
3791 constexpr char kFS[] =
3792 "#version 300 es\n"
3793 "out highp vec4 o_color;\n"
3794 "void main() {\n"
3795 " highp float f = -1.0;\n"
3796 " // atan(tan(0.5), -f) should be 0.5.\n"
3797 " highp float v = atan(tan(0.5), -f);\n"
3798 " o_color = abs(v - 0.5) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
3799 "}\n";
3800
3801 ANGLE_GL_PROGRAM(prog, essl3_shaders::vs::Simple(), kFS);
3802 drawQuad(prog, essl3_shaders::PositionAttrib(), 0.5f);
3803 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3804 }
3805
3806 // Test that atan(vec2, vec2) calculation is correct.
TEST_P(GLSLTest_ES3,AtanVec2)3807 TEST_P(GLSLTest_ES3, AtanVec2)
3808 {
3809 constexpr char kFS[] =
3810 "#version 300 es\n"
3811 "out highp vec4 o_color;\n"
3812 "void main() {\n"
3813 " highp float f = 1.0;\n"
3814 " // atan(tan(0.5), f) should be 0.5.\n"
3815 " highp vec2 v = atan(vec2(tan(0.5)), vec2(f));\n"
3816 " o_color = (abs(v[0] - 0.5) < 0.001 && abs(v[1] - 0.5) < 0.001) ? vec4(0, 1, 0, 1) : "
3817 "vec4(1, 0, 0, 1);\n"
3818 "}\n";
3819
3820 ANGLE_GL_PROGRAM(prog, essl3_shaders::vs::Simple(), kFS);
3821 drawQuad(prog, essl3_shaders::PositionAttrib(), 0.5f);
3822 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3823 }
3824
3825 // Convers a bug with the unary minus operator on signed integer workaround.
TEST_P(GLSLTest_ES3,UnaryMinusOperatorSignedInt)3826 TEST_P(GLSLTest_ES3, UnaryMinusOperatorSignedInt)
3827 {
3828 constexpr char kVS[] =
3829 "#version 300 es\n"
3830 "in highp vec4 position;\n"
3831 "out mediump vec4 v_color;\n"
3832 "uniform int ui_one;\n"
3833 "uniform int ui_two;\n"
3834 "uniform int ui_three;\n"
3835 "void main() {\n"
3836 " int s[3];\n"
3837 " s[0] = ui_one;\n"
3838 " s[1] = -(-(-ui_two + 1) + 1);\n" // s[1] = -ui_two
3839 " s[2] = ui_three;\n"
3840 " int result = 0;\n"
3841 " for (int i = 0; i < ui_three; i++) {\n"
3842 " result += s[i];\n"
3843 " }\n"
3844 " v_color = (result == 2) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
3845 " gl_Position = position;\n"
3846 "}\n";
3847 constexpr char kFS[] =
3848 "#version 300 es\n"
3849 "in mediump vec4 v_color;\n"
3850 "layout(location=0) out mediump vec4 o_color;\n"
3851 "void main() {\n"
3852 " o_color = v_color;\n"
3853 "}\n";
3854
3855 ANGLE_GL_PROGRAM(prog, kVS, kFS);
3856
3857 GLint oneIndex = glGetUniformLocation(prog, "ui_one");
3858 ASSERT_NE(-1, oneIndex);
3859 GLint twoIndex = glGetUniformLocation(prog, "ui_two");
3860 ASSERT_NE(-1, twoIndex);
3861 GLint threeIndex = glGetUniformLocation(prog, "ui_three");
3862 ASSERT_NE(-1, threeIndex);
3863 glUseProgram(prog);
3864 glUniform1i(oneIndex, 1);
3865 glUniform1i(twoIndex, 2);
3866 glUniform1i(threeIndex, 3);
3867
3868 drawQuad(prog, "position", 0.5f);
3869 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3870 }
3871
3872 // Convers a bug with the unary minus operator on unsigned integer workaround.
TEST_P(GLSLTest_ES3,UnaryMinusOperatorUnsignedInt)3873 TEST_P(GLSLTest_ES3, UnaryMinusOperatorUnsignedInt)
3874 {
3875 constexpr char kVS[] =
3876 "#version 300 es\n"
3877 "in highp vec4 position;\n"
3878 "out mediump vec4 v_color;\n"
3879 "uniform uint ui_one;\n"
3880 "uniform uint ui_two;\n"
3881 "uniform uint ui_three;\n"
3882 "void main() {\n"
3883 " uint s[3];\n"
3884 " s[0] = ui_one;\n"
3885 " s[1] = -(-(-ui_two + 1u) + 1u);\n" // s[1] = -ui_two
3886 " s[2] = ui_three;\n"
3887 " uint result = 0u;\n"
3888 " for (uint i = 0u; i < ui_three; i++) {\n"
3889 " result += s[i];\n"
3890 " }\n"
3891 " v_color = (result == 2u) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
3892 " gl_Position = position;\n"
3893 "}\n";
3894 constexpr char kFS[] =
3895 "#version 300 es\n"
3896 "in mediump vec4 v_color;\n"
3897 "layout(location=0) out mediump vec4 o_color;\n"
3898 "void main() {\n"
3899 " o_color = v_color;\n"
3900 "}\n";
3901
3902 ANGLE_GL_PROGRAM(prog, kVS, kFS);
3903
3904 GLint oneIndex = glGetUniformLocation(prog, "ui_one");
3905 ASSERT_NE(-1, oneIndex);
3906 GLint twoIndex = glGetUniformLocation(prog, "ui_two");
3907 ASSERT_NE(-1, twoIndex);
3908 GLint threeIndex = glGetUniformLocation(prog, "ui_three");
3909 ASSERT_NE(-1, threeIndex);
3910 glUseProgram(prog);
3911 glUniform1ui(oneIndex, 1u);
3912 glUniform1ui(twoIndex, 2u);
3913 glUniform1ui(threeIndex, 3u);
3914
3915 drawQuad(prog, "position", 0.5f);
3916 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3917 }
3918
3919 // Test a nested sequence operator with a ternary operator inside. The ternary operator is
3920 // intended to be such that it gets converted to an if statement on the HLSL backend.
TEST_P(GLSLTest,NestedSequenceOperatorWithTernaryInside)3921 TEST_P(GLSLTest, NestedSequenceOperatorWithTernaryInside)
3922 {
3923 // Note that the uniform keep_flop_positive doesn't need to be set - the test expects it to have
3924 // its default value false.
3925 constexpr char kFS[] =
3926 "precision mediump float;\n"
3927 "uniform bool keep_flop_positive;\n"
3928 "float flop;\n"
3929 "void main() {\n"
3930 " flop = -1.0,\n"
3931 " (flop *= -1.0,\n"
3932 " keep_flop_positive ? 0.0 : flop *= -1.0),\n"
3933 " gl_FragColor = vec4(0, -flop, 0, 1);\n"
3934 "}";
3935
3936 ANGLE_GL_PROGRAM(prog, essl1_shaders::vs::Simple(), kFS);
3937 drawQuad(prog, essl1_shaders::PositionAttrib(), 0.5f);
3938 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3939 }
3940
3941 // Test that nesting ternary and short-circuitting operators work.
TEST_P(GLSLTest,NestedTernaryAndShortCircuit)3942 TEST_P(GLSLTest, NestedTernaryAndShortCircuit)
3943 {
3944 // Note that the uniform doesn't need to be set, and will contain the default value of false.
3945 constexpr char kFS[] = R"(
3946 precision mediump float;
3947 uniform bool u;
3948 void main()
3949 {
3950 int a = u ? 12345 : 2; // will be 2
3951 int b = u ? 12345 : 4; // will be 4
3952 int c = u ? 12345 : 0; // will be 0
3953
3954 if (a == 2 // true path is taken
3955 ? (b == 3 // false path is taken
3956 ? (a=0) != 0
3957 : b != 0 // true
3958 ) && ( // short-circuit evaluates RHS
3959 (a=7) == 7 // true, modifies a
3960 || // short-circuit doesn't evaluate RHS
3961 (b=8) == 8
3962 )
3963 : (a == 0 && b == 0
3964 ? (c += int((a=0) == 0 && (b=0) == 0)) != 0
3965 : (c += int((a=0) != 0 && (b=0) != 0)) != 0))
3966 {
3967 c += 15; // will execute
3968 }
3969
3970 // Verify that a is 7, b is 4 and c is 15.
3971 gl_FragColor = vec4(a == 7, b == 4, c == 15, 1);
3972 })";
3973
3974 ANGLE_GL_PROGRAM(prog, essl1_shaders::vs::Simple(), kFS);
3975 drawQuad(prog, essl1_shaders::PositionAttrib(), 0.5f);
3976 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
3977 }
3978
3979 // Test that uniform bvecN passed to functions work.
TEST_P(GLSLTest_ES3,UniformBoolVectorPassedToFunctions)3980 TEST_P(GLSLTest_ES3, UniformBoolVectorPassedToFunctions)
3981 {
3982 constexpr char kFS[] = R"(#version 300 es
3983 precision mediump float;
3984 uniform bvec4 u;
3985 out vec4 color;
3986
3987 bool f(bvec4 bv)
3988 {
3989 return all(bv.xz) && !any(bv.yw);
3990 }
3991
3992 void main() {
3993 color = f(u) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
3994 })";
3995
3996 ANGLE_GL_PROGRAM(prog, essl3_shaders::vs::Simple(), kFS);
3997 glUseProgram(prog);
3998
3999 GLint uloc = glGetUniformLocation(prog, "u");
4000 ASSERT_NE(uloc, -1);
4001 glUniform4ui(uloc, true, false, true, false);
4002
4003 drawQuad(prog, essl3_shaders::PositionAttrib(), 0.5f);
4004 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4005 }
4006
4007 // Test that bvecN in storage buffer passed to functions work.
TEST_P(GLSLTest_ES31,StorageBufferBoolVectorPassedToFunctions)4008 TEST_P(GLSLTest_ES31, StorageBufferBoolVectorPassedToFunctions)
4009 {
4010 constexpr char kCS[] = R"(#version 310 es
4011 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
4012 layout(binding = 0, std430) buffer Output {
4013 bvec4 b;
4014 bool valid;
4015 } outbuf;
4016
4017 bool f_in(bvec4 bv)
4018 {
4019 return all(bv.xz) && !any(bv.yw);
4020 }
4021
4022 bool f_inout(inout bvec4 bv)
4023 {
4024 bool ok = all(bv.xz) && !any(bv.yw);
4025 bv.xw = bvec2(false, true);
4026 return ok;
4027 }
4028
4029 void f_out(out bvec4 bv)
4030 {
4031 bv = bvec4(false, true, false, true);
4032 }
4033
4034 void main() {
4035 bool valid = f_in(outbuf.b);
4036 valid = f_inout(outbuf.b) && valid;
4037 f_out(outbuf.b);
4038 outbuf.valid = valid;
4039 })";
4040
4041 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
4042 glUseProgram(program);
4043
4044 constexpr std::array<GLuint, 5> kOutputInitData = {true, false, true, false, false};
4045 GLBuffer outputBuffer;
4046 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
4047 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kOutputInitData), kOutputInitData.data(),
4048 GL_STATIC_DRAW);
4049 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, outputBuffer);
4050 EXPECT_GL_NO_ERROR();
4051
4052 glDispatchCompute(1, 1, 1);
4053 EXPECT_GL_NO_ERROR();
4054
4055 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4056
4057 const GLuint *ptr = reinterpret_cast<const GLuint *>(
4058 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kOutputInitData), GL_MAP_READ_BIT));
4059 fprintf(stderr, "%d %d %d %d %d\n", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4]);
4060 EXPECT_FALSE(ptr[0]);
4061 EXPECT_TRUE(ptr[1]);
4062 EXPECT_FALSE(ptr[2]);
4063 EXPECT_TRUE(ptr[3]);
4064 EXPECT_TRUE(ptr[4]);
4065 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4066 }
4067
4068 // Test that using a sampler2D and samplerExternalOES in the same shader works (anglebug.com/1534)
TEST_P(GLSLTest,ExternalAnd2DSampler)4069 TEST_P(GLSLTest, ExternalAnd2DSampler)
4070 {
4071 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_EGL_image_external"));
4072
4073 constexpr char kFS[] = R"(#extension GL_OES_EGL_image_external : enable
4074 precision mediump float;
4075 uniform samplerExternalOES tex0;
4076 uniform sampler2D tex1;
4077 void main(void)
4078 {
4079 vec2 uv = vec2(0.0, 0.0);
4080 gl_FragColor = texture2D(tex0, uv) + texture2D(tex1, uv);
4081 })";
4082
4083 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
4084 }
4085
4086 // Tests that monomorphizing functions does not crash if there is a main prototype.
TEST_P(GLSLTest,MonomorphizeMainPrototypeNoCrash)4087 TEST_P(GLSLTest, MonomorphizeMainPrototypeNoCrash)
4088 {
4089 constexpr char kFS[] = R"(precision mediump float;
4090 struct S { sampler2D source; };
4091 vec4 f(S s)
4092 {
4093 return texture2D(s.source, vec2(5));
4094 }
4095 uniform S green;
4096 void main();
4097 void main() {
4098 f(green);
4099 })";
4100 CompileShader(GL_FRAGMENT_SHADER, kFS);
4101 ASSERT_GL_NO_ERROR();
4102 }
4103
4104 // Test that using a varying matrix array is supported.
TEST_P(GLSLTest,VaryingMatrixArray)4105 TEST_P(GLSLTest, VaryingMatrixArray)
4106 {
4107 constexpr char kVS[] =
4108 "uniform vec2 u_a1;\n"
4109 "uniform vec2 u_a2;\n"
4110 "attribute vec4 a_position;\n"
4111 "varying mat2 v_mat[2];\n"
4112 "void main() {\n"
4113 " v_mat[0] = mat2(u_a1, u_a2);\n"
4114 " v_mat[1] = mat2(1.0 - u_a2, 1.0 - u_a1);\n"
4115 " gl_Position = a_position;\n"
4116 "}";
4117
4118 constexpr char kFS[] =
4119 "precision mediump float;\n"
4120 "varying mat2 v_mat[2];\n"
4121 "void main(void)\n"
4122 "{\n"
4123 " gl_FragColor = vec4(v_mat[0][0].x, v_mat[0][0].y, v_mat[1][0].x, 1.0);\n"
4124 "}";
4125
4126 ANGLE_GL_PROGRAM(program, kVS, kFS);
4127
4128 GLint oneIndex = glGetUniformLocation(program, "u_a1");
4129 ASSERT_NE(-1, oneIndex);
4130 GLint twoIndex = glGetUniformLocation(program, "u_a2");
4131 ASSERT_NE(-1, twoIndex);
4132 glUseProgram(program);
4133 glUniform2f(oneIndex, 1, 0.5f);
4134 glUniform2f(twoIndex, 0.25f, 0.125f);
4135
4136 drawQuad(program, "a_position", 0.5f);
4137 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 127, 255 - 63, 255), 1.0);
4138 }
4139
4140 // Test that using a centroid varying matrix array is supported.
TEST_P(GLSLTest_ES3,CentroidVaryingMatrixArray)4141 TEST_P(GLSLTest_ES3, CentroidVaryingMatrixArray)
4142 {
4143 // TODO(anglebug.com/5491): Skipping initial failures so we can set up a passing iOS test bot.
4144 ANGLE_SKIP_TEST_IF(IsIOS() && IsOpenGLES());
4145
4146 constexpr char kVS[] =
4147 "#version 300 es\n"
4148 "uniform vec2 u_a1;\n"
4149 "uniform vec2 u_a2;\n"
4150 "in vec4 a_position;\n"
4151 "centroid out mat3x2 v_mat[2];\n"
4152 "void main() {\n"
4153 " v_mat[0] = mat3x2(u_a1, u_a2, vec2(0.0));\n"
4154 " v_mat[1] = mat3x2(vec2(0.0), 1.0 - u_a2, 1.0 - u_a1);\n"
4155 " gl_Position = a_position;\n"
4156 "}";
4157
4158 constexpr char kFS[] =
4159 "#version 300 es\n"
4160 "precision mediump float;\n"
4161 "centroid in mat3x2 v_mat[2];\n"
4162 "layout(location = 0) out vec4 out_color;\n"
4163 "void main(void)\n"
4164 "{\n"
4165 " out_color = vec4(v_mat[0][0].x, v_mat[0][0].y, v_mat[1][1].x, 1.0);\n"
4166 "}";
4167
4168 ANGLE_GL_PROGRAM(program, kVS, kFS);
4169
4170 GLint oneIndex = glGetUniformLocation(program, "u_a1");
4171 ASSERT_NE(-1, oneIndex);
4172 GLint twoIndex = glGetUniformLocation(program, "u_a2");
4173 ASSERT_NE(-1, twoIndex);
4174 glUseProgram(program);
4175 glUniform2f(oneIndex, 1, 0.5f);
4176 glUniform2f(twoIndex, 0.25f, 0.125f);
4177
4178 drawQuad(program, "a_position", 0.5f);
4179 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 127, 255 - 63, 255), 1.0);
4180 }
4181
4182 // Test that using a flat varying matrix array is supported.
TEST_P(GLSLTest_ES3,FlatVaryingMatrixArray)4183 TEST_P(GLSLTest_ES3, FlatVaryingMatrixArray)
4184 {
4185 constexpr char kVS[] =
4186 "#version 300 es\n"
4187 "uniform vec2 u_a1;\n"
4188 "uniform vec2 u_a2;\n"
4189 "in vec4 a_position;\n"
4190 "flat out mat2 v_mat[2];\n"
4191 "void main() {\n"
4192 " v_mat[0] = mat2(u_a1, u_a2);\n"
4193 " v_mat[1] = mat2(u_a2, u_a1);\n"
4194 " gl_Position = a_position;\n"
4195 "}";
4196
4197 constexpr char kFS[] =
4198 "#version 300 es\n"
4199 "precision mediump float;\n"
4200 "flat in mat2 v_mat[2];\n"
4201 "layout(location = 0) out vec4 out_color;\n"
4202 "void main(void)\n"
4203 "{\n"
4204 " out_color = vec4(v_mat[0][0].x, v_mat[0][0].y, v_mat[1][0].x, 1.0);\n"
4205 "}";
4206
4207 ANGLE_GL_PROGRAM(program, kVS, kFS);
4208
4209 GLint oneIndex = glGetUniformLocation(program, "u_a1");
4210 ASSERT_NE(-1, oneIndex);
4211 GLint twoIndex = glGetUniformLocation(program, "u_a2");
4212 ASSERT_NE(-1, twoIndex);
4213 glUseProgram(program);
4214 glUniform2f(oneIndex, 1, 0.5f);
4215 glUniform2f(twoIndex, 0.25f, 0.125f);
4216
4217 drawQuad(program, "a_position", 0.5f);
4218 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 127, 63, 255), 1.0);
4219 }
4220
4221 // Test that literal infinity can be written out from the shader translator.
4222 // A similar test can't be made for NaNs, since ESSL 3.00.6 requirements for NaNs are very loose.
TEST_P(GLSLTest_ES3,LiteralInfinityOutput)4223 TEST_P(GLSLTest_ES3, LiteralInfinityOutput)
4224 {
4225 constexpr char kFS[] =
4226 "#version 300 es\n"
4227 "precision highp float;\n"
4228 "out vec4 out_color;\n"
4229 "uniform float u;\n"
4230 "void main()\n"
4231 "{\n"
4232 " float infVar = 1.0e40 - u;\n"
4233 " bool correct = isinf(infVar) && infVar > 0.0;\n"
4234 " out_color = correct ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4235 "}\n";
4236
4237 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4238 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
4239 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4240 }
4241
4242 // Test that literal negative infinity can be written out from the shader translator.
4243 // A similar test can't be made for NaNs, since ESSL 3.00.6 requirements for NaNs are very loose.
TEST_P(GLSLTest_ES3,LiteralNegativeInfinityOutput)4244 TEST_P(GLSLTest_ES3, LiteralNegativeInfinityOutput)
4245 {
4246 constexpr char kFS[] =
4247 "#version 300 es\n"
4248 "precision highp float;\n"
4249 "out vec4 out_color;\n"
4250 "uniform float u;\n"
4251 "void main()\n"
4252 "{\n"
4253 " float infVar = -1.0e40 + u;\n"
4254 " bool correct = isinf(infVar) && infVar < 0.0;\n"
4255 " out_color = correct ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4256 "}\n";
4257
4258 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4259 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
4260 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4261 }
4262
4263 // The following MultipleDeclaration* tests are testing TranslatorHLSL specific simplification
4264 // passes. Because the interaction of multiple passes must be tested, it is difficult to write
4265 // a unittest for them. Instead we add the tests as end2end so will in particular test
4266 // TranslatorHLSL when run on Windows.
4267
4268 // Test that passes splitting multiple declarations and comma operators are correctly ordered.
TEST_P(GLSLTest_ES3,MultipleDeclarationWithCommaOperator)4269 TEST_P(GLSLTest_ES3, MultipleDeclarationWithCommaOperator)
4270 {
4271 constexpr char kFS[] = R"(#version 300 es
4272 precision mediump float;
4273 out vec4 color;
4274
4275 uniform float u;
4276 float c = 0.0;
4277 float sideEffect()
4278 {
4279 c = u;
4280 return c;
4281 }
4282
4283 void main(void)
4284 {
4285 float a = 0.0, b = ((gl_FragCoord.x < 0.5 ? a : sideEffect()), a);
4286 color = vec4(b + c);
4287 })";
4288
4289 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4290 }
4291
4292 // Test that passes splitting multiple declarations and comma operators and for loops are
4293 // correctly ordered.
TEST_P(GLSLTest_ES3,MultipleDeclarationWithCommaOperatorInForLoop)4294 TEST_P(GLSLTest_ES3, MultipleDeclarationWithCommaOperatorInForLoop)
4295 {
4296 constexpr char kFS[] = R"(#version 300 es
4297 precision mediump float;
4298 out vec4 color;
4299
4300 uniform float u;
4301 float c = 0.0;
4302 float sideEffect()
4303 {
4304 c = u;
4305 return c;
4306 }
4307
4308 void main(void)
4309 {
4310 for(float a = 0.0, b = ((gl_FragCoord.x < 0.5 ? a : sideEffect()), a); a < 10.0; a++)
4311 {
4312 b += 1.0;
4313 color = vec4(b);
4314 }
4315 })";
4316
4317 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4318 }
4319
4320 // Test that splitting multiple declaration in for loops works with no loop condition
TEST_P(GLSLTest_ES3,MultipleDeclarationInForLoopEmptyCondition)4321 TEST_P(GLSLTest_ES3, MultipleDeclarationInForLoopEmptyCondition)
4322 {
4323 constexpr char kFS[] =
4324 "#version 300 es\n"
4325 "precision mediump float;\n"
4326 "out vec4 color;\n"
4327 "void main(void)\n"
4328 "{\n"
4329 " for(float a = 0.0, b = 1.0;; a++)\n"
4330 " {\n"
4331 " b += 1.0;\n"
4332 " if (a > 10.0) {break;}\n"
4333 " color = vec4(b);\n"
4334 " }\n"
4335 "}\n";
4336
4337 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4338 }
4339
4340 // Test that splitting multiple declaration in for loops works with no loop expression
TEST_P(GLSLTest_ES3,MultipleDeclarationInForLoopEmptyExpression)4341 TEST_P(GLSLTest_ES3, MultipleDeclarationInForLoopEmptyExpression)
4342 {
4343 constexpr char kFS[] =
4344 "#version 300 es\n"
4345 "precision mediump float;\n"
4346 "out vec4 color;\n"
4347 "void main(void)\n"
4348 "{\n"
4349 " for(float a = 0.0, b = 1.0; a < 10.0;)\n"
4350 " {\n"
4351 " b += 1.0;\n"
4352 " a += 1.0;\n"
4353 " color = vec4(b);\n"
4354 " }\n"
4355 "}\n";
4356
4357 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4358 }
4359
4360 // Test that dynamic indexing of a matrix inside a dynamic indexing of a vector in an l-value works
4361 // correctly.
TEST_P(GLSLTest_ES3,NestedDynamicIndexingInLValue)4362 TEST_P(GLSLTest_ES3, NestedDynamicIndexingInLValue)
4363 {
4364 constexpr char kFS[] =
4365 "#version 300 es\n"
4366 "precision mediump float;\n"
4367 "out vec4 my_FragColor;\n"
4368 "uniform int u_zero;\n"
4369 "void main() {\n"
4370 " mat2 m = mat2(0.0, 0.0, 0.0, 0.0);\n"
4371 " m[u_zero + 1][u_zero + 1] = float(u_zero + 1);\n"
4372 " float f = m[1][1];\n"
4373 " my_FragColor = vec4(1.0 - f, f, 0.0, 1.0);\n"
4374 "}\n";
4375
4376 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4377 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
4378 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4379 }
4380
4381 class WebGLGLSLTest : public GLSLTest
4382 {
4383 protected:
WebGLGLSLTest()4384 WebGLGLSLTest() { setWebGLCompatibilityEnabled(true); }
4385 };
4386
4387 class WebGL2GLSLTest : public GLSLTest
4388 {
4389 protected:
WebGL2GLSLTest()4390 WebGL2GLSLTest() { setWebGLCompatibilityEnabled(true); }
4391 };
4392
TEST_P(WebGLGLSLTest,MaxVaryingVec4PlusFragCoord)4393 TEST_P(WebGLGLSLTest, MaxVaryingVec4PlusFragCoord)
4394 {
4395 GLint maxVaryings = 0;
4396 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4397
4398 // Generate shader code that uses gl_FragCoord, a special fragment shader variables.
4399 // This test should fail, since we are really using (maxVaryings + 1) varyings.
4400 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, true, false, false, false);
4401 }
4402
TEST_P(WebGLGLSLTest,MaxVaryingVec4PlusPointCoord)4403 TEST_P(WebGLGLSLTest, MaxVaryingVec4PlusPointCoord)
4404 {
4405 GLint maxVaryings = 0;
4406 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4407
4408 // Generate shader code that uses gl_FragCoord, a special fragment shader variables.
4409 // This test should fail, since we are really using (maxVaryings + 1) varyings.
4410 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, false, true, false, false);
4411 }
4412
TEST_P(WebGLGLSLTest,MaxPlusOneVaryingVec3)4413 TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec3)
4414 {
4415 GLint maxVaryings = 0;
4416 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4417
4418 VaryingTestBase(0, 0, 0, 0, maxVaryings + 1, 0, 0, 0, false, false, false, false);
4419 }
4420
TEST_P(WebGLGLSLTest,MaxPlusOneVaryingVec3Array)4421 TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec3Array)
4422 {
4423 GLint maxVaryings = 0;
4424 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4425
4426 VaryingTestBase(0, 0, 0, 0, 0, maxVaryings / 2 + 1, 0, 0, false, false, false, false);
4427 }
4428
TEST_P(WebGLGLSLTest,MaxVaryingVec3AndOneVec2)4429 TEST_P(WebGLGLSLTest, MaxVaryingVec3AndOneVec2)
4430 {
4431 GLint maxVaryings = 0;
4432 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4433
4434 VaryingTestBase(0, 0, 1, 0, maxVaryings, 0, 0, 0, false, false, false, false);
4435 }
4436
TEST_P(WebGLGLSLTest,MaxPlusOneVaryingVec2)4437 TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec2)
4438 {
4439 GLint maxVaryings = 0;
4440 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4441
4442 VaryingTestBase(0, 0, 2 * maxVaryings + 1, 0, 0, 0, 0, 0, false, false, false, false);
4443 }
4444
TEST_P(WebGLGLSLTest,MaxVaryingVec3ArrayAndMaxPlusOneFloatArray)4445 TEST_P(WebGLGLSLTest, MaxVaryingVec3ArrayAndMaxPlusOneFloatArray)
4446 {
4447 GLint maxVaryings = 0;
4448 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4449
4450 VaryingTestBase(0, maxVaryings / 2 + 1, 0, 0, 0, 0, 0, maxVaryings / 2, false, false, false,
4451 false);
4452 }
4453
4454 // Test that FindLSB and FindMSB return correct values in their corner cases.
TEST_P(GLSLTest_ES31,FindMSBAndFindLSBCornerCases)4455 TEST_P(GLSLTest_ES31, FindMSBAndFindLSBCornerCases)
4456 {
4457 // Suspecting AMD driver bug - failure seen on bots running on AMD R5 230.
4458 ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL() && IsLinux());
4459
4460 // Failing on N5X Oreo http://anglebug.com/2304
4461 ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
4462
4463 constexpr char kFS[] =
4464 "#version 310 es\n"
4465 "precision mediump float;\n"
4466 "out vec4 my_FragColor;\n"
4467 "uniform int u_zero;\n"
4468 "void main() {\n"
4469 " if (findLSB(u_zero) == -1 && findMSB(u_zero) == -1 && findMSB(u_zero - 1) == -1)\n"
4470 " {\n"
4471 " my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
4472 " }\n"
4473 " else\n"
4474 " {\n"
4475 " my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
4476 " }\n"
4477 "}\n";
4478
4479 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4480 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
4481 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4482 }
4483
4484 // Test that writing into a swizzled vector that is dynamically indexed succeeds.
TEST_P(GLSLTest_ES3,WriteIntoDynamicIndexingOfSwizzledVector)4485 TEST_P(GLSLTest_ES3, WriteIntoDynamicIndexingOfSwizzledVector)
4486 {
4487 // http://anglebug.com/1924
4488 ANGLE_SKIP_TEST_IF(IsOpenGL());
4489
4490 // The shader first assigns v.x to v.z (1.0)
4491 // Then v.y to v.y (2.0)
4492 // Then v.z to v.x (1.0)
4493 constexpr char kFS[] =
4494 "#version 300 es\n"
4495 "precision highp float;\n"
4496 "out vec4 my_FragColor;\n"
4497 "void main() {\n"
4498 " vec3 v = vec3(1.0, 2.0, 3.0);\n"
4499 " for (int i = 0; i < 3; i++) {\n"
4500 " v.zyx[i] = v[i];\n"
4501 " }\n"
4502 " my_FragColor = distance(v, vec3(1.0, 2.0, 1.0)) < 0.01 ? vec4(0, 1, 0, 1) : vec4(1, "
4503 "0, 0, 1);\n"
4504 "}\n";
4505
4506 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4507 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
4508 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4509 }
4510
4511 // Test including Ternary using a uniform block is correctly
4512 // expanded.
TEST_P(GLSLTest_ES3,NamelessUniformBlockTernary)4513 TEST_P(GLSLTest_ES3, NamelessUniformBlockTernary)
4514 {
4515 const char kVS[] = R"(#version 300 es
4516 precision highp float;
4517 out vec4 color_interp;
4518 void main()
4519 {
4520 color_interp = vec4(0.0);
4521 }
4522 )";
4523 const char kFS[] = R"(#version 300 es
4524 precision highp float;
4525 out vec4 fragColor;
4526 in vec4 color_interp;
4527 layout(std140) uniform TestData {
4528 int a;
4529 int b;
4530 };
4531 void main()
4532 {
4533 int c, a1;
4534 a1 += c > 0 ? a : b;
4535 fragColor = vec4(a1,a1,a1,1.0);
4536 }
4537 )";
4538 ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
4539 }
4540
4541 // Test that the length() method is correctly translated in Vulkan atomic counter buffer emulation.
TEST_P(GLSLTest_ES31,AtomicCounterArrayLength)4542 TEST_P(GLSLTest_ES31, AtomicCounterArrayLength)
4543 {
4544 // Crashes on an assertion. The driver reports no atomic counter buffers when queried from the
4545 // program, but ANGLE believes there to be one.
4546 //
4547 // This is likely due to the fact that ANGLE generates the following code, as a side effect of
4548 // the code on which .length() is being called:
4549 //
4550 // _uac1[(_uvalue = _utestSideEffectValue)];
4551 //
4552 // The driver is optimizing the subscription out, and calling the atomic counter inactive. This
4553 // was observed on nvidia, mesa and amd/windows.
4554 //
4555 // The fix would be for ANGLE to skip uniforms it believes should exist, but when queried, the
4556 // driver says don't.
4557 //
4558 // http://anglebug.com/3782
4559 ANGLE_SKIP_TEST_IF(IsOpenGL());
4560
4561 constexpr char kCS[] = R"(#version 310 es
4562 precision mediump float;
4563 layout(local_size_x=1) in;
4564
4565 layout(binding = 0) uniform atomic_uint ac1[2][3][4];
4566 uniform uint testSideEffectValue;
4567
4568 layout(binding = 1, std140) buffer Result
4569 {
4570 uint value;
4571 } result;
4572
4573 void main() {
4574 bool passed = true;
4575 if (ac1.length() != 2)
4576 {
4577 passed = false;
4578 }
4579 uint value = 0u;
4580 if (ac1[value = testSideEffectValue].length() != 3)
4581 {
4582 passed = false;
4583 }
4584 if (value != testSideEffectValue)
4585 {
4586 passed = false;
4587 }
4588 if (ac1[1][value = testSideEffectValue + 1u].length() != 4)
4589 {
4590 passed = false;
4591 }
4592 if (value != testSideEffectValue + 1u)
4593 {
4594 passed = false;
4595 }
4596 result.value = passed ? 255u : 127u;
4597 })";
4598
4599 constexpr unsigned int kUniformTestValue = 17;
4600 constexpr unsigned int kExpectedSuccessValue = 255;
4601 constexpr unsigned int kAtomicCounterRows = 2;
4602 constexpr unsigned int kAtomicCounterCols = 3;
4603
4604 GLint maxAtomicCounters = 0;
4605 glGetIntegerv(GL_MAX_COMPUTE_ATOMIC_COUNTERS, &maxAtomicCounters);
4606 EXPECT_GL_NO_ERROR();
4607
4608 // Required minimum is 8 by the spec
4609 EXPECT_GE(maxAtomicCounters, 8);
4610 ANGLE_SKIP_TEST_IF(static_cast<uint32_t>(maxAtomicCounters) <
4611 kAtomicCounterRows * kAtomicCounterCols);
4612
4613 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
4614 glUseProgram(program);
4615
4616 constexpr unsigned int kBufferData[kAtomicCounterRows * kAtomicCounterCols] = {};
4617 GLBuffer atomicCounterBuffer;
4618 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
4619 glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(kBufferData), kBufferData, GL_STATIC_DRAW);
4620 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
4621
4622 constexpr unsigned int kOutputInitValue = 0;
4623 GLBuffer shaderStorageBuffer;
4624 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer);
4625 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kOutputInitValue), &kOutputInitValue,
4626 GL_STATIC_DRAW);
4627 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, shaderStorageBuffer);
4628
4629 GLint uniformLocation = glGetUniformLocation(program, "testSideEffectValue");
4630 EXPECT_NE(uniformLocation, -1);
4631 glUniform1ui(uniformLocation, kUniformTestValue);
4632 EXPECT_GL_NO_ERROR();
4633
4634 glDispatchCompute(1, 1, 1);
4635
4636 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4637
4638 const GLuint *ptr = reinterpret_cast<const GLuint *>(
4639 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(GLuint), GL_MAP_READ_BIT));
4640 EXPECT_EQ(*ptr, kExpectedSuccessValue);
4641 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4642 }
4643
4644 // Test that inactive images don't cause any errors.
TEST_P(GLSLTest_ES31,InactiveImages)4645 TEST_P(GLSLTest_ES31, InactiveImages)
4646 {
4647 ANGLE_SKIP_TEST_IF(IsD3D11());
4648
4649 constexpr char kCS[] = R"(#version 310 es
4650 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
4651 layout(rgba32ui) uniform highp readonly uimage2D image1;
4652 layout(rgba32ui) uniform highp readonly uimage2D image2[4];
4653 void main()
4654 {
4655 })";
4656
4657 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
4658
4659 glUseProgram(program);
4660 glDispatchCompute(1, 1, 1);
4661 EXPECT_GL_NO_ERROR();
4662
4663 // Verify that the images are indeed inactive.
4664 GLuint index = glGetProgramResourceIndex(program, GL_UNIFORM, "image1");
4665 EXPECT_GL_NO_ERROR();
4666 EXPECT_EQ(GL_INVALID_INDEX, index);
4667
4668 index = glGetProgramResourceIndex(program, GL_UNIFORM, "image2");
4669 EXPECT_GL_NO_ERROR();
4670 EXPECT_EQ(GL_INVALID_INDEX, index);
4671 }
4672
4673 // Test that inactive atomic counters don't cause any errors.
TEST_P(GLSLTest_ES31,InactiveAtomicCounters)4674 TEST_P(GLSLTest_ES31, InactiveAtomicCounters)
4675 {
4676 constexpr char kCS[] = R"(#version 310 es
4677 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
4678 layout(binding = 0, offset = 0) uniform atomic_uint ac1;
4679 layout(binding = 0, offset = 4) uniform atomic_uint ac2[5];
4680 void main()
4681 {
4682 })";
4683
4684 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
4685
4686 glUseProgram(program);
4687 glDispatchCompute(1, 1, 1);
4688 EXPECT_GL_NO_ERROR();
4689
4690 // Verify that the atomic counters are indeed inactive.
4691 GLuint index = glGetProgramResourceIndex(program, GL_UNIFORM, "ac1");
4692 EXPECT_GL_NO_ERROR();
4693 EXPECT_EQ(GL_INVALID_INDEX, index);
4694
4695 index = glGetProgramResourceIndex(program, GL_UNIFORM, "ac2");
4696 EXPECT_GL_NO_ERROR();
4697 EXPECT_EQ(GL_INVALID_INDEX, index);
4698 }
4699
4700 // Test that inactive samplers in structs don't cause any errors.
TEST_P(GLSLTest_ES31,InactiveSamplersInStructCS)4701 TEST_P(GLSLTest_ES31, InactiveSamplersInStructCS)
4702 {
4703 constexpr char kCS[] = R"(#version 310 es
4704 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
4705 struct S
4706 {
4707 vec4 v;
4708 sampler2D t[10];
4709 };
4710 uniform S s;
4711 void main()
4712 {
4713 })";
4714
4715 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
4716
4717 glUseProgram(program);
4718 glDispatchCompute(1, 1, 1);
4719 EXPECT_GL_NO_ERROR();
4720 }
4721
4722 // Test that array indices for arrays of arrays of basic types work as expected.
TEST_P(GLSLTest_ES31,ArraysOfArraysBasicType)4723 TEST_P(GLSLTest_ES31, ArraysOfArraysBasicType)
4724 {
4725 constexpr char kFS[] =
4726 "#version 310 es\n"
4727 "precision mediump float;\n"
4728 "out vec4 my_FragColor;\n"
4729 "uniform ivec2 test[2][2];\n"
4730 "void main() {\n"
4731 " bool passed = true;\n"
4732 " for (int i = 0; i < 2; i++) {\n"
4733 " for (int j = 0; j < 2; j++) {\n"
4734 " if (test[i][j] != ivec2(i + 1, j + 1)) {\n"
4735 " passed = false;\n"
4736 " }\n"
4737 " }\n"
4738 " }\n"
4739 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4740 "}\n";
4741
4742 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4743 glUseProgram(program);
4744 for (int i = 0; i < 2; i++)
4745 {
4746 for (int j = 0; j < 2; j++)
4747 {
4748 std::stringstream uniformName;
4749 uniformName << "test[" << i << "][" << j << "]";
4750 GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
4751 // All array indices should be used.
4752 EXPECT_NE(uniformLocation, -1);
4753 glUniform2i(uniformLocation, i + 1, j + 1);
4754 }
4755 }
4756 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
4757 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4758 }
4759
4760 // Test that array indices for arrays of arrays of basic types work as expected
4761 // inside blocks.
TEST_P(GLSLTest_ES31,ArraysOfArraysBlockBasicType)4762 TEST_P(GLSLTest_ES31, ArraysOfArraysBlockBasicType)
4763 {
4764 // anglebug.com/3821 - fails on AMD Windows
4765 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL());
4766 constexpr char kFS[] =
4767 "#version 310 es\n"
4768 "precision mediump float;\n"
4769 "out vec4 my_FragColor;\n"
4770 "layout(packed) uniform UBO { ivec2 test[2][2]; } ubo_data;\n"
4771 "void main() {\n"
4772 " bool passed = true;\n"
4773 " for (int i = 0; i < 2; i++) {\n"
4774 " for (int j = 0; j < 2; j++) {\n"
4775 " if (ubo_data.test[i][j] != ivec2(i + 1, j + 1)) {\n"
4776 " passed = false;\n"
4777 " }\n"
4778 " }\n"
4779 " }\n"
4780 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4781 "}\n";
4782
4783 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4784 glUseProgram(program);
4785 // Use interface queries to determine buffer size and offset
4786 GLuint uboBlockIndex = glGetProgramResourceIndex(program, GL_UNIFORM_BLOCK, "UBO");
4787 GLenum uboDataSizeProp = GL_BUFFER_DATA_SIZE;
4788 GLint uboDataSize;
4789 glGetProgramResourceiv(program, GL_UNIFORM_BLOCK, uboBlockIndex, 1, &uboDataSizeProp, 1,
4790 nullptr, &uboDataSize);
4791 std::unique_ptr<char[]> uboData(new char[uboDataSize]);
4792 for (int i = 0; i < 2; i++)
4793 {
4794 std::stringstream resourceName;
4795 resourceName << "UBO.test[" << i << "][0]";
4796 GLenum resourceProps[] = {GL_ARRAY_STRIDE, GL_OFFSET};
4797 struct
4798 {
4799 GLint stride;
4800 GLint offset;
4801 } values;
4802 GLuint resourceIndex =
4803 glGetProgramResourceIndex(program, GL_UNIFORM, resourceName.str().c_str());
4804 ASSERT_NE(resourceIndex, GL_INVALID_INDEX);
4805 glGetProgramResourceiv(program, GL_UNIFORM, resourceIndex, 2, &resourceProps[0], 2, nullptr,
4806 &values.stride);
4807 for (int j = 0; j < 2; j++)
4808 {
4809 GLint(&dataPtr)[2] =
4810 *reinterpret_cast<GLint(*)[2]>(&uboData[values.offset + j * values.stride]);
4811 dataPtr[0] = i + 1;
4812 dataPtr[1] = j + 1;
4813 }
4814 }
4815 GLBuffer ubo;
4816 glBindBuffer(GL_UNIFORM_BUFFER, ubo);
4817 glBufferData(GL_UNIFORM_BUFFER, uboDataSize, &uboData[0], GL_STATIC_DRAW);
4818 GLuint ubo_index = glGetUniformBlockIndex(program, "UBO");
4819 ASSERT_NE(ubo_index, GL_INVALID_INDEX);
4820 glUniformBlockBinding(program, ubo_index, 5);
4821 glBindBufferBase(GL_UNIFORM_BUFFER, 5, ubo);
4822 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
4823 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4824 }
4825
4826 // Test that arrays of arrays of samplers work as expected.
TEST_P(GLSLTest_ES31,ArraysOfArraysSampler)4827 TEST_P(GLSLTest_ES31, ArraysOfArraysSampler)
4828 {
4829 constexpr char kFS[] =
4830 "#version 310 es\n"
4831 "precision mediump float;\n"
4832 "out vec4 my_FragColor;\n"
4833 "uniform mediump isampler2D test[2][2];\n"
4834 "void main() {\n"
4835 " bool passed = true;\n"
4836 "#define DO_CHECK(i,j) \\\n"
4837 " if (texture(test[i][j], vec2(0.0, 0.0)) != ivec4(i + 1, j + 1, 0, 1)) { \\\n"
4838 " passed = false; \\\n"
4839 " }\n"
4840 " DO_CHECK(0, 0)\n"
4841 " DO_CHECK(0, 1)\n"
4842 " DO_CHECK(1, 0)\n"
4843 " DO_CHECK(1, 1)\n"
4844 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4845 "}\n";
4846
4847 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4848 glUseProgram(program);
4849 GLTexture textures[2][2];
4850 for (int i = 0; i < 2; i++)
4851 {
4852 for (int j = 0; j < 2; j++)
4853 {
4854 // First generate the texture
4855 int textureUnit = i * 2 + j;
4856 glActiveTexture(GL_TEXTURE0 + textureUnit);
4857 glBindTexture(GL_TEXTURE_2D, textures[i][j]);
4858 GLint texData[2] = {i + 1, j + 1};
4859 glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32I, 1, 1, 0, GL_RG_INTEGER, GL_INT, &texData[0]);
4860 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4861 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4862 // Then send it as a uniform
4863 std::stringstream uniformName;
4864 uniformName << "test[" << i << "][" << j << "]";
4865 GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
4866 // All array indices should be used.
4867 EXPECT_NE(uniformLocation, -1);
4868 glUniform1i(uniformLocation, textureUnit);
4869 }
4870 }
4871 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
4872 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4873 }
4874
4875 // Test that arrays of arrays of images work as expected.
TEST_P(GLSLTest_ES31,ArraysOfArraysImage)4876 TEST_P(GLSLTest_ES31, ArraysOfArraysImage)
4877 {
4878 // http://anglebug.com/5072
4879 ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
4880
4881 // Fails on D3D due to mistranslation.
4882 ANGLE_SKIP_TEST_IF(IsD3D());
4883
4884 // Fails on Android on GLES.
4885 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
4886
4887 GLint maxTextures, maxComputeImageUniforms;
4888 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextures);
4889 glGetIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &maxComputeImageUniforms);
4890 ANGLE_SKIP_TEST_IF(maxTextures < 1 * 2 * 3);
4891 ANGLE_SKIP_TEST_IF(maxComputeImageUniforms < 1 * 2 * 3);
4892
4893 constexpr char kComputeShader[] = R"(#version 310 es
4894 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
4895 layout(binding = 0, r32ui) uniform highp readonly uimage2D image[1][2][3];
4896 layout(binding = 1, std430) buffer Output {
4897 uint image_value;
4898 } outbuf;
4899
4900 void main(void)
4901 {
4902 outbuf.image_value = uint(0.0);
4903 outbuf.image_value += imageLoad(image[0][0][0], ivec2(0, 0)).x;
4904 outbuf.image_value += imageLoad(image[0][0][1], ivec2(0, 0)).x;
4905 outbuf.image_value += imageLoad(image[0][0][2], ivec2(0, 0)).x;
4906 outbuf.image_value += imageLoad(image[0][1][0], ivec2(0, 0)).x;
4907 outbuf.image_value += imageLoad(image[0][1][1], ivec2(0, 0)).x;
4908 outbuf.image_value += imageLoad(image[0][1][2], ivec2(0, 0)).x;
4909 })";
4910 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
4911 EXPECT_GL_NO_ERROR();
4912
4913 glUseProgram(program);
4914
4915 GLuint outputInitData[1] = {10};
4916 GLBuffer outputBuffer;
4917 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
4918 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), outputInitData, GL_STATIC_DRAW);
4919 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
4920 EXPECT_GL_NO_ERROR();
4921
4922 GLuint imageData = 200u;
4923 GLTexture images[1][2][3];
4924 for (int i = 0; i < 1; i++)
4925 {
4926 for (int j = 0; j < 2; j++)
4927 {
4928 for (int k = 0; k < 3; k++)
4929 {
4930 glBindTexture(GL_TEXTURE_2D, images[i][j][k]);
4931 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
4932 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT,
4933 &imageData);
4934 glBindImageTexture(i * 6 + j * 3 + k, images[i][j][k], 0, GL_FALSE, 0, GL_READ_ONLY,
4935 GL_R32UI);
4936 EXPECT_GL_NO_ERROR();
4937 }
4938 }
4939 }
4940
4941 glDispatchCompute(1, 1, 1);
4942 EXPECT_GL_NO_ERROR();
4943
4944 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4945
4946 // read back
4947 const GLuint *ptr = reinterpret_cast<const GLuint *>(
4948 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
4949 memcpy(outputInitData, ptr, sizeof(outputInitData));
4950 EXPECT_EQ(outputInitData[0], imageData * 1 * 2 * 3);
4951 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4952 }
4953
4954 // Test that multiple arrays of arrays of images work as expected.
TEST_P(GLSLTest_ES31,ConsecutiveArraysOfArraysImage)4955 TEST_P(GLSLTest_ES31, ConsecutiveArraysOfArraysImage)
4956 {
4957 // http://anglebug.com/5072
4958 ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
4959
4960 // Fails on D3D due to mistranslation.
4961 ANGLE_SKIP_TEST_IF(IsD3D());
4962
4963 constexpr GLsizei kImage1Layers = 3;
4964 constexpr GLsizei kImage1Rows = 2;
4965 constexpr GLsizei kImage1Cols = 1;
4966 constexpr GLsizei kImage2Rows = 2;
4967 constexpr GLsizei kImage2Cols = 4;
4968
4969 constexpr GLsizei kImage1Units = kImage1Layers * kImage1Rows * kImage1Cols;
4970 constexpr GLsizei kImage2Units = kImage2Rows * kImage2Cols;
4971 constexpr GLsizei kImage3Units = 1;
4972
4973 constexpr GLsizei kTotalImageCount = kImage1Units + kImage2Units + kImage3Units;
4974
4975 GLint maxTextures, maxComputeImageUniforms;
4976 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextures);
4977 glGetIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &maxComputeImageUniforms);
4978 ANGLE_SKIP_TEST_IF(maxTextures < kTotalImageCount);
4979 ANGLE_SKIP_TEST_IF(maxComputeImageUniforms < kTotalImageCount);
4980
4981 constexpr char kComputeShader[] = R"(#version 310 es
4982 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
4983 layout(binding = 0, r32ui) uniform highp readonly uimage2D image1[3][2][1];
4984 layout(binding = 6, r32ui) uniform highp readonly uimage2D image2[2][4];
4985 layout(binding = 14, r32ui) uniform highp readonly uimage2D image3;
4986 layout(binding = 0, std430) buffer Output {
4987 uint image_value;
4988 } outbuf;
4989
4990 void main(void)
4991 {
4992 outbuf.image_value = uint(0.0);
4993
4994 outbuf.image_value += imageLoad(image1[0][0][0], ivec2(0, 0)).x;
4995 outbuf.image_value += imageLoad(image1[0][1][0], ivec2(0, 0)).x;
4996 outbuf.image_value += imageLoad(image1[1][0][0], ivec2(0, 0)).x;
4997 outbuf.image_value += imageLoad(image1[1][1][0], ivec2(0, 0)).x;
4998 outbuf.image_value += imageLoad(image1[2][0][0], ivec2(0, 0)).x;
4999 outbuf.image_value += imageLoad(image1[2][1][0], ivec2(0, 0)).x;
5000
5001 outbuf.image_value += imageLoad(image2[0][0], ivec2(0, 0)).x;
5002 outbuf.image_value += imageLoad(image2[0][1], ivec2(0, 0)).x;
5003 outbuf.image_value += imageLoad(image2[0][2], ivec2(0, 0)).x;
5004 outbuf.image_value += imageLoad(image2[0][3], ivec2(0, 0)).x;
5005 outbuf.image_value += imageLoad(image2[1][0], ivec2(0, 0)).x;
5006 outbuf.image_value += imageLoad(image2[1][1], ivec2(0, 0)).x;
5007 outbuf.image_value += imageLoad(image2[1][2], ivec2(0, 0)).x;
5008 outbuf.image_value += imageLoad(image2[1][3], ivec2(0, 0)).x;
5009
5010 outbuf.image_value += imageLoad(image3, ivec2(0, 0)).x;
5011 })";
5012 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
5013 EXPECT_GL_NO_ERROR();
5014
5015 glUseProgram(program);
5016
5017 constexpr GLuint kOutputInitData = 10;
5018 GLBuffer outputBuffer;
5019 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
5020 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kOutputInitData), &kOutputInitData,
5021 GL_STATIC_DRAW);
5022 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, outputBuffer);
5023 EXPECT_GL_NO_ERROR();
5024
5025 constexpr GLsizei kImage1Binding = 0;
5026 constexpr GLsizei kImage2Binding = kImage1Binding + kImage1Units;
5027 constexpr GLsizei kImage3Binding = kImage2Binding + kImage2Units;
5028
5029 constexpr GLuint kImage1Data = 13;
5030 GLTexture images1[kImage1Layers][kImage1Rows][kImage1Cols];
5031 for (int layer = 0; layer < kImage1Layers; layer++)
5032 {
5033 for (int row = 0; row < kImage1Rows; row++)
5034 {
5035 for (int col = 0; col < kImage1Cols; col++)
5036 {
5037 glBindTexture(GL_TEXTURE_2D, images1[layer][row][col]);
5038 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
5039 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT,
5040 &kImage1Data);
5041 glBindImageTexture(kImage1Binding + (layer * kImage1Rows + row) * kImage1Cols + col,
5042 images1[layer][row][col], 0, GL_FALSE, 0, GL_READ_ONLY,
5043 GL_R32UI);
5044 EXPECT_GL_NO_ERROR();
5045 }
5046 }
5047 }
5048
5049 constexpr GLuint kImage2Data = 17;
5050 GLTexture images2[kImage2Rows][kImage2Cols];
5051 for (int row = 0; row < kImage2Rows; row++)
5052 {
5053 for (int col = 0; col < kImage2Cols; col++)
5054 {
5055 glBindTexture(GL_TEXTURE_2D, images2[row][col]);
5056 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
5057 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT,
5058 &kImage2Data);
5059 glBindImageTexture(kImage2Binding + row * kImage2Cols + col, images2[row][col], 0,
5060 GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
5061 EXPECT_GL_NO_ERROR();
5062 }
5063 }
5064
5065 constexpr GLuint kImage3Data = 19;
5066 GLTexture image3;
5067 glBindTexture(GL_TEXTURE_2D, image3);
5068 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
5069 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &kImage3Data);
5070 glBindImageTexture(kImage3Binding, image3, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
5071 EXPECT_GL_NO_ERROR();
5072
5073 glDispatchCompute(1, 1, 1);
5074 EXPECT_GL_NO_ERROR();
5075
5076 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5077
5078 // read back
5079 const GLuint *ptr = reinterpret_cast<const GLuint *>(
5080 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kOutputInitData), GL_MAP_READ_BIT));
5081 EXPECT_EQ(*ptr,
5082 kImage1Data * kImage1Units + kImage2Data * kImage2Units + kImage3Data * kImage3Units);
5083 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
5084 }
5085
5086 // Test that arrays of arrays of images of r32f format work when passed to functions.
TEST_P(GLSLTest_ES31,ArraysOfArraysOfR32fImages)5087 TEST_P(GLSLTest_ES31, ArraysOfArraysOfR32fImages)
5088 {
5089 // Skip if GL_OES_shader_image_atomic is not enabled.
5090 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_image_atomic"));
5091
5092 // http://anglebug.com/5072
5093 ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
5094
5095 // Fails on D3D due to mistranslation.
5096 ANGLE_SKIP_TEST_IF(IsD3D());
5097
5098 // Fails on Android on GLES.
5099 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
5100
5101 // http://anglebug.com/5353
5102 ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGL());
5103
5104 GLint maxComputeImageUniforms;
5105 glGetIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &maxComputeImageUniforms);
5106 ANGLE_SKIP_TEST_IF(maxComputeImageUniforms < 7);
5107
5108 constexpr char kComputeShader[] = R"(#version 310 es
5109 #extension GL_OES_shader_image_atomic : require
5110
5111 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
5112 layout(binding = 0, r32f) uniform highp image2D image1[2][3];
5113 layout(binding = 6, r32f) uniform highp image2D image2;
5114
5115 void testFunction(highp image2D imageOut[2][3])
5116 {
5117 // image1 is an array of 1x1 images.
5118 // image2 is a 1x4 image with the following data:
5119 //
5120 // (0, 0): 234.5
5121 // (0, 1): 4.0
5122 // (0, 2): 456.0
5123 // (0, 3): 987.0
5124
5125
5126 // Write to [0][0]
5127 imageStore(imageOut[0][0], ivec2(0, 0), vec4(1234.5));
5128
5129 // Write to [0][1]
5130 imageStore(imageOut[0][1], ivec2(0, 0), imageLoad(image2, ivec2(0, 0)));
5131
5132 // Write to [0][2]
5133 imageStore(imageOut[0][2], ivec2(0, 0), vec4(imageSize(image2).y));
5134
5135 // Write to [1][0]
5136 imageStore(imageOut[1][0], ivec2(0,
5137 imageSize(image2).y - int(imageLoad(image2, ivec2(0, 1)).x)
5138 ), vec4(678.0));
5139
5140 // Write to [1][1]
5141 imageStore(imageOut[1][1], ivec2(0, 0),
5142 vec4(imageAtomicExchange(image2, ivec2(0, 2), 135.0)));
5143
5144 // Write to [1][2]
5145 imageStore(imageOut[1][2], ivec2(0, 0),
5146 imageLoad(image2, ivec2(imageSize(image2).x - 1, 3)));
5147 }
5148
5149 void main(void)
5150 {
5151 testFunction(image1);
5152 })";
5153 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
5154 EXPECT_GL_NO_ERROR();
5155
5156 glUseProgram(program);
5157
5158 constexpr GLsizei kImageRows = 2;
5159 constexpr GLsizei kImageCols = 3;
5160 constexpr GLfloat kImageData = 0;
5161 GLTexture images[kImageRows][kImageCols];
5162 for (size_t row = 0; row < kImageRows; row++)
5163 {
5164 for (size_t col = 0; col < kImageCols; col++)
5165 {
5166 glBindTexture(GL_TEXTURE_2D, images[row][col]);
5167 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, 1, 1);
5168 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED, GL_FLOAT, &kImageData);
5169 glBindImageTexture(row * kImageCols + col, images[row][col], 0, GL_FALSE, 0,
5170 GL_READ_WRITE, GL_R32F);
5171 EXPECT_GL_NO_ERROR();
5172 }
5173 }
5174
5175 constexpr GLsizei kImage2Size = 4;
5176 constexpr std::array<GLfloat, kImage2Size> kImage2Data = {
5177 234.5f,
5178 4.0f,
5179 456.0f,
5180 987.0f,
5181 };
5182 GLTexture image2;
5183 glBindTexture(GL_TEXTURE_2D, image2);
5184 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, 1, kImage2Size);
5185 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, kImage2Size, GL_RED, GL_FLOAT, kImage2Data.data());
5186 glBindImageTexture(6, image2, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
5187 EXPECT_GL_NO_ERROR();
5188
5189 glDispatchCompute(1, 1, 1);
5190 EXPECT_GL_NO_ERROR();
5191
5192 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5193
5194 // Verify the previous dispatch with another dispatch
5195 constexpr char kVerifyShader[] = R"(#version 310 es
5196 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
5197 layout(binding = 0, r32f) uniform highp readonly image2D image1[2][3];
5198 layout(binding = 6, r32f) uniform highp readonly image2D image2;
5199 layout(binding = 0, std430) buffer Output {
5200 float image2Data[4];
5201 float image1Data[6];
5202 } outbuf;
5203
5204 void main(void)
5205 {
5206 for (int i = 0; i < 4; ++i)
5207 {
5208 outbuf.image2Data[i] = imageLoad(image2, ivec2(0, i)).x;
5209 }
5210 outbuf.image1Data[0] = imageLoad(image1[0][0], ivec2(0, 0)).x;
5211 outbuf.image1Data[1] = imageLoad(image1[0][1], ivec2(0, 0)).x;
5212 outbuf.image1Data[2] = imageLoad(image1[0][2], ivec2(0, 0)).x;
5213 outbuf.image1Data[3] = imageLoad(image1[1][0], ivec2(0, 0)).x;
5214 outbuf.image1Data[4] = imageLoad(image1[1][1], ivec2(0, 0)).x;
5215 outbuf.image1Data[5] = imageLoad(image1[1][2], ivec2(0, 0)).x;
5216 })";
5217 ANGLE_GL_COMPUTE_PROGRAM(verifyProgram, kVerifyShader);
5218 EXPECT_GL_NO_ERROR();
5219
5220 glUseProgram(verifyProgram);
5221
5222 constexpr std::array<GLfloat, kImage2Size + kImageRows * kImageCols> kOutputInitData = {};
5223 GLBuffer outputBuffer;
5224 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
5225 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kOutputInitData), kOutputInitData.data(),
5226 GL_STATIC_DRAW);
5227 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, outputBuffer);
5228 EXPECT_GL_NO_ERROR();
5229
5230 glDispatchCompute(1, 1, 1);
5231 EXPECT_GL_NO_ERROR();
5232
5233 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5234
5235 // Verify
5236 const GLfloat *ptr = reinterpret_cast<const GLfloat *>(
5237 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kOutputInitData), GL_MAP_READ_BIT));
5238
5239 EXPECT_EQ(ptr[0], kImage2Data[0]);
5240 EXPECT_EQ(ptr[1], kImage2Data[1]);
5241 EXPECT_NEAR(ptr[2], 135.0f, 0.0001f);
5242 EXPECT_EQ(ptr[3], kImage2Data[3]);
5243
5244 EXPECT_NEAR(ptr[4], 1234.5f, 0.0001f);
5245 EXPECT_NEAR(ptr[5], kImage2Data[0], 0.0001f);
5246 EXPECT_NEAR(ptr[6], kImage2Size, 0.0001f);
5247 EXPECT_NEAR(ptr[7], 678.0f, 0.0001f);
5248 EXPECT_NEAR(ptr[8], kImage2Data[2], 0.0001f);
5249 EXPECT_NEAR(ptr[9], kImage2Data[3], 0.0001f);
5250
5251 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
5252 }
5253
5254 // Check that imageLoad gives the correct color after clearing the texture -- anglebug.com/7355
TEST_P(GLSLTest_ES31,ImageLoadAfterClear)5255 TEST_P(GLSLTest_ES31, ImageLoadAfterClear)
5256 {
5257 ANGLE_GL_PROGRAM(program,
5258 R"(#version 310 es
5259 precision highp float;
5260 void main()
5261 {
5262 gl_Position.x = ((gl_VertexID & 1) == 0 ? -1.0 : 1.0);
5263 gl_Position.y = ((gl_VertexID & 2) == 0 ? -1.0 : 1.0);
5264 gl_Position.zw = vec2(0, 1);
5265 })",
5266
5267 R"(#version 310 es
5268 precision highp float;
5269 layout(binding=0, rgba8) readonly highp uniform image2D img;
5270 out vec4 fragColor;
5271 void main()
5272 {
5273 ivec2 imgcoord = ivec2(floor(gl_FragCoord.xy));
5274 fragColor = vec4(1, 0, 0, 0) + imageLoad(img, imgcoord);
5275 })");
5276 ASSERT_TRUE(program.valid());
5277 glUseProgram(program);
5278
5279 GLTexture tex;
5280 glBindTexture(GL_TEXTURE_2D, tex);
5281 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, getWindowWidth(), getWindowHeight());
5282 glBindImageTexture(0, tex, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
5283
5284 // Clear the texture to green.
5285 GLFramebuffer fbo;
5286 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5287 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
5288 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5289 glClearColor(0, 1, 0, 1);
5290 glClear(GL_COLOR_BUFFER_BIT);
5291 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_FRAMEBUFFER_BARRIER_BIT);
5292
5293 // Draw the texture via imageLoad, plus red, into the main framebuffer. Make sure the texture
5294 // was still green. (green + red == yellow.)
5295 glBindFramebuffer(GL_FRAMEBUFFER, 0);
5296 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5297 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5298
5299 EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::yellow);
5300 ASSERT_GL_NO_ERROR();
5301 }
5302
5303 // Check that writeonly image2D handles can be passed as function args.
TEST_P(GLSLTest_ES31,WriteOnlyImage2DAsFunctionArg)5304 TEST_P(GLSLTest_ES31, WriteOnlyImage2DAsFunctionArg)
5305 {
5306 // Create an image.
5307 GLTexture tex;
5308 glBindTexture(GL_TEXTURE_2D, tex);
5309 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, getWindowWidth(), getWindowHeight());
5310
5311 // Clear the image to red.
5312 GLFramebuffer fbo;
5313 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5314 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
5315 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5316
5317 glClearColor(1, 0, 0, 1);
5318 glClear(GL_COLOR_BUFFER_BIT);
5319 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5320
5321 const char kVS[] = R"(#version 310 es
5322 precision highp float;
5323 void main()
5324 {
5325 gl_Position.x = ((gl_VertexID & 1) == 0 ? -1.0 : 1.0);
5326 gl_Position.y = ((gl_VertexID & 2) == 0 ? -1.0 : 1.0);
5327 gl_Position.zw = vec2(0, 1);
5328 })";
5329
5330 const char kFS[] = R"(#version 310 es
5331 precision highp float;
5332 layout(binding=0, rgba8) writeonly highp uniform image2D uniformImage;
5333 void store(writeonly highp image2D img, vec4 color)
5334 {
5335 ivec2 imgcoord = ivec2(floor(gl_FragCoord.xy));
5336 imageStore(img, imgcoord, color);
5337 }
5338 void main()
5339 {
5340 store(uniformImage, vec4(1, 1, 0, 1));
5341 })";
5342
5343 // Store yellow to the image.
5344 ANGLE_GL_PROGRAM(program, kVS, kFS);
5345 glUseProgram(program);
5346
5347 glBindFramebuffer(GL_FRAMEBUFFER, 0);
5348 glBindImageTexture(0, tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
5349 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5350 glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
5351
5352 // Check that the image is yellow.
5353 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5354 EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::yellow);
5355 ASSERT_GL_NO_ERROR();
5356 }
5357
5358 // Check that readonly image2D handles can be passed as function args.
TEST_P(GLSLTest_ES31,ReadOnlyImage2DAsFunctionArg)5359 TEST_P(GLSLTest_ES31, ReadOnlyImage2DAsFunctionArg)
5360 {
5361 const int w = getWindowWidth();
5362 const int h = getWindowHeight();
5363
5364 // Create an image.
5365 GLTexture tex;
5366 glBindTexture(GL_TEXTURE_2D, tex);
5367 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, w, h);
5368
5369 const std::vector<GLColor> kInitData(w * h, GLColor::red);
5370 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, kInitData.data());
5371
5372 // Create a framebuffer.
5373 GLTexture color;
5374 glBindTexture(GL_TEXTURE_2D, color);
5375 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, w, h);
5376
5377 GLFramebuffer fbo;
5378 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5379 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
5380 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5381
5382 // Initialize the framebuffer with the contents of the texture.
5383 glClearColor(0, 0, 0, 0);
5384 glClear(GL_COLOR_BUFFER_BIT);
5385
5386 const char kVS[] = R"(#version 310 es
5387 precision highp float;
5388 void main()
5389 {
5390 gl_Position.x = ((gl_VertexID & 1) == 0 ? -1.0 : 1.0);
5391 gl_Position.y = ((gl_VertexID & 2) == 0 ? -1.0 : 1.0);
5392 gl_Position.zw = vec2(0, 1);
5393 })";
5394
5395 const char kFS[] = R"(#version 310 es
5396 precision highp float;
5397 layout(binding=0, rgba8) readonly highp uniform image2D uniformImage;
5398 out vec4 color;
5399 vec4 load(readonly highp image2D img)
5400 {
5401 ivec2 imgcoord = ivec2(floor(gl_FragCoord.xy));
5402 return imageLoad(img, imgcoord);
5403 }
5404 void main()
5405 {
5406 color = load(uniformImage);
5407 })";
5408
5409 ANGLE_GL_PROGRAM(program, kVS, kFS);
5410 glUseProgram(program);
5411
5412 glBindImageTexture(0, tex, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
5413 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5414
5415 // Check that the framebuffer is red.
5416 EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::red);
5417 ASSERT_GL_NO_ERROR();
5418 }
5419
5420 // Check that the volatile keyword combined with memoryBarrierImage() allow load/store from
5421 // different aliases of the same image -- anglebug.com/7343
5422 //
5423 // ES 3.1 requires most image formats to be either readonly or writeonly. (It appears that this
5424 // limitation exists due to atomics, since we still have the volatile keyword and the built-in
5425 // memoryBarrierImage(), which ought to allow us to load and store different aliases of the same
5426 // image.) To test this, we create two aliases of the same image -- one for reading and one for
5427 // writing.
TEST_P(GLSLTest_ES31,AliasedLoadStore)5428 TEST_P(GLSLTest_ES31, AliasedLoadStore)
5429 {
5430
5431 GLTexture tex;
5432 glBindTexture(GL_TEXTURE_2D, tex);
5433 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, getWindowWidth(), getWindowHeight());
5434
5435 GLFramebuffer fbo;
5436 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5437 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
5438 glClearColor(1, 0, 0, 1);
5439 glClear(GL_COLOR_BUFFER_BIT);
5440 glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5441
5442 ANGLE_GL_PROGRAM(program,
5443
5444 R"(#version 310 es
5445 precision highp float;
5446 void main()
5447 {
5448 gl_Position.x = ((gl_VertexID & 1) == 0 ? -1.0 : 1.0);
5449 gl_Position.y = ((gl_VertexID & 2) == 0 ? -1.0 : 1.0);
5450 gl_Position.zw = vec2(0, 1);
5451 })",
5452
5453 R"(#version 310 es
5454 precision highp float;
5455 layout(binding=0, rgba8) volatile readonly highp uniform image2D img_r;
5456 layout(binding=0, rgba8) volatile writeonly highp uniform image2D img_w;
5457 uniform vec4 drawColor;
5458 void main()
5459 {
5460 ivec2 coord = ivec2(floor(gl_FragCoord.xy));
5461 vec4 oldval = imageLoad(img_r, coord);
5462 memoryBarrierImage();
5463 imageStore(img_w, coord, oldval + drawColor);
5464 })");
5465
5466 ASSERT_TRUE(program.valid());
5467 glUseProgram(program);
5468 GLint drawColorLocation = glGetUniformLocation(program, "drawColor");
5469
5470 // Tell the driver the binding is GL_READ_WRITE, since it will be referenced by two image2Ds:
5471 // one readeonly and one writeonly.
5472 glBindImageTexture(0, tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8);
5473
5474 glBindFramebuffer(GL_FRAMEBUFFER, 0);
5475 glUniform4f(drawColorLocation, 0, 1, 0, 0);
5476 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5477 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5478
5479 // Ensure the cleared color was loaded before we stored.
5480 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5481 EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::yellow);
5482
5483 ASSERT_GL_NO_ERROR();
5484
5485 // Now make two draws to ensure the imageStore is coherent.
5486 glClear(GL_COLOR_BUFFER_BIT);
5487 glBindFramebuffer(GL_FRAMEBUFFER, 0);
5488 glUniform4f(drawColorLocation, 0, 1, 0, 0);
5489 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5490 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5491 glUniform4f(drawColorLocation, 0, 0, 1, 0);
5492 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5493 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5494
5495 // Ensure the first imageStore was loaded by the second imageLoad.
5496 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5497 EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::white);
5498
5499 ASSERT_GL_NO_ERROR();
5500 }
5501
5502 // Test that structs containing arrays of samplers work as expected.
TEST_P(GLSLTest_ES31,StructArraySampler)5503 TEST_P(GLSLTest_ES31, StructArraySampler)
5504 {
5505 constexpr char kFS[] =
5506 "#version 310 es\n"
5507 "precision mediump float;\n"
5508 "out vec4 my_FragColor;\n"
5509 "struct Data { mediump sampler2D data[2]; };\n"
5510 "uniform Data test;\n"
5511 "void main() {\n"
5512 " my_FragColor = vec4(texture(test.data[0], vec2(0.0, 0.0)).rg,\n"
5513 " texture(test.data[1], vec2(0.0, 0.0)).rg);\n"
5514 "}\n";
5515
5516 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5517 glUseProgram(program);
5518 GLTexture textures[2];
5519 GLColor expected = MakeGLColor(32, 64, 96, 255);
5520 GLubyte data[6] = {}; // Two bytes of padding, so that texture can be initialized with 4 bytes
5521 memcpy(data, expected.data(), sizeof(expected));
5522 for (int i = 0; i < 2; i++)
5523 {
5524 glActiveTexture(GL_TEXTURE0 + i);
5525 glBindTexture(GL_TEXTURE_2D, textures[i]);
5526 // Each element provides two components.
5527 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data + 2 * i);
5528 std::stringstream uniformName;
5529 uniformName << "test.data[" << i << "]";
5530 // Then send it as a uniform
5531 GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
5532 // The uniform should be active.
5533 EXPECT_NE(uniformLocation, -1);
5534 glUniform1i(uniformLocation, i);
5535 }
5536 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
5537 EXPECT_PIXEL_COLOR_EQ(0, 0, expected);
5538 }
5539
5540 // Test that arrays of arrays of samplers inside structs work as expected.
TEST_P(GLSLTest_ES31,StructArrayArraySampler)5541 TEST_P(GLSLTest_ES31, StructArrayArraySampler)
5542 {
5543 constexpr char kFS[] =
5544 "#version 310 es\n"
5545 "precision mediump float;\n"
5546 "out vec4 my_FragColor;\n"
5547 "struct Data { mediump isampler2D data[2][2]; };\n"
5548 "uniform Data test;\n"
5549 "void main() {\n"
5550 " bool passed = true;\n"
5551 "#define DO_CHECK(i,j) \\\n"
5552 " if (texture(test.data[i][j], vec2(0.0, 0.0)) != ivec4(i + 1, j + 1, 0, 1)) { \\\n"
5553 " passed = false; \\\n"
5554 " }\n"
5555 " DO_CHECK(0, 0)\n"
5556 " DO_CHECK(0, 1)\n"
5557 " DO_CHECK(1, 0)\n"
5558 " DO_CHECK(1, 1)\n"
5559 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
5560 "}\n";
5561
5562 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5563 glUseProgram(program);
5564 GLTexture textures[2][2];
5565 for (int i = 0; i < 2; i++)
5566 {
5567 for (int j = 0; j < 2; j++)
5568 {
5569 // First generate the texture
5570 int textureUnit = i * 2 + j;
5571 glActiveTexture(GL_TEXTURE0 + textureUnit);
5572 glBindTexture(GL_TEXTURE_2D, textures[i][j]);
5573 GLint texData[2] = {i + 1, j + 1};
5574 glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32I, 1, 1, 0, GL_RG_INTEGER, GL_INT, &texData[0]);
5575 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5576 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5577 // Then send it as a uniform
5578 std::stringstream uniformName;
5579 uniformName << "test.data[" << i << "][" << j << "]";
5580 GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
5581 // All array indices should be used.
5582 EXPECT_NE(uniformLocation, -1);
5583 glUniform1i(uniformLocation, textureUnit);
5584 }
5585 }
5586 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
5587 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5588 }
5589
5590 // Test that an array of structs with arrays of arrays of samplers works.
TEST_P(GLSLTest_ES31,ArrayStructArrayArraySampler)5591 TEST_P(GLSLTest_ES31, ArrayStructArrayArraySampler)
5592 {
5593 GLint numTextures;
5594 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
5595 ANGLE_SKIP_TEST_IF(numTextures < 2 * (2 * 2 + 2 * 2));
5596 constexpr char kFS[] =
5597 "#version 310 es\n"
5598 "precision mediump float;\n"
5599 "out vec4 my_FragColor;\n"
5600 "struct Data { mediump isampler2D data0[2][2]; mediump isampler2D data1[2][2]; };\n"
5601 "uniform Data test[2];\n"
5602 "void main() {\n"
5603 " bool passed = true;\n"
5604 "#define DO_CHECK_ikl(i,k,l) \\\n"
5605 " if (texture(test[i].data0[k][l], vec2(0.0, 0.0)) != ivec4(i, 0, k, l)+1) { \\\n"
5606 " passed = false; \\\n"
5607 " } \\\n"
5608 " if (texture(test[i].data1[k][l], vec2(0.0, 0.0)) != ivec4(i, 1, k, l)+1) { \\\n"
5609 " passed = false; \\\n"
5610 " }\n"
5611 "#define DO_CHECK_ik(i,k) \\\n"
5612 " DO_CHECK_ikl(i, k, 0) \\\n"
5613 " DO_CHECK_ikl(i, k, 1)\n"
5614 "#define DO_CHECK_i(i) \\\n"
5615 " DO_CHECK_ik(i, 0) \\\n"
5616 " DO_CHECK_ik(i, 1)\n"
5617 " DO_CHECK_i(0)\n"
5618 " DO_CHECK_i(1)\n"
5619 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
5620 "}\n";
5621
5622 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5623 glUseProgram(program);
5624 GLTexture textures[2][2][2][2];
5625 for (int i = 0; i < 2; i++)
5626 {
5627 for (int j = 0; j < 2; j++)
5628 {
5629 for (int k = 0; k < 2; k++)
5630 {
5631 for (int l = 0; l < 2; l++)
5632 {
5633 // First generate the texture
5634 int textureUnit = l + 2 * (k + 2 * (j + 2 * i));
5635 glActiveTexture(GL_TEXTURE0 + textureUnit);
5636 glBindTexture(GL_TEXTURE_2D, textures[i][j][k][l]);
5637 GLint texData[4] = {i + 1, j + 1, k + 1, l + 1};
5638 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT,
5639 &texData[0]);
5640 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5641 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5642 // Then send it as a uniform
5643 std::stringstream uniformName;
5644 uniformName << "test[" << i << "].data" << j << "[" << k << "][" << l << "]";
5645 GLint uniformLocation =
5646 glGetUniformLocation(program, uniformName.str().c_str());
5647 // All array indices should be used.
5648 EXPECT_NE(uniformLocation, -1);
5649 glUniform1i(uniformLocation, textureUnit);
5650 }
5651 }
5652 }
5653 }
5654 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
5655 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5656 }
5657
5658 // Test that a complex chain of structs and arrays of samplers works as expected.
TEST_P(GLSLTest_ES31,ComplexStructArraySampler)5659 TEST_P(GLSLTest_ES31, ComplexStructArraySampler)
5660 {
5661 GLint numTextures;
5662 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
5663 ANGLE_SKIP_TEST_IF(numTextures < 2 * 3 * (2 + 3));
5664 constexpr char kFS[] =
5665 "#version 310 es\n"
5666 "precision mediump float;\n"
5667 "out vec4 my_FragColor;\n"
5668 "struct Data { mediump isampler2D data0[2]; mediump isampler2D data1[3]; };\n"
5669 "uniform Data test[2][3];\n"
5670 "const vec2 ZERO = vec2(0.0, 0.0);\n"
5671 "void main() {\n"
5672 " bool passed = true;\n"
5673 "#define DO_CHECK_INNER0(i,j,l) \\\n"
5674 " if (texture(test[i][j].data0[l], ZERO) != ivec4(i, j, 0, l) + 1) { \\\n"
5675 " passed = false; \\\n"
5676 " }\n"
5677 "#define DO_CHECK_INNER1(i,j,l) \\\n"
5678 " if (texture(test[i][j].data1[l], ZERO) != ivec4(i, j, 1, l) + 1) { \\\n"
5679 " passed = false; \\\n"
5680 " }\n"
5681 "#define DO_CHECK(i,j) \\\n"
5682 " DO_CHECK_INNER0(i, j, 0) \\\n"
5683 " DO_CHECK_INNER0(i, j, 1) \\\n"
5684 " DO_CHECK_INNER1(i, j, 0) \\\n"
5685 " DO_CHECK_INNER1(i, j, 1) \\\n"
5686 " DO_CHECK_INNER1(i, j, 2)\n"
5687 " DO_CHECK(0, 0)\n"
5688 " DO_CHECK(0, 1)\n"
5689 " DO_CHECK(0, 2)\n"
5690 " DO_CHECK(1, 0)\n"
5691 " DO_CHECK(1, 1)\n"
5692 " DO_CHECK(1, 2)\n"
5693 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
5694 "}\n";
5695
5696 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5697 glUseProgram(program);
5698 struct Data
5699 {
5700 GLTexture data1[2];
5701 GLTexture data2[3];
5702 };
5703 Data textures[2][3];
5704 for (int i = 0; i < 2; i++)
5705 {
5706 for (int j = 0; j < 3; j++)
5707 {
5708 GLTexture *arrays[] = {&textures[i][j].data1[0], &textures[i][j].data2[0]};
5709 size_t arrayLengths[] = {2, 3};
5710 size_t arrayOffsets[] = {0, 2};
5711 size_t totalArrayLength = 5;
5712 for (int k = 0; k < 2; k++)
5713 {
5714 GLTexture *array = arrays[k];
5715 size_t arrayLength = arrayLengths[k];
5716 size_t arrayOffset = arrayOffsets[k];
5717 for (int l = 0; l < static_cast<int>(arrayLength); l++)
5718 {
5719 // First generate the texture
5720 int textureUnit = arrayOffset + l + totalArrayLength * (j + 3 * i);
5721 glActiveTexture(GL_TEXTURE0 + textureUnit);
5722 glBindTexture(GL_TEXTURE_2D, array[l]);
5723 GLint texData[4] = {i + 1, j + 1, k + 1, l + 1};
5724 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT,
5725 &texData[0]);
5726 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5727 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5728 // Then send it as a uniform
5729 std::stringstream uniformName;
5730 uniformName << "test[" << i << "][" << j << "].data" << k << "[" << l << "]";
5731 GLint uniformLocation =
5732 glGetUniformLocation(program, uniformName.str().c_str());
5733 // All array indices should be used.
5734 EXPECT_NE(uniformLocation, -1);
5735 glUniform1i(uniformLocation, textureUnit);
5736 }
5737 }
5738 }
5739 }
5740 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
5741 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5742 }
5743
TEST_P(GLSLTest_ES31,ArraysOfArraysStructDifferentTypesSampler)5744 TEST_P(GLSLTest_ES31, ArraysOfArraysStructDifferentTypesSampler)
5745 {
5746 GLint numTextures;
5747 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
5748 ANGLE_SKIP_TEST_IF(numTextures < 3 * (2 + 2));
5749 constexpr char kFS[] =
5750 "#version 310 es\n"
5751 "precision mediump float;\n"
5752 "out vec4 my_FragColor;\n"
5753 "struct Data { mediump isampler2D data0[2]; mediump sampler2D data1[2]; };\n"
5754 "uniform Data test[3];\n"
5755 "ivec4 f2i(vec4 x) { return ivec4(x * 4.0 + 0.5); }"
5756 "void main() {\n"
5757 " bool passed = true;\n"
5758 "#define DO_CHECK_ik(i,k) \\\n"
5759 " if (texture(test[i].data0[k], vec2(0.0, 0.0)) != ivec4(i, 0, k, 0)+1) { \\\n"
5760 " passed = false; \\\n"
5761 " } \\\n"
5762 " if (f2i(texture(test[i].data1[k], vec2(0.0, 0.0))) != ivec4(i, 1, k, 0)+1) { \\\n"
5763 " passed = false; \\\n"
5764 " }\n"
5765 "#define DO_CHECK_i(i) \\\n"
5766 " DO_CHECK_ik(i, 0) \\\n"
5767 " DO_CHECK_ik(i, 1)\n"
5768 " DO_CHECK_i(0)\n"
5769 " DO_CHECK_i(1)\n"
5770 " DO_CHECK_i(2)\n"
5771 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
5772 "}\n";
5773
5774 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5775 glUseProgram(program);
5776 GLTexture textures[3][2][2];
5777 for (int i = 0; i < 3; i++)
5778 {
5779 for (int j = 0; j < 2; j++)
5780 {
5781 for (int k = 0; k < 2; k++)
5782 {
5783 // First generate the texture
5784 int textureUnit = k + 2 * (j + 2 * i);
5785 glActiveTexture(GL_TEXTURE0 + textureUnit);
5786 glBindTexture(GL_TEXTURE_2D, textures[i][j][k]);
5787 GLint texData[4] = {i + 1, j + 1, k + 1, 1};
5788 GLubyte texDataFloat[4] = {static_cast<GLubyte>((i + 1) * 64 - 1),
5789 static_cast<GLubyte>((j + 1) * 64 - 1),
5790 static_cast<GLubyte>((k + 1) * 64 - 1), 64};
5791 if (j == 0)
5792 {
5793 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT,
5794 &texData[0]);
5795 }
5796 else
5797 {
5798 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5799 &texDataFloat[0]);
5800 }
5801 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5802 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5803 // Then send it as a uniform
5804 std::stringstream uniformName;
5805 uniformName << "test[" << i << "].data" << j << "[" << k << "]";
5806 GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
5807 // All array indices should be used.
5808 EXPECT_NE(uniformLocation, -1);
5809 glUniform1i(uniformLocation, textureUnit);
5810 }
5811 }
5812 }
5813 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
5814 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5815 }
5816
5817 // Test that arrays of arrays of samplers as parameters works as expected.
TEST_P(GLSLTest_ES31,ParameterArraysOfArraysSampler)5818 TEST_P(GLSLTest_ES31, ParameterArraysOfArraysSampler)
5819 {
5820 // anglebug.com/3832 - no sampler array params on Android
5821 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
5822
5823 constexpr char kFS[] =
5824 "#version 310 es\n"
5825 "precision mediump float;\n"
5826 "out vec4 my_FragColor;\n"
5827 "uniform mediump isampler2D test[2][3];\n"
5828 "const vec2 ZERO = vec2(0.0, 0.0);\n"
5829 "\n"
5830 "bool check(mediump isampler2D data[2][3]);\n"
5831 "bool check(mediump isampler2D data[2][3]) {\n"
5832 "#define DO_CHECK(i,j) \\\n"
5833 " if (texture(data[i][j], ZERO) != ivec4(i+1, j+1, 0, 1)) { \\\n"
5834 " return false; \\\n"
5835 " }\n"
5836 " DO_CHECK(0, 0)\n"
5837 " DO_CHECK(0, 1)\n"
5838 " DO_CHECK(0, 2)\n"
5839 " DO_CHECK(1, 0)\n"
5840 " DO_CHECK(1, 1)\n"
5841 " DO_CHECK(1, 2)\n"
5842 " return true;\n"
5843 "}\n"
5844 "void main() {\n"
5845 " bool passed = check(test);\n"
5846 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
5847 "}\n";
5848
5849 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5850 glUseProgram(program);
5851 GLTexture textures[2][3];
5852 for (int i = 0; i < 2; i++)
5853 {
5854 for (int j = 0; j < 3; j++)
5855 {
5856 // First generate the texture
5857 int textureUnit = i * 3 + j;
5858 glActiveTexture(GL_TEXTURE0 + textureUnit);
5859 glBindTexture(GL_TEXTURE_2D, textures[i][j]);
5860 GLint texData[2] = {i + 1, j + 1};
5861 glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32I, 1, 1, 0, GL_RG_INTEGER, GL_INT, &texData[0]);
5862 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5863 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5864 // Then send it as a uniform
5865 std::stringstream uniformName;
5866 uniformName << "test[" << i << "][" << j << "]";
5867 GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
5868 // All array indices should be used.
5869 EXPECT_NE(uniformLocation, -1);
5870 glUniform1i(uniformLocation, textureUnit);
5871 }
5872 }
5873 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
5874 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5875 }
5876
5877 // Test that structs with arrays of arrays of samplers as parameters works as expected.
TEST_P(GLSLTest_ES31,ParameterStructArrayArraySampler)5878 TEST_P(GLSLTest_ES31, ParameterStructArrayArraySampler)
5879 {
5880 // anglebug.com/3832 - no sampler array params on Android
5881 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
5882
5883 constexpr char kFS[] =
5884 "#version 310 es\n"
5885 "precision mediump float;\n"
5886 "out vec4 my_FragColor;\n"
5887 "struct Data { mediump isampler2D data[2][3]; };\n"
5888 "uniform Data test;\n"
5889 "const vec2 ZERO = vec2(0.0, 0.0);\n"
5890 "\n"
5891 "bool check(Data data) {\n"
5892 "#define DO_CHECK(i,j) \\\n"
5893 " if (texture(data.data[i][j], ZERO) != ivec4(i+1, j+1, 0, 1)) { \\\n"
5894 " return false; \\\n"
5895 " }\n"
5896 " DO_CHECK(0, 0)\n"
5897 " DO_CHECK(0, 1)\n"
5898 " DO_CHECK(0, 2)\n"
5899 " DO_CHECK(1, 0)\n"
5900 " DO_CHECK(1, 1)\n"
5901 " DO_CHECK(1, 2)\n"
5902 " return true;\n"
5903 "}\n"
5904 "void main() {\n"
5905 " bool passed = check(test);\n"
5906 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
5907 "}\n";
5908
5909 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5910 glUseProgram(program);
5911 GLTexture textures[2][3];
5912 for (int i = 0; i < 2; i++)
5913 {
5914 for (int j = 0; j < 3; j++)
5915 {
5916 // First generate the texture
5917 int textureUnit = i * 3 + j;
5918 glActiveTexture(GL_TEXTURE0 + textureUnit);
5919 glBindTexture(GL_TEXTURE_2D, textures[i][j]);
5920 GLint texData[2] = {i + 1, j + 1};
5921 glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32I, 1, 1, 0, GL_RG_INTEGER, GL_INT, &texData[0]);
5922 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5923 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5924 // Then send it as a uniform
5925 std::stringstream uniformName;
5926 uniformName << "test.data[" << i << "][" << j << "]";
5927 GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
5928 // All array indices should be used.
5929 EXPECT_NE(uniformLocation, -1);
5930 glUniform1i(uniformLocation, textureUnit);
5931 }
5932 }
5933 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
5934 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5935 }
5936
5937 // Test that arrays of arrays of structs with arrays of arrays of samplers
5938 // as parameters works as expected.
TEST_P(GLSLTest_ES31,ParameterArrayArrayStructArrayArraySampler)5939 TEST_P(GLSLTest_ES31, ParameterArrayArrayStructArrayArraySampler)
5940 {
5941 // anglebug.com/3832 - no sampler array params on Android
5942 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
5943
5944 GLint numTextures;
5945 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
5946 ANGLE_SKIP_TEST_IF(numTextures < 3 * 2 * 2 * 2);
5947 constexpr char kFS[] =
5948 "#version 310 es\n"
5949 "precision mediump float;\n"
5950 "out vec4 my_FragColor;\n"
5951 "struct Data { mediump isampler2D data[2][2]; };\n"
5952 "uniform Data test[3][2];\n"
5953 "const vec2 ZERO = vec2(0.0, 0.0);\n"
5954 "\n"
5955 "bool check(Data data[3][2]) {\n"
5956 "#define DO_CHECK_ijkl(i,j,k,l) \\\n"
5957 " if (texture(data[i][j].data[k][l], ZERO) != ivec4(i, j, k, l) + 1) { \\\n"
5958 " return false; \\\n"
5959 " }\n"
5960 "#define DO_CHECK_ij(i,j) \\\n"
5961 " DO_CHECK_ijkl(i, j, 0, 0) \\\n"
5962 " DO_CHECK_ijkl(i, j, 0, 1) \\\n"
5963 " DO_CHECK_ijkl(i, j, 1, 0) \\\n"
5964 " DO_CHECK_ijkl(i, j, 1, 1)\n"
5965 " DO_CHECK_ij(0, 0)\n"
5966 " DO_CHECK_ij(1, 0)\n"
5967 " DO_CHECK_ij(2, 0)\n"
5968 " DO_CHECK_ij(0, 1)\n"
5969 " DO_CHECK_ij(1, 1)\n"
5970 " DO_CHECK_ij(2, 1)\n"
5971 " return true;\n"
5972 "}\n"
5973 "void main() {\n"
5974 " bool passed = check(test);\n"
5975 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
5976 "}\n";
5977
5978 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5979 glUseProgram(program);
5980 GLTexture textures[3][2][2][2];
5981 for (int i = 0; i < 3; i++)
5982 {
5983 for (int j = 0; j < 2; j++)
5984 {
5985 for (int k = 0; k < 2; k++)
5986 {
5987 for (int l = 0; l < 2; l++)
5988 {
5989 // First generate the texture
5990 int textureUnit = l + 2 * (k + 2 * (j + 2 * i));
5991 glActiveTexture(GL_TEXTURE0 + textureUnit);
5992 glBindTexture(GL_TEXTURE_2D, textures[i][j][k][l]);
5993 GLint texData[4] = {i + 1, j + 1, k + 1, l + 1};
5994 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT,
5995 &texData[0]);
5996 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5997 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5998 // Then send it as a uniform
5999 std::stringstream uniformName;
6000 uniformName << "test[" << i << "][" << j << "].data[" << k << "][" << l << "]";
6001 GLint uniformLocation =
6002 glGetUniformLocation(program, uniformName.str().c_str());
6003 // All array indices should be used.
6004 EXPECT_NE(uniformLocation, -1);
6005 glUniform1i(uniformLocation, textureUnit);
6006 }
6007 }
6008 }
6009 }
6010 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
6011 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6012 }
6013
6014 // Test that 3D arrays with sub-arrays passed as parameters works as expected.
TEST_P(GLSLTest_ES31,ParameterArrayArrayArraySampler)6015 TEST_P(GLSLTest_ES31, ParameterArrayArrayArraySampler)
6016 {
6017 GLint numTextures;
6018 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
6019 ANGLE_SKIP_TEST_IF(numTextures < 2 * 3 * 4 + 4);
6020
6021 // anglebug.com/3832 - no sampler array params on Android
6022 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
6023
6024 // http://anglebug.com/5546
6025 ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
6026
6027 constexpr char kFS[] =
6028 "#version 310 es\n"
6029 "precision mediump float;\n"
6030 "out vec4 my_FragColor;\n"
6031 "uniform mediump isampler2D test[2][3][4];\n"
6032 "uniform mediump isampler2D test2[4];\n"
6033 "const vec2 ZERO = vec2(0.0, 0.0);\n"
6034 "\n"
6035 "bool check1D(mediump isampler2D arr[4], int x, int y) {\n"
6036 " if (texture(arr[0], ZERO) != ivec4(x, y, 0, 0)+1) return false;\n"
6037 " if (texture(arr[1], ZERO) != ivec4(x, y, 1, 0)+1) return false;\n"
6038 " if (texture(arr[2], ZERO) != ivec4(x, y, 2, 0)+1) return false;\n"
6039 " if (texture(arr[3], ZERO) != ivec4(x, y, 3, 0)+1) return false;\n"
6040 " return true;\n"
6041 "}\n"
6042 "bool check2D(mediump isampler2D arr[3][4], int x) {\n"
6043 " if (!check1D(arr[0], x, 0)) return false;\n"
6044 " if (!check1D(arr[1], x, 1)) return false;\n"
6045 " if (!check1D(arr[2], x, 2)) return false;\n"
6046 " return true;\n"
6047 "}\n"
6048 "bool check3D(mediump isampler2D arr[2][3][4]) {\n"
6049 " if (!check2D(arr[0], 0)) return false;\n"
6050 " if (!check2D(arr[1], 1)) return false;\n"
6051 " return true;\n"
6052 "}\n"
6053 "void main() {\n"
6054 " bool passed = check3D(test) && check1D(test2, 7, 8);\n"
6055 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
6056 "}\n";
6057
6058 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
6059 glUseProgram(program);
6060 GLTexture textures1[2][3][4];
6061 GLTexture textures2[4];
6062 for (int i = 0; i < 2; i++)
6063 {
6064 for (int j = 0; j < 3; j++)
6065 {
6066 for (int k = 0; k < 4; k++)
6067 {
6068 // First generate the texture
6069 int textureUnit = k + 4 * (j + 3 * i);
6070 glActiveTexture(GL_TEXTURE0 + textureUnit);
6071 glBindTexture(GL_TEXTURE_2D, textures1[i][j][k]);
6072 GLint texData[3] = {i + 1, j + 1, k + 1};
6073 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32I, 1, 1, 0, GL_RGB_INTEGER, GL_INT,
6074 &texData[0]);
6075 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6076 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6077 // Then send it as a uniform
6078 std::stringstream uniformName;
6079 uniformName << "test[" << i << "][" << j << "][" << k << "]";
6080 GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
6081 // All array indices should be used.
6082 EXPECT_NE(uniformLocation, -1);
6083 glUniform1i(uniformLocation, textureUnit);
6084 }
6085 }
6086 }
6087 for (int k = 0; k < 4; k++)
6088 {
6089 // First generate the texture
6090 int textureUnit = 2 * 3 * 4 + k;
6091 glActiveTexture(GL_TEXTURE0 + textureUnit);
6092 glBindTexture(GL_TEXTURE_2D, textures2[k]);
6093 GLint texData[3] = {7 + 1, 8 + 1, k + 1};
6094 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32I, 1, 1, 0, GL_RGB_INTEGER, GL_INT, &texData[0]);
6095 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6096 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6097 // Then send it as a uniform
6098 std::stringstream uniformName;
6099 uniformName << "test2[" << k << "]";
6100 GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
6101 // All array indices should be used.
6102 EXPECT_NE(uniformLocation, -1);
6103 glUniform1i(uniformLocation, textureUnit);
6104 }
6105 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
6106 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6107 }
6108
6109 // Test that names do not collide when translating arrays of arrays of samplers.
TEST_P(GLSLTest_ES31,ArraysOfArraysNameCollisionSampler)6110 TEST_P(GLSLTest_ES31, ArraysOfArraysNameCollisionSampler)
6111 {
6112 ANGLE_SKIP_TEST_IF(IsVulkan()); // anglebug.com/3604 - rewriter can create name collisions
6113 GLint numTextures;
6114 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
6115 ANGLE_SKIP_TEST_IF(numTextures < 2 * 2 + 3 * 3 + 4 * 4);
6116 // anglebug.com/3832 - no sampler array params on Android
6117 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
6118 constexpr char kFS[] =
6119 "#version 310 es\n"
6120 "precision mediump sampler2D;\n"
6121 "precision mediump float;\n"
6122 "uniform sampler2D test_field1_field2[2][2];\n"
6123 "struct S1 { sampler2D field2[3][3]; }; uniform S1 test_field1;\n"
6124 "struct S2 { sampler2D field1_field2[4][4]; }; uniform S2 test;\n"
6125 "vec4 func1(sampler2D param_field1_field2[2][2],\n"
6126 " int param_field1_field2_offset,\n"
6127 " S1 param_field1,\n"
6128 " S2 param) {\n"
6129 " return vec4(0.0, 1.0, 0.0, 0.0);\n"
6130 "}\n"
6131 "out vec4 my_FragColor;\n"
6132 "void main() {\n"
6133 " my_FragColor = vec4(0.0, 0.0, 0.0, 1.0);\n"
6134 " my_FragColor += func1(test_field1_field2, 0, test_field1, test);\n"
6135 " vec2 uv = vec2(0.0);\n"
6136 " my_FragColor += texture(test_field1_field2[0][0], uv) +\n"
6137 " texture(test_field1.field2[0][0], uv) +\n"
6138 " texture(test.field1_field2[0][0], uv);\n"
6139 "}\n";
6140 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
6141 glActiveTexture(GL_TEXTURE0);
6142 GLTexture tex;
6143 glBindTexture(GL_TEXTURE_2D, tex);
6144 GLint zero = 0;
6145 glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 1, 1, 0, GL_RED, GL_UNSIGNED_BYTE, &zero);
6146 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
6147 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6148 }
6149
6150 // Test that regular arrays are unmodified.
TEST_P(GLSLTest_ES31,BasicTypeArrayAndArrayOfSampler)6151 TEST_P(GLSLTest_ES31, BasicTypeArrayAndArrayOfSampler)
6152 {
6153 constexpr char kFS[] =
6154 "#version 310 es\n"
6155 "precision mediump sampler2D;\n"
6156 "precision mediump float;\n"
6157 "uniform sampler2D sampler_array[2][2];\n"
6158 "uniform int array[3][2];\n"
6159 "vec4 func1(int param[2],\n"
6160 " int param2[3]) {\n"
6161 " return vec4(0.0, 1.0, 0.0, 0.0);\n"
6162 "}\n"
6163 "out vec4 my_FragColor;\n"
6164 "void main() {\n"
6165 " my_FragColor = texture(sampler_array[0][0], vec2(0.0));\n"
6166 " my_FragColor += func1(array[1], int[](1, 2, 3));\n"
6167 "}\n";
6168 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
6169 glActiveTexture(GL_TEXTURE0);
6170 GLTexture tex;
6171 glBindTexture(GL_TEXTURE_2D, tex);
6172 GLint zero = 0;
6173 glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 1, 1, 0, GL_RED, GL_UNSIGNED_BYTE, &zero);
6174 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
6175 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6176 }
6177
6178 // This test covers a bug (and associated workaround) with nested sampling operations in the HLSL
6179 // compiler DLL.
TEST_P(GLSLTest_ES3,NestedSamplingOperation)6180 TEST_P(GLSLTest_ES3, NestedSamplingOperation)
6181 {
6182 // This seems to be bugged on some version of Android. Might not affect the newest versions.
6183 // TODO(jmadill): Lift suppression when Chromium bots are upgraded.
6184 // Test skipped on Android because of bug with Nexus 5X.
6185 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
6186
6187 constexpr char kVS[] =
6188 "#version 300 es\n"
6189 "out vec2 texCoord;\n"
6190 "in vec2 position;\n"
6191 "void main()\n"
6192 "{\n"
6193 " gl_Position = vec4(position, 0, 1);\n"
6194 " texCoord = position * 0.5 + vec2(0.5);\n"
6195 "}\n";
6196
6197 constexpr char kSimpleFS[] =
6198 "#version 300 es\n"
6199 "in mediump vec2 texCoord;\n"
6200 "out mediump vec4 fragColor;\n"
6201 "void main()\n"
6202 "{\n"
6203 " fragColor = vec4(texCoord, 0, 1);\n"
6204 "}\n";
6205
6206 constexpr char kNestedFS[] =
6207 "#version 300 es\n"
6208 "uniform mediump sampler2D samplerA;\n"
6209 "uniform mediump sampler2D samplerB;\n"
6210 "in mediump vec2 texCoord;\n"
6211 "out mediump vec4 fragColor;\n"
6212 "void main ()\n"
6213 "{\n"
6214 " fragColor = texture(samplerB, texture(samplerA, texCoord).xy);\n"
6215 "}\n";
6216
6217 ANGLE_GL_PROGRAM(initProg, kVS, kSimpleFS);
6218 ANGLE_GL_PROGRAM(nestedProg, kVS, kNestedFS);
6219
6220 // Initialize a first texture with default texCoord data.
6221 GLTexture texA;
6222 glActiveTexture(GL_TEXTURE0);
6223 glBindTexture(GL_TEXTURE_2D, texA);
6224 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
6225 GL_UNSIGNED_BYTE, nullptr);
6226 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6227 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6228
6229 GLFramebuffer fbo;
6230 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6231 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texA, 0);
6232
6233 drawQuad(initProg, "position", 0.5f);
6234 ASSERT_GL_NO_ERROR();
6235
6236 // Initialize a second texture with a simple color pattern.
6237 GLTexture texB;
6238 glActiveTexture(GL_TEXTURE1);
6239 glBindTexture(GL_TEXTURE_2D, texB);
6240
6241 std::array<GLColor, 4> simpleColors = {
6242 {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
6243 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6244 simpleColors.data());
6245 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6246 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6247
6248 // Draw with the nested program, using the first texture to index the second.
6249 glBindFramebuffer(GL_FRAMEBUFFER, 0);
6250 glUseProgram(nestedProg);
6251 GLint samplerALoc = glGetUniformLocation(nestedProg, "samplerA");
6252 ASSERT_NE(-1, samplerALoc);
6253 glUniform1i(samplerALoc, 0);
6254 GLint samplerBLoc = glGetUniformLocation(nestedProg, "samplerB");
6255 ASSERT_NE(-1, samplerBLoc);
6256 glUniform1i(samplerBLoc, 1);
6257
6258 drawQuad(nestedProg, "position", 0.5f);
6259 ASSERT_GL_NO_ERROR();
6260
6261 // Compute four texel centers.
6262 Vector2 windowSize(getWindowWidth(), getWindowHeight());
6263 Vector2 quarterWindowSize = windowSize / 4;
6264 Vector2 ul = quarterWindowSize;
6265 Vector2 ur(windowSize.x() - quarterWindowSize.x(), quarterWindowSize.y());
6266 Vector2 ll(quarterWindowSize.x(), windowSize.y() - quarterWindowSize.y());
6267 Vector2 lr = windowSize - quarterWindowSize;
6268
6269 EXPECT_PIXEL_COLOR_EQ_VEC2(ul, simpleColors[0]);
6270 EXPECT_PIXEL_COLOR_EQ_VEC2(ur, simpleColors[1]);
6271 EXPECT_PIXEL_COLOR_EQ_VEC2(ll, simpleColors[2]);
6272 EXPECT_PIXEL_COLOR_EQ_VEC2(lr, simpleColors[3]);
6273 }
6274
6275 // Tests that using a constant declaration as the only statement in a for loop without curly braces
6276 // doesn't crash.
TEST_P(GLSLTest,ConstantStatementInForLoop)6277 TEST_P(GLSLTest, ConstantStatementInForLoop)
6278 {
6279 constexpr char kVS[] =
6280 "void main()\n"
6281 "{\n"
6282 " for (int i = 0; i < 10; ++i)\n"
6283 " const int b = 0;\n"
6284 "}\n";
6285
6286 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
6287 EXPECT_NE(0u, shader);
6288 glDeleteShader(shader);
6289 }
6290
6291 // Tests that using a constant declaration as a loop init expression doesn't crash. Note that this
6292 // test doesn't work on D3D9 due to looping limitations, so it is only run on ES3.
TEST_P(GLSLTest_ES3,ConstantStatementAsLoopInit)6293 TEST_P(GLSLTest_ES3, ConstantStatementAsLoopInit)
6294 {
6295 constexpr char kVS[] =
6296 "void main()\n"
6297 "{\n"
6298 " for (const int i = 0; i < 0;) {}\n"
6299 "}\n";
6300
6301 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
6302 EXPECT_NE(0u, shader);
6303 glDeleteShader(shader);
6304 }
6305
6306 // Tests that using a constant condition guarding a discard works
6307 // Covers a failing case in the Vulkan backend: http://anglebug.com/7033
TEST_P(GLSLTest_ES3,ConstantConditionGuardingDiscard)6308 TEST_P(GLSLTest_ES3, ConstantConditionGuardingDiscard)
6309 {
6310 constexpr char kFS[] = R"(#version 300 es
6311 void main()
6312 {
6313 if (true)
6314 {
6315 discard;
6316 }
6317 })";
6318
6319 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
6320 EXPECT_NE(0u, shader);
6321 glDeleteShader(shader);
6322 }
6323
6324 // Tests that nesting a discard in unconditional blocks works
6325 // Covers a failing case in the Vulkan backend: http://anglebug.com/7033
TEST_P(GLSLTest_ES3,NestedUnconditionalDiscards)6326 TEST_P(GLSLTest_ES3, NestedUnconditionalDiscards)
6327 {
6328 constexpr char kFS[] = R"(#version 300 es
6329 out mediump vec4 c;
6330 void main()
6331 {
6332 {
6333 c = vec4(0);
6334 {
6335 discard;
6336 }
6337 }
6338 })";
6339
6340 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
6341 EXPECT_NE(0u, shader);
6342 glDeleteShader(shader);
6343 }
6344
6345 // Test that uninitialized local variables are initialized to 0.
TEST_P(WebGL2GLSLTest,InitUninitializedLocals)6346 TEST_P(WebGL2GLSLTest, InitUninitializedLocals)
6347 {
6348 // Test skipped on Android GLES because local variable initialization is disabled.
6349 // http://anglebug.com/2046
6350 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
6351
6352 constexpr char kFS[] =
6353 "#version 300 es\n"
6354 "precision mediump float;\n"
6355 "out vec4 my_FragColor;\n"
6356 "int result = 0;\n"
6357 "void main()\n"
6358 "{\n"
6359 " int u;\n"
6360 " result += u;\n"
6361 " int k = 0;\n"
6362 " for (int i[2], j = i[0] + 1; k < 2; ++k)\n"
6363 " {\n"
6364 " result += j;\n"
6365 " }\n"
6366 " if (result == 2)\n"
6367 " {\n"
6368 " my_FragColor = vec4(0, 1, 0, 1);\n"
6369 " }\n"
6370 " else\n"
6371 " {\n"
6372 " my_FragColor = vec4(1, 0, 0, 1);\n"
6373 " }\n"
6374 "}\n";
6375
6376 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6377
6378 // [WebGL 1.0]
6379 // DrawArrays or drawElements will generate an INVALID_OPERATION error
6380 // if a vertex attribute is enabled as an array via enableVertexAttribArray
6381 // but no buffer is bound to that attribute.
6382 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6383 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6384 }
6385
6386 // Test that uninitialized structs containing arrays of structs are initialized to 0. This
6387 // specifically tests with two different struct variables declared in the same block.
TEST_P(WebGL2GLSLTest,InitUninitializedStructContainingArrays)6388 TEST_P(WebGL2GLSLTest, InitUninitializedStructContainingArrays)
6389 {
6390 // Test skipped on Android GLES because local variable initialization is disabled.
6391 // http://anglebug.com/2046
6392 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
6393
6394 constexpr char kFS[] =
6395 "precision mediump float;\n"
6396 "struct T\n"
6397 "{\n"
6398 " int a[2];\n"
6399 "};\n"
6400 "struct S\n"
6401 "{\n"
6402 " T t[2];\n"
6403 "};\n"
6404 "void main()\n"
6405 "{\n"
6406 " S s;\n"
6407 " S s2;\n"
6408 " if (s.t[1].a[1] == 0 && s2.t[1].a[1] == 0)\n"
6409 " {\n"
6410 " gl_FragColor = vec4(0, 1, 0, 1);\n"
6411 " }\n"
6412 " else\n"
6413 " {\n"
6414 " gl_FragColor = vec4(1, 0, 0, 1);\n"
6415 " }\n"
6416 "}\n";
6417
6418 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
6419 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6420 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6421 }
6422
6423 // Verify that two shaders with the same uniform name and members but different structure names will
6424 // not link.
TEST_P(GLSLTest,StructureNameMatchingTest)6425 TEST_P(GLSLTest, StructureNameMatchingTest)
6426 {
6427 const char *vsSource =
6428 "// Structures must have the same name, sequence of type names, and\n"
6429 "// type definitions, and field names to be considered the same type.\n"
6430 "// GLSL 1.017 4.2.4\n"
6431 "precision mediump float;\n"
6432 "struct info {\n"
6433 " vec4 pos;\n"
6434 " vec4 color;\n"
6435 "};\n"
6436 "\n"
6437 "uniform info uni;\n"
6438 "void main()\n"
6439 "{\n"
6440 " gl_Position = uni.pos;\n"
6441 "}\n";
6442
6443 GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
6444 ASSERT_NE(0u, vs);
6445 glDeleteShader(vs);
6446
6447 const char *fsSource =
6448 "// Structures must have the same name, sequence of type names, and\n"
6449 "// type definitions, and field names to be considered the same type.\n"
6450 "// GLSL 1.017 4.2.4\n"
6451 "precision mediump float;\n"
6452 "struct info1 {\n"
6453 " vec4 pos;\n"
6454 " vec4 color;\n"
6455 "};\n"
6456 "\n"
6457 "uniform info1 uni;\n"
6458 "void main()\n"
6459 "{\n"
6460 " gl_FragColor = uni.color;\n"
6461 "}\n";
6462
6463 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
6464 ASSERT_NE(0u, fs);
6465 glDeleteShader(fs);
6466
6467 GLuint program = CompileProgram(vsSource, fsSource);
6468 EXPECT_EQ(0u, program);
6469 }
6470
6471 // Test that an uninitialized nameless struct inside a for loop init statement works.
TEST_P(WebGL2GLSLTest,UninitializedNamelessStructInForInitStatement)6472 TEST_P(WebGL2GLSLTest, UninitializedNamelessStructInForInitStatement)
6473 {
6474 // Test skipped on Android GLES because local variable initialization is disabled.
6475 // http://anglebug.com/2046
6476 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
6477
6478 constexpr char kFS[] =
6479 "#version 300 es\n"
6480 "precision highp float;\n"
6481 "out vec4 my_FragColor;\n"
6482 "void main()\n"
6483 "{\n"
6484 " my_FragColor = vec4(1, 0, 0, 1);\n"
6485 " for (struct { float q; } b; b.q < 2.0; b.q++) {\n"
6486 " my_FragColor = vec4(0, 1, 0, 1);\n"
6487 " }\n"
6488 "}\n";
6489
6490 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6491 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6492 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6493 }
6494
6495 // Test that uninitialized global variables are initialized to 0.
TEST_P(WebGLGLSLTest,InitUninitializedGlobals)6496 TEST_P(WebGLGLSLTest, InitUninitializedGlobals)
6497 {
6498 // http://anglebug.com/2862
6499 ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
6500
6501 constexpr char kFS[] =
6502 "precision mediump float;\n"
6503 "int result;\n"
6504 "int i[2], j = i[0] + 1;\n"
6505 "void main()\n"
6506 "{\n"
6507 " result += j;\n"
6508 " if (result == 1)\n"
6509 " {\n"
6510 " gl_FragColor = vec4(0, 1, 0, 1);\n"
6511 " }\n"
6512 " else\n"
6513 " {\n"
6514 " gl_FragColor = vec4(1, 0, 0, 1);\n"
6515 " }\n"
6516 "}\n";
6517
6518 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
6519 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6520 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6521 }
6522
6523 // Test that an uninitialized nameless struct in the global scope works.
TEST_P(WebGLGLSLTest,UninitializedNamelessStructInGlobalScope)6524 TEST_P(WebGLGLSLTest, UninitializedNamelessStructInGlobalScope)
6525 {
6526 constexpr char kFS[] =
6527 "precision mediump float;\n"
6528 "struct { float q; } b;\n"
6529 "void main()\n"
6530 "{\n"
6531 " gl_FragColor = vec4(1, 0, 0, 1);\n"
6532 " if (b.q == 0.0)\n"
6533 " {\n"
6534 " gl_FragColor = vec4(0, 1, 0, 1);\n"
6535 " }\n"
6536 "}\n";
6537
6538 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
6539 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6540 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6541 }
6542
6543 // Test that uninitialized output arguments are initialized to 0.
TEST_P(WebGL2GLSLTest,InitOutputParams)6544 TEST_P(WebGL2GLSLTest, InitOutputParams)
6545 {
6546 constexpr char kFS[] = R"(#version 300 es
6547 precision mediump float;
6548
6549 struct S { float a; };
6550
6551 out vec4 color;
6552
6553 float f(out vec2 o1, out S o2[2], out float o3[3])
6554 {
6555 float uninitialized_local;
6556
6557 // leave o1 uninitialized
6558 // leave o2 partially uninitialized
6559 o2[0].a = 1.0;
6560
6561 // leave o3 partially uninitialized
6562 o3[1] = 0.5;
6563
6564 return uninitialized_local;
6565 }
6566
6567 void main()
6568 {
6569 vec2 v1 = vec2(123., 234.);
6570 S v2[2] = S[2](S(-1111.), S(55.));
6571 float v3[3] = float[3](20., 30., 40.);
6572 float v4 = f(v1, v2, v3);
6573
6574 // Everything should be 0 now except for v2[0].a and v3[1] which should be 1.0 and 0.5
6575 // respectively.
6576 color = vec4(v1.x + v2[0].a + v3[0], // 1.0
6577 v1.y + v2[1].a + v3[1], // 0.5
6578 v3[2] + v4, // 0
6579 1.0);
6580 })";
6581
6582 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6583 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6584 EXPECT_PIXEL_NEAR(0, 0, 255, 127, 0, 255, 1);
6585 }
6586
6587 // Tests nameless struct uniforms.
TEST_P(GLSLTest,EmbeddedStructUniform)6588 TEST_P(GLSLTest, EmbeddedStructUniform)
6589 {
6590 const char kFragmentShader[] = R"(precision mediump float;
6591 uniform struct { float q; } b;
6592 void main()
6593 {
6594 gl_FragColor = vec4(1, 0, 0, 1);
6595 if (b.q == 0.5)
6596 {
6597 gl_FragColor = vec4(0, 1, 0, 1);
6598 }
6599 })";
6600
6601 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
6602 glUseProgram(program);
6603 GLint uniLoc = glGetUniformLocation(program, "b.q");
6604 ASSERT_NE(-1, uniLoc);
6605 glUniform1f(uniLoc, 0.5f);
6606
6607 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6608 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6609 }
6610
6611 // Tests nameless struct uniform arrays.
TEST_P(GLSLTest,EmbeddedStructUniformArray)6612 TEST_P(GLSLTest, EmbeddedStructUniformArray)
6613 {
6614 const char kFragmentShader[] = R"(precision mediump float;
6615 uniform struct { float q; } b[2];
6616 void main()
6617 {
6618 gl_FragColor = vec4(1, 0, 0, 1);
6619 if (b[0].q == 0.5)
6620 {
6621 gl_FragColor = vec4(0, 1, 0, 1);
6622 }
6623 })";
6624
6625 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
6626 glUseProgram(program);
6627 GLint uniLoc = glGetUniformLocation(program, "b[0].q");
6628 ASSERT_NE(-1, uniLoc);
6629 glUniform1f(uniLoc, 0.5f);
6630
6631 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6632 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6633 }
6634
6635 // Test that samplers in structs can be extracted if the first reference to the struct does not
6636 // select an attribute.
TEST_P(GLSLTest,SamplerInStructNoMemberIndexing)6637 TEST_P(GLSLTest, SamplerInStructNoMemberIndexing)
6638 {
6639 constexpr char kVS[] = R"(
6640 uniform struct {
6641 sampler2D n;
6642 vec2 c;
6643 } s;
6644 void main()
6645 {
6646 s;
6647 })";
6648
6649 constexpr char kFS[] = R"(void main()
6650 {
6651 gl_FragColor = vec4(1);
6652 })";
6653
6654 ANGLE_GL_PROGRAM(program, kVS, kFS);
6655 }
6656
6657 // Similar test to SamplerInStructNoMemberIndexing, but the struct variable is an array.
TEST_P(GLSLTest,SamplerInStructArrayNoMemberIndexing)6658 TEST_P(GLSLTest, SamplerInStructArrayNoMemberIndexing)
6659 {
6660 constexpr char kVS[] = R"(
6661 uniform struct
6662 {
6663 sampler2D K;
6664 vec4 c;
6665 } s[6];
6666 void main()
6667 {
6668 s[0];
6669 })";
6670
6671 constexpr char kFS[] = R"(void main()
6672 {
6673 gl_FragColor = vec4(1);
6674 })";
6675
6676 ANGLE_GL_PROGRAM(program, kVS, kFS);
6677 }
6678
6679 // Tests that rewriting samplers in structs doesn't mess up indexing.
TEST_P(GLSLTest,SamplerInStructMemberIndexing)6680 TEST_P(GLSLTest, SamplerInStructMemberIndexing)
6681 {
6682 const char kVertexShader[] = R"(attribute vec2 position;
6683 varying vec2 texCoord;
6684 void main()
6685 {
6686 gl_Position = vec4(position, 0, 1);
6687 texCoord = position * 0.5 + vec2(0.5);
6688 })";
6689
6690 const char kFragmentShader[] = R"(precision mediump float;
6691 struct S { sampler2D samp; bool b; };
6692 uniform S uni;
6693 varying vec2 texCoord;
6694 void main()
6695 {
6696 uni;
6697 if (uni.b)
6698 {
6699 gl_FragColor = texture2D(uni.samp, texCoord);
6700 }
6701 else
6702 {
6703 gl_FragColor = vec4(1, 0, 0, 1);
6704 }
6705 })";
6706
6707 ANGLE_GL_PROGRAM(program, kVertexShader, kFragmentShader);
6708 glUseProgram(program);
6709
6710 GLint bLoc = glGetUniformLocation(program, "uni.b");
6711 ASSERT_NE(-1, bLoc);
6712 GLint sampLoc = glGetUniformLocation(program, "uni.samp");
6713 ASSERT_NE(-1, sampLoc);
6714
6715 glUniform1i(bLoc, 1);
6716
6717 std::array<GLColor, 4> kGreenPixels = {
6718 {GLColor::green, GLColor::green, GLColor::green, GLColor::green}};
6719
6720 GLTexture tex;
6721 glBindTexture(GL_TEXTURE_2D, tex);
6722 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6723 kGreenPixels.data());
6724 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6725 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6726 ASSERT_GL_NO_ERROR();
6727
6728 drawQuad(program, "position", 0.5f);
6729 ASSERT_GL_NO_ERROR();
6730
6731 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6732 }
6733
6734 // Tests that rewriting samplers in structs works when passed as function argument. In this test,
6735 // the function references another struct, which is not being modified. Regression test for AST
6736 // validation applied to a multipass transformation, where references to declarations were attempted
6737 // to be validated without having the entire shader. In this case, the reference to S2 was flagged
6738 // as invalid because S2's declaration was not visible.
TEST_P(GLSLTest,SamplerInStructAsFunctionArg)6739 TEST_P(GLSLTest, SamplerInStructAsFunctionArg)
6740 {
6741 const char kFS[] = R"(precision mediump float;
6742 struct S { sampler2D samp; bool b; };
6743 struct S2 { float f; };
6744
6745 uniform S us;
6746
6747 float f(S s)
6748 {
6749 S2 s2;
6750 s2.f = float(s.b);
6751 return s2.f;
6752 }
6753
6754 void main()
6755 {
6756 gl_FragColor = vec4(f(us), 0, 0, 1);
6757 })";
6758
6759 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
6760 EXPECT_NE(fs, 0u);
6761 ASSERT_GL_NO_ERROR();
6762 }
6763
6764 // Test that structs with samplers are not allowed in interface blocks. This is forbidden per
6765 // GLES3:
6766 //
6767 // > Types and declarators are the same as for other uniform variable declarations outside blocks,
6768 // > with these exceptions:
6769 // > * opaque types are not allowed
TEST_P(GLSLTest_ES3,StructWithSamplersDisallowedInInterfaceBlock)6770 TEST_P(GLSLTest_ES3, StructWithSamplersDisallowedInInterfaceBlock)
6771 {
6772 const char kFS[] = R"(#version 300 es
6773 precision mediump float;
6774 struct S { sampler2D samp; bool b; };
6775
6776 layout(std140) uniform Buffer { S s; } buffer;
6777
6778 out vec4 color;
6779
6780 void main()
6781 {
6782 color = texture(buffer.s.samp, vec2(0));
6783 })";
6784
6785 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
6786 EXPECT_EQ(fs, 0u);
6787 ASSERT_GL_NO_ERROR();
6788 }
6789
6790 // Tests two nameless struct uniforms.
TEST_P(GLSLTest,TwoEmbeddedStructUniforms)6791 TEST_P(GLSLTest, TwoEmbeddedStructUniforms)
6792 {
6793 const char kFragmentShader[] = R"(precision mediump float;
6794 uniform struct { float q; } b, c;
6795 void main()
6796 {
6797 gl_FragColor = vec4(1, 0, 0, 1);
6798 if (b.q == 0.5 && c.q == 1.0)
6799 {
6800 gl_FragColor = vec4(0, 1, 0, 1);
6801 }
6802 })";
6803
6804 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
6805 glUseProgram(program);
6806
6807 GLint uniLocB = glGetUniformLocation(program, "b.q");
6808 ASSERT_NE(-1, uniLocB);
6809 glUniform1f(uniLocB, 0.5f);
6810
6811 GLint uniLocC = glGetUniformLocation(program, "c.q");
6812 ASSERT_NE(-1, uniLocC);
6813 glUniform1f(uniLocC, 1.0f);
6814
6815 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6816 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6817 }
6818
6819 // Test that a loop condition that has an initializer declares a variable.
TEST_P(GLSLTest_ES3,ConditionInitializerDeclaresVariable)6820 TEST_P(GLSLTest_ES3, ConditionInitializerDeclaresVariable)
6821 {
6822 constexpr char kFS[] =
6823 "#version 300 es\n"
6824 "precision highp float;\n"
6825 "out vec4 my_FragColor;\n"
6826 "void main()\n"
6827 "{\n"
6828 " float i = 0.0;\n"
6829 " while (bool foo = (i < 1.5))\n"
6830 " {\n"
6831 " if (!foo)\n"
6832 " {\n"
6833 " ++i;\n"
6834 " }\n"
6835 " if (i > 3.5)\n"
6836 " {\n"
6837 " break;\n"
6838 " }\n"
6839 " ++i;\n"
6840 " }\n"
6841 " my_FragColor = vec4(i * 0.5 - 1.0, i * 0.5, 0.0, 1.0);\n"
6842 "}\n";
6843
6844 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6845 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
6846 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6847 }
6848
6849 // Test that a variable hides a user-defined function with the same name after its initializer.
6850 // GLSL ES 1.00.17 section 4.2.2: "A variable declaration is visible immediately following the
6851 // initializer if present, otherwise immediately following the identifier"
TEST_P(GLSLTest,VariableHidesUserDefinedFunctionAfterInitializer)6852 TEST_P(GLSLTest, VariableHidesUserDefinedFunctionAfterInitializer)
6853 {
6854 constexpr char kFS[] =
6855 "precision mediump float;\n"
6856 "uniform vec4 u;\n"
6857 "vec4 foo()\n"
6858 "{\n"
6859 " return u;\n"
6860 "}\n"
6861 "void main()\n"
6862 "{\n"
6863 " vec4 foo = foo();\n"
6864 " gl_FragColor = foo + vec4(0, 1, 0, 1);\n"
6865 "}\n";
6866
6867 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
6868 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
6869 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6870 }
6871
6872 // Test that structs with identical members are not ambiguous as function arguments.
TEST_P(GLSLTest,StructsWithSameMembersDisambiguatedByName)6873 TEST_P(GLSLTest, StructsWithSameMembersDisambiguatedByName)
6874 {
6875 constexpr char kFS[] =
6876 "precision mediump float;\n"
6877 "uniform float u_zero;\n"
6878 "struct S { float foo; };\n"
6879 "struct S2 { float foo; };\n"
6880 "float get(S s) { return s.foo + u_zero; }\n"
6881 "float get(S2 s2) { return 0.25 + s2.foo + u_zero; }\n"
6882 "void main()\n"
6883 "{\n"
6884 " S s;\n"
6885 " s.foo = 0.5;\n"
6886 " S2 s2;\n"
6887 " s2.foo = 0.25;\n"
6888 " gl_FragColor = vec4(0.0, get(s) + get(s2), 0.0, 1.0);\n"
6889 "}\n";
6890
6891 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
6892 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
6893 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6894 }
6895
6896 // Test that an inactive varying in vertex shader but used in fragment shader can be linked
6897 // successfully.
TEST_P(GLSLTest,InactiveVaryingInVertexActiveInFragment)6898 TEST_P(GLSLTest, InactiveVaryingInVertexActiveInFragment)
6899 {
6900 // http://anglebug.com/4820
6901 ANGLE_SKIP_TEST_IF((IsMac() && IsOpenGL()) || (IsIOS() && IsOpenGLES()));
6902
6903 constexpr char kVS[] =
6904 "attribute vec4 inputAttribute;\n"
6905 "varying vec4 varColor;\n"
6906 "void main()\n"
6907 "{\n"
6908 " gl_Position = inputAttribute;\n"
6909 "}\n";
6910
6911 constexpr char kFS[] =
6912 "precision mediump float;\n"
6913 "varying vec4 varColor;\n"
6914 "void main()\n"
6915 "{\n"
6916 " gl_FragColor = varColor;\n"
6917 "}\n";
6918
6919 ANGLE_GL_PROGRAM(program, kVS, kFS);
6920 drawQuad(program, "inputAttribute", 0.5f);
6921 ASSERT_GL_NO_ERROR();
6922 }
6923
6924 // Test that a varying struct that's not statically used in the fragment shader works.
6925 // GLSL ES 3.00.6 section 4.3.10.
TEST_P(GLSLTest_ES3,VaryingStructNotStaticallyUsedInFragmentShader)6926 TEST_P(GLSLTest_ES3, VaryingStructNotStaticallyUsedInFragmentShader)
6927 {
6928 constexpr char kVS[] =
6929 "#version 300 es\n"
6930 "struct S {\n"
6931 " vec4 field;\n"
6932 "};\n"
6933 "out S varStruct;\n"
6934 "void main()\n"
6935 "{\n"
6936 " gl_Position = vec4(1.0);\n"
6937 " varStruct.field = vec4(0.0, 0.5, 0.0, 0.0);\n"
6938 "}\n";
6939
6940 constexpr char kFS[] =
6941 "#version 300 es\n"
6942 "precision mediump float;\n"
6943 "struct S {\n"
6944 " vec4 field;\n"
6945 "};\n"
6946 "in S varStruct;\n"
6947 "out vec4 col;\n"
6948 "void main()\n"
6949 "{\n"
6950 " col = vec4(1.0);\n"
6951 "}\n";
6952
6953 ANGLE_GL_PROGRAM(program, kVS, kFS);
6954 }
6955
6956 // Test that inactive shader IO block varying are ok.
TEST_P(GLSLTest_ES31,InactiveVaryingIOBlock)6957 TEST_P(GLSLTest_ES31, InactiveVaryingIOBlock)
6958 {
6959 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
6960
6961 constexpr char kVS[] =
6962 R"(#version 310 es
6963 #extension GL_EXT_shader_io_blocks : require
6964
6965 precision highp float;
6966 in vec4 inputAttribute;
6967 out Block { vec4 v; };
6968 out Inactive1 { vec4 value; };
6969 out Inactive2 { vec4 value; } named;
6970
6971 void main()
6972 {
6973 gl_Position = inputAttribute;
6974 v = vec4(0);
6975 })";
6976
6977 constexpr char kFS[] =
6978 R"(#version 310 es
6979 #extension GL_EXT_shader_io_blocks : require
6980
6981 precision highp float;
6982
6983 in Block { vec4 v; };
6984 in Inactive3 { vec4 value; };
6985 in Inactive4 { vec4 value; } named2;
6986
6987 layout(location = 0) out mediump vec4 color;
6988 void main()
6989 {
6990 color = vec4(1, v.xy, 1);
6991 })";
6992
6993 ANGLE_GL_PROGRAM(program, kVS, kFS);
6994 drawQuad(program, "inputAttribute", 0.5f);
6995 ASSERT_GL_NO_ERROR();
6996
6997 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6998 }
6999
7000 // Test that a shader IO block varying that's not declared in the fragment shader links
7001 // successfully.
TEST_P(GLSLTest_ES31,VaryingIOBlockNotDeclaredInFragmentShader)7002 TEST_P(GLSLTest_ES31, VaryingIOBlockNotDeclaredInFragmentShader)
7003 {
7004 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
7005
7006 constexpr char kVS[] =
7007 R"(#version 310 es
7008 #extension GL_EXT_shader_io_blocks : require
7009
7010 precision highp float;
7011 in vec4 inputAttribute;
7012 out Block_inout { vec4 value; } user_out;
7013
7014 void main()
7015 {
7016 gl_Position = inputAttribute;
7017 user_out.value = vec4(4.0, 5.0, 6.0, 7.0);
7018 })";
7019
7020 constexpr char kFS[] =
7021 R"(#version 310 es
7022 #extension GL_EXT_shader_io_blocks : require
7023
7024 precision highp float;
7025 layout(location = 0) out mediump vec4 color;
7026 void main()
7027 {
7028 color = vec4(1, 0, 0, 1);
7029 })";
7030
7031 ANGLE_GL_PROGRAM(program, kVS, kFS);
7032 drawQuad(program, "inputAttribute", 0.5f);
7033 ASSERT_GL_NO_ERROR();
7034
7035 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7036 }
7037
7038 // Test that a shader IO block varying that's not declared in the vertex shader links
7039 // successfully.
TEST_P(GLSLTest_ES31,VaryingIOBlockNotDeclaredInVertexShader)7040 TEST_P(GLSLTest_ES31, VaryingIOBlockNotDeclaredInVertexShader)
7041 {
7042 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
7043
7044 constexpr char kVS[] =
7045 R"(#version 310 es
7046 #extension GL_EXT_shader_io_blocks : require
7047
7048 precision highp float;
7049 in vec4 inputAttribute;
7050
7051 void main()
7052 {
7053 gl_Position = inputAttribute;
7054 })";
7055
7056 constexpr char kFS[] =
7057 R"(#version 310 es
7058 #extension GL_EXT_shader_io_blocks : require
7059
7060 precision highp float;
7061 in Block_inout { vec4 value; } user_in;
7062 layout(location = 0) out mediump vec4 color;
7063
7064 void main()
7065 {
7066 color = vec4(1, 0, 0, 1);
7067 })";
7068
7069 ANGLE_GL_PROGRAM(program, kVS, kFS);
7070 drawQuad(program, "inputAttribute", 0.5f);
7071 ASSERT_GL_NO_ERROR();
7072
7073 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7074 }
7075
7076 // Test that a shader with sample in / sample out can be linked successfully.
TEST_P(GLSLTest_ES31,VaryingTessellationSampleInAndOut)7077 TEST_P(GLSLTest_ES31, VaryingTessellationSampleInAndOut)
7078 {
7079 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
7080 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_multisample_interpolation"));
7081
7082 constexpr char kVS[] =
7083 R"(#version 310 es
7084 #extension GL_OES_shader_multisample_interpolation : require
7085
7086 precision highp float;
7087 in vec4 inputAttribute;
7088
7089 sample out mediump float tc_in;
7090 void main()
7091 {
7092 tc_in = inputAttribute[0];
7093 gl_Position = inputAttribute;
7094 })";
7095
7096 constexpr char kTCS[] =
7097 R"(#version 310 es
7098 #extension GL_EXT_tessellation_shader : require
7099 #extension GL_OES_shader_multisample_interpolation : require
7100 layout (vertices=3) out;
7101
7102 sample in mediump float tc_in[];
7103 sample out mediump float tc_out[];
7104 void main()
7105 {
7106 tc_out[gl_InvocationID] = tc_in[gl_InvocationID];
7107 gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
7108 gl_TessLevelInner[0] = 2.0;
7109 gl_TessLevelInner[1] = 2.0;
7110 gl_TessLevelOuter[0] = 2.0;
7111 gl_TessLevelOuter[1] = 2.0;
7112 gl_TessLevelOuter[2] = 2.0;
7113 gl_TessLevelOuter[3] = 2.0;
7114 })";
7115
7116 constexpr char kTES[] =
7117 R"(#version 310 es
7118 #extension GL_EXT_tessellation_shader : require
7119 #extension GL_OES_shader_multisample_interpolation : require
7120 layout (triangles) in;
7121
7122 sample in mediump float tc_out[];
7123 sample out mediump float te_out;
7124 void main()
7125 {
7126 te_out = tc_out[2];
7127 gl_Position = gl_TessCoord[0] * gl_in[0].gl_Position;
7128 })";
7129
7130 constexpr char kFS[] =
7131 R"(#version 310 es
7132 #extension GL_OES_shader_multisample_interpolation : require
7133
7134 precision highp float;
7135 sample in mediump float te_out;
7136 layout(location = 0) out mediump vec4 color;
7137
7138 void main()
7139 {
7140 float out0 = te_out;
7141 color = vec4(1, 0, 0, 1);
7142 })";
7143
7144 ANGLE_GL_PROGRAM_WITH_TESS(program, kVS, kTCS, kTES, kFS);
7145 drawPatches(program, "inputAttribute", 0.5f, 1.0f, GL_FALSE);
7146 ASSERT_GL_NO_ERROR();
7147 }
7148
7149 // Test that `smooth sample` and `flat sample` pass the validation.
TEST_P(GLSLTest_ES3,AliasedSampleQualifiers)7150 TEST_P(GLSLTest_ES3, AliasedSampleQualifiers)
7151 {
7152 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_multisample_interpolation"));
7153
7154 constexpr char kVS[] =
7155 R"(#version 300 es
7156 #extension GL_OES_shader_multisample_interpolation : require
7157
7158 smooth sample out mediump float f;
7159 flat sample out mediump int i;
7160 void main()
7161 {
7162 f = 1.0;
7163 i = 1;
7164 gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
7165 })";
7166
7167 constexpr char kFS[] =
7168 R"(#version 300 es
7169 #extension GL_OES_shader_multisample_interpolation : require
7170
7171 smooth sample in mediump float f;
7172 flat sample in mediump int i;
7173 out mediump vec4 color;
7174 void main()
7175 {
7176 color = vec4(f, float(i), 0, 1);
7177 })";
7178
7179 ANGLE_GL_PROGRAM(program, kVS, kFS);
7180 }
7181
7182 // Test that `noperspective centroid` passes the validation and compiles.
TEST_P(GLSLTest_ES3,NoPerspectiveCentroid)7183 TEST_P(GLSLTest_ES3, NoPerspectiveCentroid)
7184 {
7185 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_shader_noperspective_interpolation"));
7186
7187 constexpr char kVS[] =
7188 R"(#version 300 es
7189 #extension GL_NV_shader_noperspective_interpolation : require
7190
7191 noperspective centroid out mediump float f;
7192 void main()
7193 {
7194 f = 1.0;
7195 gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
7196 })";
7197
7198 constexpr char kFS[] =
7199 R"(#version 300 es
7200 #extension GL_NV_shader_noperspective_interpolation : require
7201
7202 noperspective centroid in mediump float f;
7203 out mediump vec4 color;
7204 void main()
7205 {
7206 color = vec4(f, 0.0, 0.0, 1.0);
7207 })";
7208
7209 ANGLE_GL_PROGRAM(program, kVS, kFS);
7210 }
7211
7212 // Test that `noperspective sample` passes the validation and compiles.
TEST_P(GLSLTest_ES3,NoPerspectiveSample)7213 TEST_P(GLSLTest_ES3, NoPerspectiveSample)
7214 {
7215 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_multisample_interpolation"));
7216 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_shader_noperspective_interpolation"));
7217
7218 constexpr char kVS[] =
7219 R"(#version 300 es
7220 #extension GL_OES_shader_multisample_interpolation : require
7221 #extension GL_NV_shader_noperspective_interpolation : require
7222
7223 noperspective sample out mediump float f;
7224 void main()
7225 {
7226 f = 1.0;
7227 gl_Position = vec4(f, 0.0, 0.0, 1.0);
7228 })";
7229
7230 constexpr char kFS[] =
7231 R"(#version 300 es
7232 #extension GL_OES_shader_multisample_interpolation : require
7233 #extension GL_NV_shader_noperspective_interpolation : require
7234
7235 noperspective sample in mediump float f;
7236 out mediump vec4 color;
7237 void main()
7238 {
7239 color = vec4(f, 0.0, 0.0, 1.0);
7240 })";
7241
7242 ANGLE_GL_PROGRAM(program, kVS, kFS);
7243 }
7244
7245 // Test that a shader with sample in / sample out can be used successfully when the varying
7246 // precision is different between VS and FS.
TEST_P(GLSLTest_ES31,VaryingSampleInAndOutDifferentPrecision)7247 TEST_P(GLSLTest_ES31, VaryingSampleInAndOutDifferentPrecision)
7248 {
7249 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_multisample_interpolation"));
7250
7251 constexpr char kVS[] =
7252 R"(#version 310 es
7253 #extension GL_OES_shader_multisample_interpolation : require
7254
7255 precision highp float;
7256 in vec4 inputAttribute;
7257
7258 sample out highp float v;
7259 void main()
7260 {
7261 v = inputAttribute[0];
7262 gl_Position = inputAttribute;
7263 })";
7264
7265 constexpr char kFS[] =
7266 R"(#version 310 es
7267 #extension GL_OES_shader_multisample_interpolation : require
7268
7269 precision highp float;
7270 sample in mediump float v;
7271 layout(location = 0) out mediump vec4 color;
7272
7273 void main()
7274 {
7275 color = vec4(round((v + 1.) / 2. * 5.) / 5., 0, 0, 1);
7276 })";
7277
7278 ANGLE_GL_PROGRAM(program, kVS, kFS);
7279 drawQuad(program, "inputAttribute", 0.5f, 1.0f, GL_FALSE);
7280 ASSERT_GL_NO_ERROR();
7281
7282 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, 0, GLColor::red);
7283 }
7284
7285 // Test that a shader IO block varying whose block name is declared multiple(in/out) time links
7286 // successfully.
TEST_P(GLSLTest_ES31,VaryingIOBlockDeclaredAsInAndOut)7287 TEST_P(GLSLTest_ES31, VaryingIOBlockDeclaredAsInAndOut)
7288 {
7289 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
7290 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
7291
7292 constexpr char kVS[] = R"(#version 310 es
7293 #extension GL_EXT_shader_io_blocks : require
7294 precision highp float;
7295 in vec4 inputAttribute;
7296 out Vertex
7297 {
7298 vec4 fv;
7299 } outVertex;
7300 void main()
7301 {
7302 gl_Position = inputAttribute;
7303 outVertex.fv = gl_Position;
7304 })";
7305
7306 constexpr char kTCS[] = R"(#version 310 es
7307 #extension GL_EXT_tessellation_shader : require
7308 #extension GL_EXT_shader_io_blocks : require
7309 precision mediump float;
7310 in Vertex
7311 {
7312 vec4 fv;
7313 } inVertex[];
7314 layout(vertices = 2) out;
7315 out Vertex
7316 {
7317 vec4 fv;
7318 } outVertex[];
7319
7320 void main()
7321 {
7322 gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
7323 outVertex[gl_InvocationID].fv = inVertex[gl_InvocationID].fv;
7324 gl_TessLevelInner[0] = 1.0;
7325 gl_TessLevelInner[1] = 1.0;
7326 gl_TessLevelOuter[0] = 1.0;
7327 gl_TessLevelOuter[1] = 1.0;
7328 gl_TessLevelOuter[2] = 1.0;
7329 gl_TessLevelOuter[3] = 1.0;
7330 })";
7331
7332 constexpr char kTES[] = R"(#version 310 es
7333 #extension GL_EXT_tessellation_shader : require
7334 #extension GL_EXT_shader_io_blocks : require
7335 precision mediump float;
7336 layout (isolines, point_mode) in;
7337 in Vertex
7338 {
7339 vec4 fv;
7340 } inVertex[];
7341 out vec4 result_fv;
7342
7343 void main()
7344 {
7345 gl_Position = gl_in[0].gl_Position;
7346 result_fv = inVertex[0].fv;
7347 })";
7348
7349 constexpr char kFS[] = R"(#version 310 es
7350 precision mediump float;
7351
7352 layout(location = 0) out mediump vec4 color;
7353
7354 void main()
7355 {
7356 // Output solid green
7357 color = vec4(0, 1.0, 0, 1.0);
7358 })";
7359
7360 ANGLE_GL_PROGRAM_WITH_TESS(program, kVS, kTCS, kTES, kFS);
7361 drawPatches(program, "inputAttribute", 0.5f, 1.0f, GL_FALSE);
7362 ASSERT_GL_NO_ERROR();
7363 }
7364
testTessellationTextureBufferAccess(const APIExtensionVersion usedExtension)7365 void GLSLTest_ES31::testTessellationTextureBufferAccess(const APIExtensionVersion usedExtension)
7366 {
7367 ASSERT(usedExtension == APIExtensionVersion::EXT || usedExtension == APIExtensionVersion::OES);
7368
7369 // Vertex shader
7370 constexpr char kVS[] = R"(#version 310 es
7371 precision highp float;
7372 in vec4 inputAttribute;
7373
7374 void main()
7375 {
7376 gl_Position = inputAttribute;
7377 })";
7378
7379 // Tessellation shaders
7380 constexpr char kGLSLVersion[] = R"(#version 310 es
7381 )";
7382 constexpr char kTessEXT[] = R"(#extension GL_EXT_tessellation_shader : require
7383 )";
7384 constexpr char kTessOES[] = R"(#extension GL_OES_tessellation_shader : require
7385 )";
7386 constexpr char kTexBufEXT[] = R"(#extension GL_EXT_texture_buffer : require
7387 )";
7388 constexpr char kTexBufOES[] = R"(#extension GL_OES_texture_buffer : require
7389 )";
7390
7391 std::string tcs;
7392 std::string tes;
7393
7394 tcs.append(kGLSLVersion);
7395 tes.append(kGLSLVersion);
7396
7397 if (usedExtension == APIExtensionVersion::EXT)
7398 {
7399 tcs.append(kTessEXT);
7400 tes.append(kTessEXT);
7401 tes.append(kTexBufEXT);
7402 }
7403 else
7404 {
7405 tcs.append(kTessOES);
7406 tes.append(kTessOES);
7407 tes.append(kTexBufOES);
7408 }
7409
7410 constexpr char kTCSBody[] = R"(precision mediump float;
7411 layout(vertices = 2) out;
7412
7413 void main()
7414 {
7415 gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
7416 gl_TessLevelInner[0] = 1.0;
7417 gl_TessLevelInner[1] = 1.0;
7418 gl_TessLevelOuter[0] = 1.0;
7419 gl_TessLevelOuter[1] = 1.0;
7420 gl_TessLevelOuter[2] = 1.0;
7421 gl_TessLevelOuter[3] = 1.0;
7422 })";
7423 tcs.append(kTCSBody);
7424
7425 constexpr char kTESBody[] = R"(precision mediump float;
7426 layout (isolines, point_mode) in;
7427
7428 uniform highp samplerBuffer tex;
7429
7430 out vec4 tex_color;
7431
7432 void main()
7433 {
7434 tex_color = texelFetch(tex, 0);
7435 gl_Position = gl_in[0].gl_Position;
7436 })";
7437 tes.append(kTESBody);
7438
7439 // Fragment shader
7440 constexpr char kFS[] = R"(#version 310 es
7441 precision mediump float;
7442 layout(location = 0) out mediump vec4 color;
7443
7444 in vec4 tex_color;
7445
7446 void main()
7447 {
7448 color = tex_color;
7449 })";
7450
7451 constexpr GLint kBufferSize = 32;
7452 GLubyte texData[] = {0u, 255u, 0u, 255u};
7453
7454 GLTexture texture;
7455 glBindTexture(GL_TEXTURE_BUFFER, texture);
7456
7457 GLBuffer buffer;
7458 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
7459 glBufferData(GL_TEXTURE_BUFFER, kBufferSize, texData, GL_STATIC_DRAW);
7460 glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGBA8, buffer);
7461 ASSERT_GL_NO_ERROR();
7462
7463 glClearColor(1.0, 0, 0, 1.0);
7464 glClear(GL_COLOR_BUFFER_BIT);
7465
7466 ANGLE_GL_PROGRAM_WITH_TESS(program, kVS, tcs.c_str(), tes.c_str(), kFS);
7467 drawPatches(program, "inputAttribute", 0.5f, 1.0f, GL_FALSE);
7468 ASSERT_GL_NO_ERROR();
7469 }
7470
7471 // Test that texture buffers can be accessed in a tessellation stage (using EXT)
TEST_P(GLSLTest_ES31,TessellationTextureBufferAccessEXT)7472 TEST_P(GLSLTest_ES31, TessellationTextureBufferAccessEXT)
7473 {
7474 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
7475 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_buffer"));
7476 testTessellationTextureBufferAccess(APIExtensionVersion::EXT);
7477 }
7478
7479 // Test that texture buffers can be accessed in a tessellation stage (using OES)
TEST_P(GLSLTest_ES31,TessellationTextureBufferAccessOES)7480 TEST_P(GLSLTest_ES31, TessellationTextureBufferAccessOES)
7481 {
7482 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_tessellation_shader"));
7483 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_buffer"));
7484 testTessellationTextureBufferAccess(APIExtensionVersion::OES);
7485 }
7486
7487 // Test that a varying struct that's not declared in the fragment shader links successfully.
7488 // GLSL ES 3.00.6 section 4.3.10.
TEST_P(GLSLTest_ES3,VaryingStructNotDeclaredInFragmentShader)7489 TEST_P(GLSLTest_ES3, VaryingStructNotDeclaredInFragmentShader)
7490 {
7491 constexpr char kVS[] =
7492 "#version 300 es\n"
7493 "struct S {\n"
7494 " vec4 field;\n"
7495 "};\n"
7496 "out S varStruct;\n"
7497 "void main()\n"
7498 "{\n"
7499 " gl_Position = vec4(1.0);\n"
7500 " varStruct.field = vec4(0.0, 0.5, 0.0, 0.0);\n"
7501 "}\n";
7502
7503 constexpr char kFS[] =
7504 "#version 300 es\n"
7505 "precision mediump float;\n"
7506 "out vec4 col;\n"
7507 "void main()\n"
7508 "{\n"
7509 " col = vec4(1.0);\n"
7510 "}\n";
7511
7512 ANGLE_GL_PROGRAM(program, kVS, kFS);
7513 }
7514
7515 // Test that a varying struct that's not declared in the vertex shader, and is unused in the
7516 // fragment shader links successfully.
TEST_P(GLSLTest_ES3,VaryingStructNotDeclaredInVertexShader)7517 TEST_P(GLSLTest_ES3, VaryingStructNotDeclaredInVertexShader)
7518 {
7519 // GLSL ES allows the vertex shader to not declare a varying if the fragment shader is not
7520 // going to use it. See section 9.1 in
7521 // https://www.khronos.org/registry/OpenGL/specs/es/3.2/GLSL_ES_Specification_3.20.pdf or
7522 // section 4.3.5 in https://www.khronos.org/files/opengles_shading_language.pdf
7523 //
7524 // However, nvidia OpenGL ES drivers fail to link this program.
7525 //
7526 // http://anglebug.com/3413
7527 ANGLE_SKIP_TEST_IF(IsOpenGLES() && IsNVIDIA());
7528
7529 constexpr char kVS[] =
7530 "#version 300 es\n"
7531 "void main()\n"
7532 "{\n"
7533 " gl_Position = vec4(1.0);\n"
7534 "}\n";
7535
7536 constexpr char kFS[] =
7537 "#version 300 es\n"
7538 "precision mediump float;\n"
7539 "out vec4 col;\n"
7540 "struct S {\n"
7541 " vec4 field;\n"
7542 "};\n"
7543 "in S varStruct;\n"
7544 "void main()\n"
7545 "{\n"
7546 " col = vec4(1.0);\n"
7547 "}\n";
7548
7549 ANGLE_GL_PROGRAM(program, kVS, kFS);
7550 }
7551
7552 // Test that a varying struct that's not initialized in the vertex shader links successfully.
TEST_P(WebGL2GLSLTest,VaryingStructNotInitializedInVertexShader)7553 TEST_P(WebGL2GLSLTest, VaryingStructNotInitializedInVertexShader)
7554 {
7555 // GLSL ES allows the vertex shader to declare but not initialize a varying (with a
7556 // specification that the varying values are undefined in the fragment stage). See section 9.1
7557 // in https://www.khronos.org/registry/OpenGL/specs/es/3.2/GLSL_ES_Specification_3.20.pdf
7558 // or section 4.3.5 in https://www.khronos.org/files/opengles_shading_language.pdf
7559 //
7560 // However, windows and mac OpenGL drivers fail to link this program. With a message like:
7561 //
7562 // > Input of fragment shader 'varStruct' not written by vertex shader
7563 //
7564 // http://anglebug.com/3413
7565 ANGLE_SKIP_TEST_IF(IsDesktopOpenGL() && (IsMac() || (IsWindows() && !IsNVIDIA())));
7566 // TODO(anglebug.com/5491): iOS thinks that the precision qualifiers don't match on the
7567 // struct member. Not sure if it's being overly strict.
7568 ANGLE_SKIP_TEST_IF(IsIOS() && IsOpenGLES());
7569
7570 constexpr char kVS[] =
7571 "#version 300 es\n"
7572 "struct S {\n"
7573 " vec4 field;\n"
7574 "};\n"
7575 "out S varStruct;\n"
7576 "void main()\n"
7577 "{\n"
7578 " gl_Position = vec4(1.0);\n"
7579 "}\n";
7580
7581 constexpr char kFS[] =
7582 "#version 300 es\n"
7583 "precision mediump float;\n"
7584 "out vec4 col;\n"
7585 "struct S {\n"
7586 " vec4 field;\n"
7587 "};\n"
7588 "in S varStruct;\n"
7589 "void main()\n"
7590 "{\n"
7591 " col = varStruct.field;\n"
7592 "}\n";
7593
7594 ANGLE_GL_PROGRAM(program, kVS, kFS);
7595 }
7596
7597 // Test that a varying struct that gets used in the fragment shader works.
TEST_P(GLSLTest_ES3,VaryingStructUsedInFragmentShader)7598 TEST_P(GLSLTest_ES3, VaryingStructUsedInFragmentShader)
7599 {
7600 // TODO(anglebug.com/5491): iOS thinks that the precision qualifiers don't match on the
7601 // struct member. Not sure if it's being overly strict.
7602 ANGLE_SKIP_TEST_IF(IsIOS() && IsOpenGLES());
7603 constexpr char kVS[] =
7604 "#version 300 es\n"
7605 "in vec4 inputAttribute;\n"
7606 "struct S {\n"
7607 " vec4 field;\n"
7608 "};\n"
7609 "out S varStruct;\n"
7610 "out S varStruct2;\n"
7611 "void main()\n"
7612 "{\n"
7613 " gl_Position = inputAttribute;\n"
7614 " varStruct.field = vec4(0.0, 0.5, 0.0, 1.0);\n"
7615 " varStruct2.field = vec4(0.0, 0.5, 0.0, 1.0);\n"
7616 "}\n";
7617
7618 constexpr char kFS[] =
7619 "#version 300 es\n"
7620 "precision mediump float;\n"
7621 "out vec4 col;\n"
7622 "struct S {\n"
7623 " vec4 field;\n"
7624 "};\n"
7625 "in S varStruct;\n"
7626 "in S varStruct2;\n"
7627 "void main()\n"
7628 "{\n"
7629 " col = varStruct.field + varStruct2.field;\n"
7630 "}\n";
7631
7632 ANGLE_GL_PROGRAM(program, kVS, kFS);
7633 drawQuad(program, "inputAttribute", 0.5f);
7634 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7635 }
7636
7637 // This is a regression test to make sure a red quad is rendered without issues
7638 // when a passthrough function with a vec3 input parameter is used in the fragment shader.
TEST_P(GLSLTest_ES31,SamplerPassthroughFailedLink)7639 TEST_P(GLSLTest_ES31, SamplerPassthroughFailedLink)
7640 {
7641 constexpr char kVS[] =
7642 "precision mediump float;\n"
7643 "attribute vec4 inputAttribute;\n"
7644 "varying mediump vec2 texCoord;\n"
7645 "void main() {\n"
7646 " texCoord = inputAttribute.xy;\n"
7647 " gl_Position = vec4(inputAttribute.x, inputAttribute.y, 0.0, 1.0);\n"
7648 "}\n";
7649
7650 constexpr char kFS[] =
7651 "precision mediump float;\n"
7652 "varying mediump vec2 texCoord;\n"
7653 "uniform sampler2D testSampler;\n"
7654 "vec3 passthrough(vec3 c) {\n"
7655 " return c;\n"
7656 "}\n"
7657 "void main() {\n"
7658 " gl_FragColor = vec4(passthrough(texture2D(testSampler, texCoord).rgb), 1.0);\n"
7659 "}\n";
7660 ANGLE_GL_PROGRAM(program, kVS, kFS);
7661
7662 // Initialize basic red texture.
7663 GLTexture texture;
7664 glBindTexture(GL_TEXTURE_2D, texture);
7665 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
7666 GLColor::red.data());
7667 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7668 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7669 ASSERT_GL_NO_ERROR();
7670
7671 drawQuad(program, "inputAttribute", 0.5f);
7672 ASSERT_GL_NO_ERROR();
7673 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7674 }
7675
7676 // This is a regression test to make sure a red quad is rendered without issues
7677 // when a passthrough function with a vec4 input parameter is used in the fragment shader.
TEST_P(GLSLTest_ES31,SamplerPassthroughIncorrectColor)7678 TEST_P(GLSLTest_ES31, SamplerPassthroughIncorrectColor)
7679 {
7680 constexpr char kVS[] =
7681 "precision mediump float;\n"
7682 "attribute vec4 inputAttribute;\n"
7683 "varying mediump vec2 texCoord;\n"
7684 "void main() {\n"
7685 " texCoord = inputAttribute.xy;\n"
7686 " gl_Position = vec4(inputAttribute.x, inputAttribute.y, 0.0, 1.0);\n"
7687 "}\n";
7688
7689 constexpr char kFS[] =
7690 "precision mediump float;\n"
7691 "varying mediump vec2 texCoord;\n"
7692 "uniform sampler2D testSampler;\n"
7693 "vec4 passthrough(vec4 c) {\n"
7694 " return c;\n"
7695 "}\n"
7696 "void main() {\n"
7697 " gl_FragColor = vec4(passthrough(texture2D(testSampler, texCoord)));\n"
7698 "}\n";
7699 ANGLE_GL_PROGRAM(program, kVS, kFS);
7700
7701 // Initialize basic red texture.
7702 GLTexture texture;
7703 glBindTexture(GL_TEXTURE_2D, texture);
7704 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
7705 GLColor::red.data());
7706 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7707 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7708 ASSERT_GL_NO_ERROR();
7709
7710 drawQuad(program, "inputAttribute", 0.5f);
7711 ASSERT_GL_NO_ERROR();
7712 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7713 }
7714
7715 // Test that multiple multi-field varying structs that get used in the fragment shader work.
TEST_P(GLSLTest_ES3,ComplexVaryingStructsUsedInFragmentShader)7716 TEST_P(GLSLTest_ES3, ComplexVaryingStructsUsedInFragmentShader)
7717 {
7718 // TODO(syoussefi): fails on android with:
7719 //
7720 // > Internal Vulkan error: A return array was too small for the result
7721 //
7722 // http://anglebug.com/3220
7723 ANGLE_SKIP_TEST_IF(IsVulkan() && IsAndroid());
7724 // TODO(anglebug.com/5491): iOS thinks that the precision qualifiers don't match on the
7725 // struct members. Not sure if it's being overly strict.
7726 ANGLE_SKIP_TEST_IF(IsIOS() && IsOpenGLES());
7727
7728 constexpr char kVS[] =
7729 "#version 300 es\n"
7730 "in vec4 inputAttribute;\n"
7731 "struct S {\n"
7732 " vec4 field1;\n"
7733 " vec4 field2;\n"
7734 "};\n"
7735 "out S varStruct;\n"
7736 "out S varStruct2;\n"
7737 "void main()\n"
7738 "{\n"
7739 " gl_Position = inputAttribute;\n"
7740 " varStruct.field1 = vec4(0.0, 0.5, 0.0, 1.0);\n"
7741 " varStruct.field2 = vec4(0.0, 0.5, 0.0, 1.0);\n"
7742 " varStruct2.field1 = vec4(0.0, 0.5, 0.0, 1.0);\n"
7743 " varStruct2.field2 = vec4(0.0, 0.5, 0.0, 1.0);\n"
7744 "}\n";
7745
7746 constexpr char kFS[] =
7747 "#version 300 es\n"
7748 "precision mediump float;\n"
7749 "out vec4 col;\n"
7750 "struct S {\n"
7751 " vec4 field1;\n"
7752 " vec4 field2;\n"
7753 "};\n"
7754 "in S varStruct;\n"
7755 "in S varStruct2;\n"
7756 "void main()\n"
7757 "{\n"
7758 " col = varStruct.field1 + varStruct2.field2;\n"
7759 "}\n";
7760
7761 ANGLE_GL_PROGRAM(program, kVS, kFS);
7762 drawQuad(program, "inputAttribute", 0.5f);
7763 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7764 }
7765
7766 // Test that an inactive varying array that doesn't get used in the fragment shader works.
TEST_P(GLSLTest_ES3,InactiveVaryingArrayUnusedInFragmentShader)7767 TEST_P(GLSLTest_ES3, InactiveVaryingArrayUnusedInFragmentShader)
7768 {
7769 constexpr char kVS[] =
7770 "#version 300 es\n"
7771 "in vec4 inputAttribute;\n"
7772 "out vec4 varArray[4];\n"
7773 "void main()\n"
7774 "{\n"
7775 " gl_Position = inputAttribute;\n"
7776 " varArray[0] = vec4(1.0, 0.0, 0.0, 1.0);\n"
7777 " varArray[1] = vec4(0.0, 1.0, 0.0, 1.0);\n"
7778 " varArray[2] = vec4(0.0, 0.0, 1.0, 1.0);\n"
7779 " varArray[3] = vec4(1.0, 1.0, 0.0, 1.0);\n"
7780 "}\n";
7781
7782 constexpr char kFS[] =
7783 "#version 300 es\n"
7784 "precision mediump float;\n"
7785 "out vec4 col;\n"
7786 "void main()\n"
7787 "{\n"
7788 " col = vec4(0.0, 0.0, 0.0, 1.0);\n"
7789 "}\n";
7790
7791 ANGLE_GL_PROGRAM(program, kVS, kFS);
7792 drawQuad(program, "inputAttribute", 0.5f);
7793 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
7794 }
7795
7796 // Test that an inactive varying struct that doesn't get used in the fragment shader works.
TEST_P(GLSLTest_ES3,InactiveVaryingStructUnusedInFragmentShader)7797 TEST_P(GLSLTest_ES3, InactiveVaryingStructUnusedInFragmentShader)
7798 {
7799 constexpr char kVS[] =
7800 "#version 300 es\n"
7801 "in vec4 inputAttribute;\n"
7802 "struct S {\n"
7803 " vec4 field;\n"
7804 "};\n"
7805 "out S varStruct;\n"
7806 "out S varStruct2;\n"
7807 "void main()\n"
7808 "{\n"
7809 " gl_Position = inputAttribute;\n"
7810 " varStruct.field = vec4(0.0, 1.0, 0.0, 1.0);\n"
7811 " varStruct2.field = vec4(0.0, 1.0, 0.0, 1.0);\n"
7812 "}\n";
7813
7814 constexpr char kFS[] =
7815 "#version 300 es\n"
7816 "precision mediump float;\n"
7817 "out vec4 col;\n"
7818 "struct S {\n"
7819 " vec4 field;\n"
7820 "};\n"
7821 "in S varStruct;\n"
7822 "in S varStruct2;\n"
7823 "void main()\n"
7824 "{\n"
7825 " col = varStruct.field;\n"
7826 "}\n";
7827
7828 ANGLE_GL_PROGRAM(program, kVS, kFS);
7829 drawQuad(program, "inputAttribute", 0.5f);
7830 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7831 }
7832
7833 // Test that multiple varying matrices that get used in the fragment shader work.
TEST_P(GLSLTest_ES3,VaryingMatrices)7834 TEST_P(GLSLTest_ES3, VaryingMatrices)
7835 {
7836 constexpr char kVS[] =
7837 "#version 300 es\n"
7838 "in vec4 inputAttribute;\n"
7839 "out mat2x2 varMat;\n"
7840 "out mat2x2 varMat2;\n"
7841 "out mat4x3 varMat3;\n"
7842 "void main()\n"
7843 "{\n"
7844 " gl_Position = inputAttribute;\n"
7845 " varMat[0] = vec2(1, 1);\n"
7846 " varMat[1] = vec2(1, 1);\n"
7847 " varMat2[0] = vec2(0.5, 0.5);\n"
7848 " varMat2[1] = vec2(0.5, 0.5);\n"
7849 " varMat3[0] = vec3(0.75, 0.75, 0.75);\n"
7850 " varMat3[1] = vec3(0.75, 0.75, 0.75);\n"
7851 " varMat3[2] = vec3(0.75, 0.75, 0.75);\n"
7852 " varMat3[3] = vec3(0.75, 0.75, 0.75);\n"
7853 "}\n";
7854
7855 constexpr char kFS[] =
7856 "#version 300 es\n"
7857 "precision mediump float;\n"
7858 "out vec4 col;\n"
7859 "in mat2x2 varMat;\n"
7860 "in mat2x2 varMat2;\n"
7861 "in mat4x3 varMat3;\n"
7862 "void main()\n"
7863 "{\n"
7864 " col = vec4(varMat[0].x, varMat2[1].y, varMat3[2].z, 1);\n"
7865 "}\n";
7866
7867 ANGLE_GL_PROGRAM(program, kVS, kFS);
7868 drawQuad(program, "inputAttribute", 0.5f);
7869 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 127, 191, 255), 1);
7870 }
7871
7872 // This test covers passing a struct containing a sampler as a function argument.
TEST_P(GLSLTest,StructsWithSamplersAsFunctionArg)7873 TEST_P(GLSLTest, StructsWithSamplersAsFunctionArg)
7874 {
7875 // Shader failed to compile on Nexus devices. http://anglebug.com/2114
7876 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
7877
7878 const char kFragmentShader[] = R"(precision mediump float;
7879 struct S { sampler2D samplerMember; };
7880 uniform S uStruct;
7881 uniform vec2 uTexCoord;
7882 vec4 foo(S structVar)
7883 {
7884 return texture2D(structVar.samplerMember, uTexCoord);
7885 }
7886 void main()
7887 {
7888 gl_FragColor = foo(uStruct);
7889 })";
7890
7891 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
7892
7893 // Initialize the texture with green.
7894 GLTexture tex;
7895 glActiveTexture(GL_TEXTURE0);
7896 glBindTexture(GL_TEXTURE_2D, tex);
7897 GLubyte texData[] = {0u, 255u, 0u, 255u};
7898 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
7899 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7900 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7901 ASSERT_GL_NO_ERROR();
7902
7903 // Draw
7904 glUseProgram(program);
7905 GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMember");
7906 ASSERT_NE(-1, samplerMemberLoc);
7907 glUniform1i(samplerMemberLoc, 0);
7908 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
7909 ASSERT_NE(-1, texCoordLoc);
7910 glUniform2f(texCoordLoc, 0.5f, 0.5f);
7911
7912 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
7913 ASSERT_GL_NO_ERROR();
7914
7915 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
7916 }
7917
7918 // This test covers passing a struct containing a sampler as a function argument.
TEST_P(GLSLTest,StructsWithSamplersAsFunctionArgWithPrototype)7919 TEST_P(GLSLTest, StructsWithSamplersAsFunctionArgWithPrototype)
7920 {
7921 // Shader failed to compile on Android. http://anglebug.com/2114
7922 ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
7923
7924 const char kFragmentShader[] = R"(precision mediump float;
7925 struct S { sampler2D samplerMember; };
7926 uniform S uStruct;
7927 uniform vec2 uTexCoord;
7928 vec4 foo(S structVar);
7929 vec4 foo(S structVar)
7930 {
7931 return texture2D(structVar.samplerMember, uTexCoord);
7932 }
7933 void main()
7934 {
7935 gl_FragColor = foo(uStruct);
7936 })";
7937
7938 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
7939
7940 // Initialize the texture with green.
7941 GLTexture tex;
7942 glActiveTexture(GL_TEXTURE0);
7943 glBindTexture(GL_TEXTURE_2D, tex);
7944 GLubyte texData[] = {0u, 255u, 0u, 255u};
7945 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
7946 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7947 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7948 ASSERT_GL_NO_ERROR();
7949
7950 // Draw
7951 glUseProgram(program);
7952 GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMember");
7953 ASSERT_NE(-1, samplerMemberLoc);
7954 glUniform1i(samplerMemberLoc, 0);
7955 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
7956 ASSERT_NE(-1, texCoordLoc);
7957 glUniform2f(texCoordLoc, 0.5f, 0.5f);
7958
7959 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
7960 ASSERT_GL_NO_ERROR();
7961
7962 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
7963 }
7964
7965 // This test covers passing a struct containing a sampler as a function argument, where the function
7966 // has non-return branch statements.
TEST_P(GLSLTest_ES3,StructsWithSamplersAsFunctionArgWithBranch)7967 TEST_P(GLSLTest_ES3, StructsWithSamplersAsFunctionArgWithBranch)
7968 {
7969 // Shader failed to compile on Nexus devices. http://anglebug.com/2114
7970 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
7971
7972 const char kFragmentShader[] = R"(precision mediump float;
7973 struct S { sampler2D samplerMember; };
7974 uniform S uStruct;
7975 uniform vec2 uTexCoord;
7976 vec4 foo(S structVar)
7977 {
7978 vec4 result;
7979 while (true)
7980 {
7981 result = texture2D(structVar.samplerMember, uTexCoord);
7982 if (result.x == 12345.)
7983 {
7984 continue;
7985 }
7986 break;
7987 }
7988 return result;
7989 }
7990 void main()
7991 {
7992 gl_FragColor = foo(uStruct);
7993 })";
7994
7995 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
7996
7997 // Initialize the texture with green.
7998 GLTexture tex;
7999 glActiveTexture(GL_TEXTURE0);
8000 glBindTexture(GL_TEXTURE_2D, tex);
8001 GLubyte texData[] = {0u, 255u, 0u, 255u};
8002 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
8003 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8004 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8005 ASSERT_GL_NO_ERROR();
8006
8007 // Draw
8008 glUseProgram(program);
8009 GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMember");
8010 ASSERT_NE(-1, samplerMemberLoc);
8011 glUniform1i(samplerMemberLoc, 0);
8012 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
8013 ASSERT_NE(-1, texCoordLoc);
8014 glUniform2f(texCoordLoc, 0.5f, 0.5f);
8015
8016 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
8017 ASSERT_GL_NO_ERROR();
8018
8019 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
8020 }
8021
8022 // This test covers passing an array of structs containing samplers as a function argument.
TEST_P(GLSLTest,ArrayOfStructsWithSamplersAsFunctionArg)8023 TEST_P(GLSLTest, ArrayOfStructsWithSamplersAsFunctionArg)
8024 {
8025 // Shader failed to compile on Nexus devices. http://anglebug.com/2114
8026 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
8027
8028 constexpr char kFS[] =
8029 "precision mediump float;\n"
8030 "struct S\n"
8031 "{\n"
8032 " sampler2D samplerMember; \n"
8033 "};\n"
8034 "uniform S uStructs[2];\n"
8035 "uniform vec2 uTexCoord;\n"
8036 "\n"
8037 "vec4 foo(S[2] structs)\n"
8038 "{\n"
8039 " return texture2D(structs[0].samplerMember, uTexCoord);\n"
8040 "}\n"
8041 "void main()\n"
8042 "{\n"
8043 " gl_FragColor = foo(uStructs);\n"
8044 "}\n";
8045
8046 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
8047
8048 // Initialize the texture with green.
8049 GLTexture tex;
8050 glActiveTexture(GL_TEXTURE0);
8051 glBindTexture(GL_TEXTURE_2D, tex);
8052 GLubyte texData[] = {0u, 255u, 0u, 255u};
8053 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
8054 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8055 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8056 ASSERT_GL_NO_ERROR();
8057
8058 // Draw
8059 glUseProgram(program);
8060 GLint samplerMemberLoc = glGetUniformLocation(program, "uStructs[0].samplerMember");
8061 ASSERT_NE(-1, samplerMemberLoc);
8062 glUniform1i(samplerMemberLoc, 0);
8063 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
8064 ASSERT_NE(-1, texCoordLoc);
8065 glUniform2f(texCoordLoc, 0.5f, 0.5f);
8066
8067 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
8068 ASSERT_GL_NO_ERROR();
8069
8070 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
8071 }
8072
8073 // This test covers passing a struct containing an array of samplers as a function argument.
TEST_P(GLSLTest,StructWithSamplerArrayAsFunctionArg)8074 TEST_P(GLSLTest, StructWithSamplerArrayAsFunctionArg)
8075 {
8076 // Shader failed to compile on Nexus devices. http://anglebug.com/2114
8077 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
8078
8079 constexpr char kFS[] =
8080 "precision mediump float;\n"
8081 "struct S\n"
8082 "{\n"
8083 " sampler2D samplerMembers[2];\n"
8084 "};\n"
8085 "uniform S uStruct;\n"
8086 "uniform vec2 uTexCoord;\n"
8087 "\n"
8088 "vec4 foo(S str)\n"
8089 "{\n"
8090 " return texture2D(str.samplerMembers[0], uTexCoord);\n"
8091 "}\n"
8092 "void main()\n"
8093 "{\n"
8094 " gl_FragColor = foo(uStruct);\n"
8095 "}\n";
8096
8097 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
8098
8099 // Initialize the texture with green.
8100 GLTexture tex;
8101 glActiveTexture(GL_TEXTURE0);
8102 glBindTexture(GL_TEXTURE_2D, tex);
8103 GLubyte texData[] = {0u, 255u, 0u, 255u};
8104 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
8105 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8106 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8107 ASSERT_GL_NO_ERROR();
8108
8109 // Draw
8110 glUseProgram(program);
8111 GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMembers[0]");
8112 ASSERT_NE(-1, samplerMemberLoc);
8113 glUniform1i(samplerMemberLoc, 0);
8114 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
8115 ASSERT_NE(-1, texCoordLoc);
8116 glUniform2f(texCoordLoc, 0.5f, 0.5f);
8117
8118 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
8119 ASSERT_GL_NO_ERROR();
8120
8121 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
8122 }
8123
8124 // This test covers passing nested structs containing a sampler as a function argument.
TEST_P(GLSLTest,NestedStructsWithSamplersAsFunctionArg)8125 TEST_P(GLSLTest, NestedStructsWithSamplersAsFunctionArg)
8126 {
8127 // Shader failed to compile on Nexus devices. http://anglebug.com/2114
8128 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
8129
8130 // TODO(anglebug.com/5360): Failing on ARM-based Apple DTKs.
8131 ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && IsDesktopOpenGL());
8132
8133 const char kFragmentShader[] = R"(precision mediump float;
8134 struct S { sampler2D samplerMember; };
8135 struct T { S nest; };
8136 uniform T uStruct;
8137 uniform vec2 uTexCoord;
8138 vec4 foo2(S structVar)
8139 {
8140 return texture2D(structVar.samplerMember, uTexCoord);
8141 }
8142 vec4 foo(T structVar)
8143 {
8144 return foo2(structVar.nest);
8145 }
8146 void main()
8147 {
8148 gl_FragColor = foo(uStruct);
8149 })";
8150
8151 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
8152
8153 // Initialize the texture with green.
8154 GLTexture tex;
8155 glActiveTexture(GL_TEXTURE0);
8156 glBindTexture(GL_TEXTURE_2D, tex);
8157 GLubyte texData[] = {0u, 255u, 0u, 255u};
8158 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
8159 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8160 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8161 ASSERT_GL_NO_ERROR();
8162
8163 // Draw
8164 glUseProgram(program);
8165 GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.nest.samplerMember");
8166 ASSERT_NE(-1, samplerMemberLoc);
8167 glUniform1i(samplerMemberLoc, 0);
8168 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
8169 ASSERT_NE(-1, texCoordLoc);
8170 glUniform2f(texCoordLoc, 0.5f, 0.5f);
8171
8172 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
8173 ASSERT_GL_NO_ERROR();
8174
8175 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
8176 }
8177
8178 // This test covers passing a compound structs containing a sampler as a function argument.
TEST_P(GLSLTest,CompoundStructsWithSamplersAsFunctionArg)8179 TEST_P(GLSLTest, CompoundStructsWithSamplersAsFunctionArg)
8180 {
8181 // Shader failed to compile on Nexus devices. http://anglebug.com/2114
8182 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
8183
8184 const char kFragmentShader[] = R"(precision mediump float;
8185 struct S { sampler2D samplerMember; bool b; };
8186 uniform S uStruct;
8187 uniform vec2 uTexCoord;
8188 vec4 foo(S structVar)
8189 {
8190 if (structVar.b)
8191 return texture2D(structVar.samplerMember, uTexCoord);
8192 else
8193 return vec4(1, 0, 0, 1);
8194 }
8195 void main()
8196 {
8197 gl_FragColor = foo(uStruct);
8198 })";
8199
8200 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
8201
8202 // Initialize the texture with green.
8203 GLTexture tex;
8204 glActiveTexture(GL_TEXTURE0);
8205 glBindTexture(GL_TEXTURE_2D, tex);
8206 GLubyte texData[] = {0u, 255u, 0u, 255u};
8207 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
8208 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8209 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8210 ASSERT_GL_NO_ERROR();
8211
8212 // Draw
8213 glUseProgram(program);
8214 GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMember");
8215 ASSERT_NE(-1, samplerMemberLoc);
8216 glUniform1i(samplerMemberLoc, 0);
8217 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
8218 ASSERT_NE(-1, texCoordLoc);
8219 glUniform2f(texCoordLoc, 0.5f, 0.5f);
8220 GLint bLoc = glGetUniformLocation(program, "uStruct.b");
8221 ASSERT_NE(-1, bLoc);
8222 glUniform1i(bLoc, 1);
8223
8224 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
8225 ASSERT_GL_NO_ERROR();
8226
8227 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
8228 }
8229
8230 // This test covers passing nested compound structs containing a sampler as a function argument.
TEST_P(GLSLTest,NestedCompoundStructsWithSamplersAsFunctionArg)8231 TEST_P(GLSLTest, NestedCompoundStructsWithSamplersAsFunctionArg)
8232 {
8233 // Shader failed to compile on Nexus devices. http://anglebug.com/2114
8234 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
8235
8236 // TODO(anglebug.com/5360): Failing on ARM-based Apple DTKs.
8237 ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && IsDesktopOpenGL());
8238
8239 const char kFragmentShader[] = R"(precision mediump float;
8240 struct S { sampler2D samplerMember; bool b; };
8241 struct T { S nest; bool b; };
8242 uniform T uStruct;
8243 uniform vec2 uTexCoord;
8244 vec4 foo2(S structVar)
8245 {
8246 if (structVar.b)
8247 return texture2D(structVar.samplerMember, uTexCoord);
8248 else
8249 return vec4(1, 0, 0, 1);
8250 }
8251 vec4 foo(T structVar)
8252 {
8253 if (structVar.b)
8254 return foo2(structVar.nest);
8255 else
8256 return vec4(1, 0, 0, 1);
8257 }
8258 void main()
8259 {
8260 gl_FragColor = foo(uStruct);
8261 })";
8262
8263 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
8264
8265 // Initialize the texture with green.
8266 GLTexture tex;
8267 glActiveTexture(GL_TEXTURE0);
8268 glBindTexture(GL_TEXTURE_2D, tex);
8269 GLubyte texData[] = {0u, 255u, 0u, 255u};
8270 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
8271 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8272 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8273 ASSERT_GL_NO_ERROR();
8274
8275 // Draw
8276 glUseProgram(program);
8277 GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.nest.samplerMember");
8278 ASSERT_NE(-1, samplerMemberLoc);
8279 glUniform1i(samplerMemberLoc, 0);
8280 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
8281 ASSERT_NE(-1, texCoordLoc);
8282 glUniform2f(texCoordLoc, 0.5f, 0.5f);
8283
8284 GLint bLoc = glGetUniformLocation(program, "uStruct.b");
8285 ASSERT_NE(-1, bLoc);
8286 glUniform1i(bLoc, 1);
8287
8288 GLint nestbLoc = glGetUniformLocation(program, "uStruct.nest.b");
8289 ASSERT_NE(-1, nestbLoc);
8290 glUniform1i(nestbLoc, 1);
8291
8292 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
8293 ASSERT_GL_NO_ERROR();
8294
8295 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
8296 }
8297
8298 // Same as the prior test but with reordered struct members.
TEST_P(GLSLTest,MoreNestedCompoundStructsWithSamplersAsFunctionArg)8299 TEST_P(GLSLTest, MoreNestedCompoundStructsWithSamplersAsFunctionArg)
8300 {
8301 // Shader failed to compile on Nexus devices. http://anglebug.com/2114
8302 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
8303
8304 // TODO(anglebug.com/5360): Failing on ARM-based Apple DTKs.
8305 ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && IsDesktopOpenGL());
8306
8307 const char kFragmentShader[] = R"(precision mediump float;
8308 struct S { bool b; sampler2D samplerMember; };
8309 struct T { bool b; S nest; };
8310 uniform T uStruct;
8311 uniform vec2 uTexCoord;
8312 vec4 foo2(S structVar)
8313 {
8314 if (structVar.b)
8315 return texture2D(structVar.samplerMember, uTexCoord);
8316 else
8317 return vec4(1, 0, 0, 1);
8318 }
8319 vec4 foo(T structVar)
8320 {
8321 if (structVar.b)
8322 return foo2(structVar.nest);
8323 else
8324 return vec4(1, 0, 0, 1);
8325 }
8326 void main()
8327 {
8328 gl_FragColor = foo(uStruct);
8329 })";
8330
8331 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
8332
8333 // Initialize the texture with green.
8334 GLTexture tex;
8335 glActiveTexture(GL_TEXTURE0);
8336 glBindTexture(GL_TEXTURE_2D, tex);
8337 GLubyte texData[] = {0u, 255u, 0u, 255u};
8338 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
8339 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8340 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8341 ASSERT_GL_NO_ERROR();
8342
8343 // Draw
8344 glUseProgram(program);
8345 GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.nest.samplerMember");
8346 ASSERT_NE(-1, samplerMemberLoc);
8347 glUniform1i(samplerMemberLoc, 0);
8348 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
8349 ASSERT_NE(-1, texCoordLoc);
8350 glUniform2f(texCoordLoc, 0.5f, 0.5f);
8351
8352 GLint bLoc = glGetUniformLocation(program, "uStruct.b");
8353 ASSERT_NE(-1, bLoc);
8354 glUniform1i(bLoc, 1);
8355
8356 GLint nestbLoc = glGetUniformLocation(program, "uStruct.nest.b");
8357 ASSERT_NE(-1, nestbLoc);
8358 glUniform1i(nestbLoc, 1);
8359
8360 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
8361 ASSERT_GL_NO_ERROR();
8362
8363 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
8364 }
8365 // Test that a global variable declared after main() works. This is a regression test for an issue
8366 // in global variable initialization.
TEST_P(WebGLGLSLTest,GlobalVariableDeclaredAfterMain)8367 TEST_P(WebGLGLSLTest, GlobalVariableDeclaredAfterMain)
8368 {
8369 constexpr char kFS[] =
8370 "precision mediump float;\n"
8371 "int getFoo();\n"
8372 "uniform int u_zero;\n"
8373 "void main()\n"
8374 "{\n"
8375 " gl_FragColor = vec4(1, 0, 0, 1);\n"
8376 " if (getFoo() == 0)\n"
8377 " {\n"
8378 " gl_FragColor = vec4(0, 1, 0, 1);\n"
8379 " }\n"
8380 "}\n"
8381 "int foo;\n"
8382 "int getFoo()\n"
8383 "{\n"
8384 " foo = u_zero;\n"
8385 " return foo;\n"
8386 "}\n";
8387
8388 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
8389 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
8390 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8391 }
8392
8393 // Test calling array length() with a "this" expression having side effects inside a loop condition.
8394 // The spec says that sequence operator operands need to run in sequence.
TEST_P(GLSLTest_ES3,ArrayLengthOnExpressionWithSideEffectsInLoopCondition)8395 TEST_P(GLSLTest_ES3, ArrayLengthOnExpressionWithSideEffectsInLoopCondition)
8396 {
8397 // "a" gets doubled three times in the below program.
8398 constexpr char kFS[] = R"(#version 300 es
8399 precision highp float;
8400 out vec4 my_FragColor;
8401 uniform int u_zero;
8402 int a;
8403 int[2] doubleA()
8404 {
8405 a *= 2;
8406 return int[2](a, a);
8407 }
8408 void main()
8409 {
8410 a = u_zero + 1;
8411 for (int i = 0; i < doubleA().length(); ++i)
8412 {}
8413 if (a == 8)
8414 {
8415 my_FragColor = vec4(0, 1, 0, 1);
8416 }
8417 else
8418 {
8419 my_FragColor = vec4(1, 0, 0, 1);
8420 }
8421 })";
8422
8423 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8424 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
8425 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8426 }
8427
8428 // Test calling array length() with a "this" expression having side effects that interact with side
8429 // effects of another operand of the same sequence operator. The spec says that sequence operator
8430 // operands need to run in order from left to right (ESSL 3.00.6 section 5.9).
TEST_P(GLSLTest_ES3,ArrayLengthOnExpressionWithSideEffectsInSequence)8431 TEST_P(GLSLTest_ES3, ArrayLengthOnExpressionWithSideEffectsInSequence)
8432 {
8433 constexpr char kFS[] = R"(#version 300 es
8434 precision highp float;
8435 out vec4 my_FragColor;
8436 uniform int u_zero;
8437 int a;
8438 int[3] doubleA()
8439 {
8440 a *= 2;
8441 return int[3](a, a, a);
8442 }
8443 void main()
8444 {
8445 a = u_zero;
8446 int b = (a++, doubleA().length());
8447 if (b == 3 && a == 2)
8448 {
8449 my_FragColor = vec4(0, 1, 0, 1);
8450 }
8451 else
8452 {
8453 my_FragColor = vec4(1, 0, 0, 1);
8454 }
8455 })";
8456
8457 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8458 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
8459 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8460 }
8461
8462 // Test calling array length() with a "this" expression that also contains a call of array length().
8463 // Both "this" expressions also have side effects.
TEST_P(GLSLTest_ES3,NestedArrayLengthMethodsWithSideEffects)8464 TEST_P(GLSLTest_ES3, NestedArrayLengthMethodsWithSideEffects)
8465 {
8466 constexpr char kFS[] = R"(#version 300 es
8467 precision highp float;
8468 out vec4 my_FragColor;
8469 uniform int u_zero;
8470 int a;
8471 int[3] multiplyA(int multiplier)
8472 {
8473 a *= multiplier;
8474 return int[3](a, a, a);
8475 }
8476 void main()
8477 {
8478 a = u_zero + 1;
8479 int b = multiplyA(multiplyA(2).length()).length();
8480 if (b == 3 && a == 6)
8481 {
8482 my_FragColor = vec4(0, 1, 0, 1);
8483 }
8484 else
8485 {
8486 my_FragColor = vec4(1, 0, 0, 1);
8487 }
8488 })";
8489
8490 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8491 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
8492 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8493 }
8494
8495 // Test calling array length() with a "this" expression having side effects inside an if condition.
8496 // This is an issue if the the side effect can be short circuited.
TEST_P(GLSLTest_ES3,ArrayLengthOnShortCircuitedExpressionWithSideEffectsInIfCondition)8497 TEST_P(GLSLTest_ES3, ArrayLengthOnShortCircuitedExpressionWithSideEffectsInIfCondition)
8498 {
8499 // Bug in the shader translator. http://anglebug.com/3829
8500 ANGLE_SKIP_TEST_IF(true);
8501
8502 // "a" shouldn't get modified by this shader.
8503 constexpr char kFS[] = R"(#version 300 es
8504 precision highp float;
8505 out vec4 my_FragColor;
8506 uniform int u_zero;
8507 int a;
8508 int[2] doubleA()
8509 {
8510 a *= 2;
8511 return int[2](a, a);
8512 }
8513 void main()
8514 {
8515 a = u_zero + 1;
8516 if (u_zero != 0 && doubleA().length() == 2)
8517 {
8518 ++a;
8519 }
8520 if (a == 1)
8521 {
8522 my_FragColor = vec4(0, 1, 0, 1);
8523 }
8524 else
8525 {
8526 my_FragColor = vec4(1, 0, 0, 1);
8527 }
8528 })";
8529
8530 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8531 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
8532 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8533 }
8534
8535 // Test calling array length() with a "this" expression having side effects in a statement where the
8536 // side effect can be short circuited.
TEST_P(GLSLTest_ES3,ArrayLengthOnShortCircuitedExpressionWithSideEffectsInStatement)8537 TEST_P(GLSLTest_ES3, ArrayLengthOnShortCircuitedExpressionWithSideEffectsInStatement)
8538 {
8539 // Bug in the shader translator. http://anglebug.com/3829
8540 ANGLE_SKIP_TEST_IF(true);
8541
8542 // "a" shouldn't get modified by this shader.
8543 constexpr char kFS[] = R"(#version 300 es
8544 precision highp float;
8545 out vec4 my_FragColor;
8546 uniform int u_zero;
8547 int a;
8548 int[2] doubleA()
8549 {
8550 a *= 2;
8551 return int[2](a, a);
8552 }
8553 void main()
8554 {
8555 a = u_zero + 1;
8556 bool test = u_zero != 0 && doubleA().length() == 2;
8557 if (a == 1)
8558 {
8559 my_FragColor = vec4(0, 1, 0, 1);
8560 }
8561 else
8562 {
8563 my_FragColor = vec4(1, 0, 0, 1);
8564 }
8565 })";
8566
8567 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8568 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
8569 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8570 }
8571
8572 // Test that array length inside vector constructor works.
TEST_P(GLSLTest_ES3,ArrayLengthInVectorConstructor)8573 TEST_P(GLSLTest_ES3, ArrayLengthInVectorConstructor)
8574 {
8575 const char kVS[] = R"(#version 300 es
8576 precision highp float;
8577 flat out uvec4 v;
8578
8579 int[1] f0()
8580 {
8581 return int[1](1);
8582 }
8583 void main()
8584 {
8585 v = uvec4(vec4(f0().length()));
8586
8587 gl_Position.x = ((gl_VertexID & 1) == 0 ? -1.0 : 1.0);
8588 gl_Position.y = ((gl_VertexID & 2) == 0 ? -1.0 : 1.0);
8589 gl_Position.zw = vec2(0, 1);
8590 })";
8591
8592 const char kFS[] = R"(#version 300 es
8593 precision highp float;
8594 flat in uvec4 v;
8595 out vec4 color;
8596
8597 bool isEq(uint a, float b) { return abs(float(a) - b) < 0.01; }
8598
8599 void main()
8600 {
8601 if (isEq(v[0], 1.) &&
8602 isEq(v[1], 1.) &&
8603 isEq(v[2], 1.) &&
8604 isEq(v[3], 1.))
8605 {
8606 color = vec4(0, 1, 0, 1);
8607 }
8608 else
8609 {
8610 color = vec4(1, 0, 0, 1);
8611 }
8612 })";
8613
8614 ANGLE_GL_PROGRAM(program, kVS, kFS);
8615 glUseProgram(program);
8616 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
8617 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8618 }
8619
8620 // Test that array length inside vector constructor works in complex expression.
TEST_P(GLSLTest_ES3,ArrayLengthInVectorConstructorComplex)8621 TEST_P(GLSLTest_ES3, ArrayLengthInVectorConstructorComplex)
8622 {
8623 const char kVS[] = R"(#version 300 es
8624 precision highp float;
8625 out vec4 v;
8626
8627 int[1] f0()
8628 {
8629 return int[1](1);
8630 }
8631 void main()
8632 {
8633 v = vec4(float(uint(f0().length()) + 1u) / 4.);
8634
8635 gl_Position.x = ((gl_VertexID & 1) == 0 ? -1.0 : 1.0);
8636 gl_Position.y = ((gl_VertexID & 2) == 0 ? -1.0 : 1.0);
8637 gl_Position.zw = vec2(0, 1);
8638 })";
8639
8640 const char kFS[] = R"(#version 300 es
8641 precision highp float;
8642 in vec4 v;
8643 out vec4 color;
8644
8645 bool isEq(float a, float b) { return abs(float(a) - b) < 0.01; }
8646
8647 void main()
8648 {
8649 if (isEq(v[0], 0.5) &&
8650 isEq(v[1], 0.5) &&
8651 isEq(v[2], 0.5) &&
8652 isEq(v[3], 0.5))
8653 {
8654 color = vec4(0, 1, 0, 1);
8655 }
8656 else
8657 {
8658 color = vec4(1, 0, 0, 1);
8659 }
8660 })";
8661
8662 ANGLE_GL_PROGRAM(program, kVS, kFS);
8663 glUseProgram(program);
8664 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
8665 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8666 }
8667
8668 // Test that array length inside matrix constructor works.
TEST_P(GLSLTest_ES3,ArrayLengthInMatrixConstructor)8669 TEST_P(GLSLTest_ES3, ArrayLengthInMatrixConstructor)
8670 {
8671 const char kVS[] = R"(#version 300 es
8672 precision highp float;
8673 out mat2x2 v;
8674
8675 int[1] f0()
8676 {
8677 return int[1](1);
8678 }
8679 void main()
8680 {
8681 v = mat2x2(f0().length());
8682
8683 gl_Position.x = ((gl_VertexID & 1) == 0 ? -1.0 : 1.0);
8684 gl_Position.y = ((gl_VertexID & 2) == 0 ? -1.0 : 1.0);
8685 gl_Position.zw = vec2(0, 1);
8686 })";
8687
8688 const char kFS[] = R"(#version 300 es
8689 precision highp float;
8690 in mat2x2 v;
8691 out vec4 color;
8692
8693 bool isEq(float a, float b) { return abs(a - b) < 0.01; }
8694
8695 void main()
8696 {
8697 if (isEq(v[0][0], 1.) &&
8698 isEq(v[0][1], 0.) &&
8699 isEq(v[1][0], 0.) &&
8700 isEq(v[1][1], 1.))
8701 {
8702 color = vec4(0, 1, 0, 1);
8703 }
8704 else
8705 {
8706 color = vec4(1, 0, 0, 1);
8707 }
8708 })";
8709
8710 ANGLE_GL_PROGRAM(program, kVS, kFS);
8711 glUseProgram(program);
8712 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
8713 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8714 }
8715
8716 // Test that array length inside vector constructor inside matrix constructor works.
TEST_P(GLSLTest_ES3,ArrayLengthInVectorInMatrixConstructor)8717 TEST_P(GLSLTest_ES3, ArrayLengthInVectorInMatrixConstructor)
8718 {
8719 const char kVS[] = R"(#version 300 es
8720 precision highp float;
8721 out mat2x2 v;
8722
8723 int[1] f0()
8724 {
8725 return int[1](1);
8726 }
8727 void main()
8728 {
8729 v = mat2x2(vec2(f0().length()), f0().length(), 0);
8730
8731 gl_Position.x = ((gl_VertexID & 1) == 0 ? -1.0 : 1.0);
8732 gl_Position.y = ((gl_VertexID & 2) == 0 ? -1.0 : 1.0);
8733 gl_Position.zw = vec2(0, 1);
8734 })";
8735
8736 const char kFS[] = R"(#version 300 es
8737 precision highp float;
8738 in mat2x2 v;
8739 out vec4 color;
8740
8741 bool isEq(float a, float b) { return abs(a - b) < 0.01; }
8742
8743 void main()
8744 {
8745 if (isEq(v[0][0], 1.) &&
8746 isEq(v[0][1], 1.) &&
8747 isEq(v[1][0], 1.) &&
8748 isEq(v[1][1], 0.))
8749 {
8750 color = vec4(0, 1, 0, 1);
8751 }
8752 else
8753 {
8754 color = vec4(1, 0, 0, 1);
8755 }
8756 })";
8757
8758 ANGLE_GL_PROGRAM(program, kVS, kFS);
8759 glUseProgram(program);
8760 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
8761 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8762 }
8763
8764 // Test that statements inside switch() get translated to correct HLSL.
TEST_P(GLSLTest_ES3,DifferentStatementsInsideSwitch)8765 TEST_P(GLSLTest_ES3, DifferentStatementsInsideSwitch)
8766 {
8767 constexpr char kFS[] = R"(#version 300 es
8768 precision highp float;
8769 uniform int u;
8770 void main()
8771 {
8772 switch (u)
8773 {
8774 case 0:
8775 ivec2 i;
8776 i.yx;
8777 }
8778 })";
8779
8780 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8781 }
8782
8783 // Test that switch fall-through works correctly.
8784 // This is a regression test for http://anglebug.com/2178
TEST_P(GLSLTest_ES3,SwitchFallThroughCodeDuplication)8785 TEST_P(GLSLTest_ES3, SwitchFallThroughCodeDuplication)
8786 {
8787 constexpr char kFS[] = R"(#version 300 es
8788 precision highp float;
8789 out vec4 my_FragColor;
8790 uniform int u_zero;
8791
8792 void main()
8793 {
8794 int i = 0;
8795 // switch should fall through both cases.
8796 switch(u_zero)
8797 {
8798 case 0:
8799 i += 1;
8800 case 1:
8801 i += 2;
8802 }
8803 if (i == 3)
8804 {
8805 my_FragColor = vec4(0, 1, 0, 1);
8806 }
8807 else
8808 {
8809 my_FragColor = vec4(1, 0, 0, 1);
8810 }
8811 })";
8812
8813 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8814 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
8815 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8816 }
8817
8818 // Test switch/case where default is last.
TEST_P(GLSLTest_ES3,SwitchWithDefaultAtTheEnd)8819 TEST_P(GLSLTest_ES3, SwitchWithDefaultAtTheEnd)
8820 {
8821 constexpr char kFS[] = R"(#version 300 es
8822
8823 precision highp float;
8824 out vec4 my_FragColor;
8825
8826 uniform int u_zero;
8827
8828 void main()
8829 {
8830 switch (u_zero)
8831 {
8832 case 1:
8833 my_FragColor = vec4(1, 0, 0, 1);
8834 break;
8835 default:
8836 my_FragColor = vec4(0, 1, 0, 1);
8837 }
8838 })";
8839
8840 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8841 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
8842 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8843 }
8844
8845 // Test that a switch statement with an empty block inside as a final statement compiles.
TEST_P(GLSLTest_ES3,SwitchFinalCaseHasEmptyBlock)8846 TEST_P(GLSLTest_ES3, SwitchFinalCaseHasEmptyBlock)
8847 {
8848 constexpr char kFS[] = R"(#version 300 es
8849
8850 precision mediump float;
8851 uniform int i;
8852 void main()
8853 {
8854 switch (i)
8855 {
8856 case 0:
8857 break;
8858 default:
8859 {}
8860 }
8861 })";
8862 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8863 }
8864
8865 // Test that a switch statement with an empty declaration inside as a final statement compiles.
TEST_P(GLSLTest_ES3,SwitchFinalCaseHasEmptyDeclaration)8866 TEST_P(GLSLTest_ES3, SwitchFinalCaseHasEmptyDeclaration)
8867 {
8868 constexpr char kFS[] = R"(#version 300 es
8869
8870 precision mediump float;
8871 uniform int i;
8872 void main()
8873 {
8874 switch (i)
8875 {
8876 case 0:
8877 break;
8878 default:
8879 float;
8880 }
8881 })";
8882 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8883 }
8884
8885 // Test switch/case where break/return statements are within blocks.
TEST_P(GLSLTest_ES3,SwitchBreakOrReturnInsideBlocks)8886 TEST_P(GLSLTest_ES3, SwitchBreakOrReturnInsideBlocks)
8887 {
8888 constexpr char kFS[] = R"(#version 300 es
8889
8890 precision highp float;
8891
8892 uniform int u_zero;
8893 out vec4 my_FragColor;
8894
8895 bool test(int n)
8896 {
8897 switch(n) {
8898 case 0:
8899 {
8900 {
8901 break;
8902 }
8903 }
8904 case 1:
8905 {
8906 return true;
8907 }
8908 case 2:
8909 {
8910 n++;
8911 }
8912 }
8913 return false;
8914 }
8915
8916 void main()
8917 {
8918 my_FragColor = test(u_zero + 1) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
8919 })";
8920
8921 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8922 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
8923 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8924 }
8925
8926 // Test switch/case where a variable is declared inside one of the cases and is accessed by a
8927 // subsequent case.
TEST_P(GLSLTest_ES3,SwitchWithVariableDeclarationInside)8928 TEST_P(GLSLTest_ES3, SwitchWithVariableDeclarationInside)
8929 {
8930 constexpr char kFS[] = R"(#version 300 es
8931
8932 precision highp float;
8933 out vec4 my_FragColor;
8934
8935 uniform int u_zero;
8936
8937 void main()
8938 {
8939 my_FragColor = vec4(1, 0, 0, 1);
8940 switch (u_zero)
8941 {
8942 case 0:
8943 ivec2 i;
8944 i = ivec2(1, 0);
8945 default:
8946 my_FragColor = vec4(0, i[0], 0, 1);
8947 }
8948 })";
8949
8950 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8951 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
8952 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8953 }
8954
8955 // Test nested switch/case where a variable is declared inside one of the cases and is accessed by a
8956 // subsequent case.
TEST_P(GLSLTest_ES3,NestedSwitchWithVariableDeclarationInside)8957 TEST_P(GLSLTest_ES3, NestedSwitchWithVariableDeclarationInside)
8958 {
8959 constexpr char kFS[] = R"(#version 300 es
8960
8961 precision highp float;
8962 out vec4 my_FragColor;
8963
8964 uniform int u_zero;
8965 uniform int u_zero2;
8966
8967 void main()
8968 {
8969 my_FragColor = vec4(1, 0, 0, 1);
8970 switch (u_zero)
8971 {
8972 case 0:
8973 ivec2 i;
8974 i = ivec2(1, 0);
8975 switch (u_zero2)
8976 {
8977 case 0:
8978 int j;
8979 default:
8980 j = 1;
8981 i *= j;
8982 }
8983 default:
8984 my_FragColor = vec4(0, i[0], 0, 1);
8985 }
8986 })";
8987
8988 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8989 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
8990 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8991 }
8992
8993 // Test that an empty switch/case statement is translated in a way that compiles and executes the
8994 // init-statement.
TEST_P(GLSLTest_ES3,EmptySwitch)8995 TEST_P(GLSLTest_ES3, EmptySwitch)
8996 {
8997 constexpr char kFS[] = R"(#version 300 es
8998
8999 precision highp float;
9000
9001 uniform int u_zero;
9002 out vec4 my_FragColor;
9003
9004 void main()
9005 {
9006 int i = u_zero;
9007 switch(++i) {}
9008 my_FragColor = (i == 1) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
9009 })";
9010
9011 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9012 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
9013 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9014 }
9015
9016 // Test that a constant struct inside an expression is handled correctly.
TEST_P(GLSLTest_ES3,ConstStructInsideExpression)9017 TEST_P(GLSLTest_ES3, ConstStructInsideExpression)
9018 {
9019 // Incorrect output color was seen on Android. http://anglebug.com/2226
9020 ANGLE_SKIP_TEST_IF(IsAndroid() && !IsNVIDIA() && IsOpenGLES());
9021
9022 constexpr char kFS[] = R"(#version 300 es
9023
9024 precision highp float;
9025 out vec4 my_FragColor;
9026
9027 uniform float u_zero;
9028
9029 struct S
9030 {
9031 float field;
9032 };
9033
9034 void main()
9035 {
9036 const S constS = S(1.0);
9037 S nonConstS = constS;
9038 nonConstS.field = u_zero;
9039 bool fail = (constS == nonConstS);
9040 my_FragColor = vec4(0, 1, 0, 1);
9041 if (fail)
9042 {
9043 my_FragColor = vec4(1, 0, 0, 1);
9044 }
9045 })";
9046
9047 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9048 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
9049 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9050 }
9051
9052 // Test that a varying struct that's defined as a part of the declaration is handled correctly.
TEST_P(GLSLTest_ES3,VaryingStructWithInlineDefinition)9053 TEST_P(GLSLTest_ES3, VaryingStructWithInlineDefinition)
9054 {
9055 // TODO(anglebug.com/5491): iOS thinks that the precision qualifiers don't match on the
9056 // struct member. Not sure if it's being overly strict.
9057 ANGLE_SKIP_TEST_IF(IsIOS() && IsOpenGLES());
9058 constexpr char kVS[] = R"(#version 300 es
9059 in vec4 inputAttribute;
9060
9061 flat out struct S
9062 {
9063 int field;
9064 } v_s;
9065
9066 void main()
9067 {
9068 v_s.field = 1;
9069 gl_Position = inputAttribute;
9070 })";
9071
9072 constexpr char kFS[] = R"(#version 300 es
9073
9074 precision highp float;
9075 out vec4 my_FragColor;
9076
9077 flat in struct S
9078 {
9079 int field;
9080 } v_s;
9081
9082 void main()
9083 {
9084 bool success = (v_s.field == 1);
9085 my_FragColor = vec4(1, 0, 0, 1);
9086 if (success)
9087 {
9088 my_FragColor = vec4(0, 1, 0, 1);
9089 }
9090 })";
9091
9092 ANGLE_GL_PROGRAM(program, kVS, kFS);
9093 drawQuad(program, "inputAttribute", 0.5f);
9094 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9095 }
9096
9097 // Test that multi variables struct should not crash in separated struct expressions.
TEST_P(GLSLTest_ES3,VaryingStructWithInlineDefinition2)9098 TEST_P(GLSLTest_ES3, VaryingStructWithInlineDefinition2)
9099 {
9100 constexpr char kVS[] = R"(#version 300 es
9101 in vec4 inputAttribute;
9102 flat out struct A
9103 {
9104 int a;
9105 } z1, z2;
9106 void main()
9107 {
9108 z1.a = 1;
9109 z2.a = 2;
9110 gl_Position = inputAttribute;
9111 })";
9112 constexpr char kFS[] = R"(#version 300 es
9113 precision highp float;
9114 out vec4 my_FragColor;
9115 flat in struct A
9116 {
9117 int a;
9118 } z1, z2;
9119 void main()
9120 {
9121 bool success = (z1.a == 1 && z2.a == 2);
9122 my_FragColor = vec4(1, 0, 0, 1);
9123 if (success)
9124 {
9125 my_FragColor = vec4(0, 1, 0, 1);
9126 }
9127 })";
9128 ANGLE_GL_PROGRAM(program, kVS, kFS);
9129 drawQuad(program.get(), "inputAttribute", 0.5f);
9130 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9131 }
9132
9133 // Test mismatched precision in varying is handled correctly.
TEST_P(GLSLTest_ES3,MismatchPrecisionFloat)9134 TEST_P(GLSLTest_ES3, MismatchPrecisionFloat)
9135 {
9136 constexpr char kVS[] = R"(#version 300 es
9137 in vec4 position;
9138 uniform highp float inVal;
9139 out highp float myVarying;
9140
9141 void main()
9142 {
9143 myVarying = inVal;
9144 gl_Position = position;
9145 })";
9146
9147 constexpr char kFS[] = R"(#version 300 es
9148 precision highp float;
9149 out vec4 my_FragColor;
9150 in mediump float myVarying;
9151
9152 void main()
9153 {
9154 my_FragColor = vec4(1, 0, 0, 1);
9155 if (myVarying > 1.0)
9156 {
9157 my_FragColor = vec4(0, 1, 0, 1);
9158 }
9159 })";
9160
9161 ANGLE_GL_PROGRAM(program, kVS, kFS);
9162
9163 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
9164 glClear(GL_COLOR_BUFFER_BIT);
9165 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
9166
9167 glUseProgram(program);
9168 GLint positionLocation = glGetAttribLocation(program, "position");
9169 std::array<Vector3, 6> quadVertices = GetQuadVertices();
9170 for (Vector3 &vertex : quadVertices)
9171 {
9172 vertex.z() = 0.5f;
9173 }
9174 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
9175 glEnableVertexAttribArray(positionLocation);
9176
9177 GLint inValLoc = glGetUniformLocation(program, "inVal");
9178 ASSERT_NE(-1, inValLoc);
9179 glUniform1f(inValLoc, static_cast<GLfloat>(1.003));
9180
9181 glDrawArrays(GL_TRIANGLES, 0, 6);
9182 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9183 }
9184
9185 // Test mismatched precision in varying is handled correctly.
TEST_P(GLSLTest_ES3,MismatchPrecisionlowpFloat)9186 TEST_P(GLSLTest_ES3, MismatchPrecisionlowpFloat)
9187 {
9188 // Note: SPIRV only has relaxed precision so both lowp and mediump turn into "relaxed
9189 // precision", thus this is the same test as MismatchPrecisionFloat but including it for
9190 // completeness in case something changes.
9191 constexpr char kVS[] = R"(#version 300 es
9192 in vec4 position;
9193 uniform highp float inVal;
9194 out highp float myVarying;
9195
9196 void main()
9197 {
9198 myVarying = inVal;
9199 gl_Position = position;
9200 })";
9201
9202 constexpr char kFS[] = R"(#version 300 es
9203 precision highp float;
9204 out vec4 my_FragColor;
9205 in lowp float myVarying;
9206
9207 void main()
9208 {
9209 my_FragColor = vec4(1, 0, 0, 1);
9210 if (myVarying > 1.0)
9211 {
9212 my_FragColor = vec4(0, 1, 0, 1);
9213 }
9214 })";
9215
9216 ANGLE_GL_PROGRAM(program, kVS, kFS);
9217
9218 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
9219 glClear(GL_COLOR_BUFFER_BIT);
9220 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
9221
9222 glUseProgram(program);
9223 GLint positionLocation = glGetAttribLocation(program, "position");
9224 std::array<Vector3, 6> quadVertices = GetQuadVertices();
9225 for (Vector3 &vertex : quadVertices)
9226 {
9227 vertex.z() = 0.5f;
9228 }
9229 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
9230 glEnableVertexAttribArray(positionLocation);
9231
9232 GLint inValLoc = glGetUniformLocation(program, "inVal");
9233 ASSERT_NE(-1, inValLoc);
9234 glUniform1f(inValLoc, static_cast<GLfloat>(1.003));
9235
9236 glDrawArrays(GL_TRIANGLES, 0, 6);
9237 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9238 }
9239
9240 // Test mismatched precision in varying is handled correctly.
TEST_P(GLSLTest_ES3,MismatchPrecisionVec2UnusedVarying)9241 TEST_P(GLSLTest_ES3, MismatchPrecisionVec2UnusedVarying)
9242 {
9243 constexpr char kVS[] = R"(#version 300 es
9244 in vec2 position;
9245 uniform highp float inVal;
9246 out highp float myVarying;
9247 out highp vec2 texCoord;
9248
9249 void main()
9250 {
9251 myVarying = inVal;
9252 gl_Position = vec4(position, 0, 1);
9253 texCoord = position * 0.5 + vec2(0.5);
9254 })";
9255
9256 constexpr char kFS[] = R"(#version 300 es
9257 precision highp float;
9258 out vec4 my_FragColor;
9259 in mediump float myVarying;
9260 in mediump vec2 texCoord;
9261
9262 void main()
9263 {
9264 my_FragColor = vec4(1, 0, 0, 1);
9265 if (myVarying > 1.0)
9266 {
9267 my_FragColor = vec4(0, 1, 0, 1);
9268 }
9269 })";
9270
9271 ANGLE_GL_PROGRAM(program, kVS, kFS);
9272
9273 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
9274 glClear(GL_COLOR_BUFFER_BIT);
9275 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
9276
9277 glUseProgram(program);
9278 GLint positionLocation = glGetAttribLocation(program, "position");
9279 std::array<Vector3, 6> quadVertices = GetQuadVertices();
9280 for (Vector3 &vertex : quadVertices)
9281 {
9282 vertex.z() = 0.5f;
9283 }
9284 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
9285 glEnableVertexAttribArray(positionLocation);
9286
9287 GLint inValLoc = glGetUniformLocation(program, "inVal");
9288 ASSERT_NE(-1, inValLoc);
9289 glUniform1f(inValLoc, static_cast<GLfloat>(1.003));
9290
9291 glDrawArrays(GL_TRIANGLES, 0, 6);
9292 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9293 }
9294
9295 // Test mismatched precision in varying is handled correctly.
TEST_P(GLSLTest_ES3,MismatchPrecisionMedToHigh)9296 TEST_P(GLSLTest_ES3, MismatchPrecisionMedToHigh)
9297 {
9298 constexpr char kVS[] = R"(#version 300 es
9299 in vec2 position;
9300 uniform highp float inVal;
9301 out mediump float myVarying;
9302
9303 void main()
9304 {
9305 myVarying = inVal;
9306 gl_Position = vec4(position, 0, 1);
9307 })";
9308
9309 constexpr char kFS[] = R"(#version 300 es
9310 precision highp float;
9311 out vec4 my_FragColor;
9312 in highp float myVarying;
9313
9314 void main()
9315 {
9316 my_FragColor = vec4(1, 0, 0, 1);
9317 if (myVarying > 1.0)
9318 {
9319 my_FragColor = vec4(0, 1, 0, 1);
9320 }
9321 })";
9322
9323 ANGLE_GL_PROGRAM(program, kVS, kFS);
9324
9325 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
9326 glClear(GL_COLOR_BUFFER_BIT);
9327 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
9328
9329 glUseProgram(program);
9330 GLint positionLocation = glGetAttribLocation(program, "position");
9331 std::array<Vector3, 6> quadVertices = GetQuadVertices();
9332 for (Vector3 &vertex : quadVertices)
9333 {
9334 vertex.z() = 0.5f;
9335 }
9336 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
9337 glEnableVertexAttribArray(positionLocation);
9338
9339 GLint inValLoc = glGetUniformLocation(program, "inVal");
9340 ASSERT_NE(-1, inValLoc);
9341 glUniform1f(inValLoc, static_cast<GLfloat>(1.003));
9342
9343 glDrawArrays(GL_TRIANGLES, 0, 6);
9344 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9345 }
9346
9347 // Test vector/scalar arithmetic (in this case multiplication and addition).
TEST_P(GLSLTest,VectorScalarMultiplyAndAddInLoop)9348 TEST_P(GLSLTest, VectorScalarMultiplyAndAddInLoop)
9349 {
9350 constexpr char kFS[] = R"(precision mediump float;
9351
9352 void main() {
9353 gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
9354 for (int i = 0; i < 2; i++)
9355 {
9356 gl_FragColor += (2.0 * gl_FragCoord.x);
9357 }
9358 if (gl_FragColor.g == gl_FragColor.r &&
9359 gl_FragColor.b == gl_FragColor.r &&
9360 gl_FragColor.a == gl_FragColor.r)
9361 {
9362 gl_FragColor = vec4(0, 1, 0, 1);
9363 }
9364 })";
9365
9366 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
9367 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
9368 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9369 }
9370
9371 // Test vector/scalar arithmetic (in this case compound division and addition).
TEST_P(GLSLTest,VectorScalarDivideAndAddInLoop)9372 TEST_P(GLSLTest, VectorScalarDivideAndAddInLoop)
9373 {
9374 constexpr char kFS[] = R"(precision mediump float;
9375
9376 void main() {
9377 gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
9378 for (int i = 0; i < 2; i++)
9379 {
9380 float x = gl_FragCoord.x;
9381 gl_FragColor = gl_FragColor + (x /= 2.0);
9382 }
9383 if (gl_FragColor.g == gl_FragColor.r &&
9384 gl_FragColor.b == gl_FragColor.r &&
9385 gl_FragColor.a == gl_FragColor.r)
9386 {
9387 gl_FragColor = vec4(0, 1, 0, 1);
9388 }
9389 })";
9390
9391 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
9392 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
9393 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9394 }
9395
9396 // Test a fuzzer-discovered bug with the VectorizeVectorScalarArithmetic transformation.
TEST_P(GLSLTest,VectorScalarArithmeticWithSideEffectInLoop)9397 TEST_P(GLSLTest, VectorScalarArithmeticWithSideEffectInLoop)
9398 {
9399 // The VectorizeVectorScalarArithmetic transformation was generating invalid code in the past
9400 // (notice how sbcd references i outside the for loop. The loop condition doesn't look right
9401 // either):
9402 //
9403 // #version 450
9404 // void main(){
9405 // (gl_Position = vec4(0.0, 0.0, 0.0, 0.0));
9406 // mat3 _utmp = mat3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
9407 // vec3 _ures = vec3(0.0, 0.0, 0.0);
9408 // vec3 sbcd = vec3(_ures[_ui]);
9409 // for (int _ui = 0; (_ures[((_utmp[_ui] += (((sbcd *= _ures[_ui]), (_ures[_ui] = sbcd.x)),
9410 // sbcd)), _ui)], (_ui < 7)); )
9411 // {
9412 // }
9413 // }
9414
9415 constexpr char kVS[] = R"(
9416 void main()
9417 {
9418 mat3 tmp;
9419 vec3 res;
9420 for(int i; res[tmp[i]+=res[i]*=res[i],i],i<7;);
9421 })";
9422
9423 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
9424
9425 const char *sourceArray[1] = {kVS};
9426 GLint lengths[1] = {static_cast<GLint>(sizeof(kVS) - 1)};
9427 glShaderSource(shader, 1, sourceArray, lengths);
9428 glCompileShader(shader);
9429
9430 GLint compileResult;
9431 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
9432 EXPECT_NE(compileResult, 0);
9433 }
9434
9435 // Test that packing of excessive 3-column variables does not overflow the count of 3-column
9436 // variables in VariablePacker
TEST_P(WebGL2GLSLTest,ExcessiveMat3UniformPacking)9437 TEST_P(WebGL2GLSLTest, ExcessiveMat3UniformPacking)
9438 {
9439 std::ostringstream srcStream;
9440
9441 srcStream << "#version 300 es\n";
9442 srcStream << "precision mediump float;\n";
9443 srcStream << "out vec4 finalColor;\n";
9444 srcStream << "in vec4 color;\n";
9445 srcStream << "uniform mat4 r[254];\n";
9446
9447 srcStream << "uniform mat3 ";
9448 constexpr size_t kNumUniforms = 10000;
9449 for (size_t i = 0; i < kNumUniforms; ++i)
9450 {
9451 if (i > 0)
9452 {
9453 srcStream << ", ";
9454 }
9455 srcStream << "m3a_" << i << "[256]";
9456 }
9457 srcStream << ";\n";
9458
9459 srcStream << "void main(void) { finalColor = color; }\n";
9460 std::string src = std::move(srcStream).str();
9461
9462 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
9463
9464 const char *sourceArray[1] = {src.c_str()};
9465 GLint lengths[1] = {static_cast<GLint>(src.length())};
9466 glShaderSource(shader, 1, sourceArray, lengths);
9467 glCompileShader(shader);
9468
9469 GLint compileResult;
9470 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
9471 EXPECT_EQ(compileResult, 0);
9472 }
9473
9474 // Test that a varying with a flat qualifier that is used as an operand of a folded ternary operator
9475 // is handled correctly.
TEST_P(GLSLTest_ES3,FlatVaryingUsedInFoldedTernary)9476 TEST_P(GLSLTest_ES3, FlatVaryingUsedInFoldedTernary)
9477 {
9478 constexpr char kVS[] = R"(#version 300 es
9479
9480 in vec4 inputAttribute;
9481
9482 flat out int v;
9483
9484 void main()
9485 {
9486 v = 1;
9487 gl_Position = inputAttribute;
9488 })";
9489
9490 constexpr char kFS[] = R"(#version 300 es
9491
9492 precision highp float;
9493 out vec4 my_FragColor;
9494
9495 flat in int v;
9496
9497 void main()
9498 {
9499 my_FragColor = vec4(0, (true ? v : 0), 0, 1);
9500 })";
9501
9502 ANGLE_GL_PROGRAM(program, kVS, kFS);
9503 drawQuad(program, "inputAttribute", 0.5f);
9504 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9505 }
9506
9507 // Verify that the link error message from last link failure is cleared when the new link is
9508 // finished.
TEST_P(GLSLTest,ClearLinkErrorLog)9509 TEST_P(GLSLTest, ClearLinkErrorLog)
9510 {
9511 constexpr char kVS[] = R"(attribute vec4 vert_in;
9512 varying vec4 vert_out;
9513 void main()
9514 {
9515 gl_Position = vert_in;
9516 vert_out = vert_in;
9517 })";
9518
9519 constexpr char kFS[] = R"(precision mediump float;
9520 varying vec4 frag_in;
9521 void main()
9522 {
9523 gl_FragColor = frag_in;
9524 })";
9525
9526 GLuint vs = CompileShader(GL_VERTEX_SHADER, kVS);
9527 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
9528
9529 GLuint program = glCreateProgram();
9530
9531 // The first time the program link fails because of lack of fragment shader.
9532 glAttachShader(program, vs);
9533 glLinkProgram(program);
9534 GLint linkStatus = GL_TRUE;
9535 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
9536 ASSERT_FALSE(linkStatus);
9537
9538 const std::string lackOfFragmentShader = QueryErrorMessage(program);
9539 EXPECT_TRUE(lackOfFragmentShader != "");
9540
9541 // The second time the program link fails because of the mismatch of the varying types.
9542 glAttachShader(program, fs);
9543 glLinkProgram(program);
9544 linkStatus = GL_TRUE;
9545 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
9546 ASSERT_FALSE(linkStatus);
9547
9548 const std::string varyingTypeMismatch = QueryErrorMessage(program);
9549 EXPECT_TRUE(varyingTypeMismatch != "");
9550
9551 EXPECT_EQ(std::string::npos, varyingTypeMismatch.find(lackOfFragmentShader));
9552
9553 glDetachShader(program, vs);
9554 glDetachShader(program, fs);
9555 glDeleteShader(vs);
9556 glDeleteShader(fs);
9557 glDeleteProgram(program);
9558
9559 ASSERT_GL_NO_ERROR();
9560 }
9561
9562 // Verify that a valid program still draws correctly after a shader link error
TEST_P(GLSLTest,DrawAfterShaderLinkError)9563 TEST_P(GLSLTest, DrawAfterShaderLinkError)
9564 {
9565 constexpr char kVS[] = R"(attribute vec4 position;
9566 varying vec4 vColor;
9567 void main()
9568 {
9569 vColor = vec4(0.0, 1.0, 0.0, 1.0);
9570 gl_Position = position;
9571 })";
9572 constexpr char kFS[] = R"(precision mediump float;
9573 varying vec4 vColor;
9574 void main()
9575 {
9576 gl_FragColor = vColor;
9577 })";
9578 constexpr char kBadFS[] = R"(WILL NOT COMPILE;)";
9579
9580 GLuint fsBad = glCreateShader(GL_FRAGMENT_SHADER);
9581
9582 // Create bad fragment shader
9583 {
9584 const char *sourceArray[1] = {kBadFS};
9585 glShaderSource(fsBad, 1, sourceArray, nullptr);
9586 glCompileShader(fsBad);
9587
9588 GLint compileResult;
9589 glGetShaderiv(fsBad, GL_COMPILE_STATUS, &compileResult);
9590 ASSERT_FALSE(compileResult);
9591 }
9592
9593 ANGLE_GL_PROGRAM(program, kVS, kFS);
9594 GLuint fs = GetProgramShader(program, GL_FRAGMENT_SHADER);
9595
9596 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
9597 glClear(GL_COLOR_BUFFER_BIT);
9598 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
9599
9600 glUseProgram(program);
9601 GLint positionLocation = glGetAttribLocation(program, "position");
9602 std::array<Vector3, 6> quadVertices = GetQuadVertices();
9603 for (Vector3 &vertex : quadVertices)
9604 {
9605 vertex.z() = 0.5f;
9606 }
9607 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
9608 glEnableVertexAttribArray(positionLocation);
9609 glDrawArrays(GL_TRIANGLES, 0, 6);
9610 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9611
9612 glDetachShader(program, fs);
9613 glAttachShader(program, fsBad);
9614 glLinkProgram(program);
9615 GLint linkStatus = GL_TRUE;
9616 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
9617 ASSERT_FALSE(linkStatus);
9618
9619 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
9620 glClear(GL_COLOR_BUFFER_BIT);
9621 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
9622
9623 glDrawArrays(GL_TRIANGLES, 0, 6);
9624 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9625 }
9626
9627 // Validate error messages when the link mismatch occurs on the type of a non-struct varying.
TEST_P(GLSLTest,ErrorMessageOfVaryingMismatch)9628 TEST_P(GLSLTest, ErrorMessageOfVaryingMismatch)
9629 {
9630 constexpr char kVS[] = R"(attribute vec4 inputAttribute;
9631 varying vec4 vertex_out;
9632 void main()
9633 {
9634 vertex_out = inputAttribute;
9635 gl_Position = inputAttribute;
9636 })";
9637
9638 constexpr char kFS[] = R"(precision mediump float;
9639 varying float vertex_out;
9640 void main()
9641 {
9642 gl_FragColor = vec4(vertex_out, 0.0, 0.0, 1.0);
9643 })";
9644
9645 validateComponentsInErrorMessage(kVS, kFS, "Types", "varying 'vertex_out'");
9646 }
9647
9648 // Validate error messages when the link mismatch occurs on the name of a varying field.
TEST_P(GLSLTest_ES3,ErrorMessageOfVaryingStructFieldNameMismatch)9649 TEST_P(GLSLTest_ES3, ErrorMessageOfVaryingStructFieldNameMismatch)
9650 {
9651 constexpr char kVS[] = R"(#version 300 es
9652 in vec4 inputAttribute;
9653 struct S {
9654 float val1;
9655 vec4 val2;
9656 };
9657 out S vertex_out;
9658 void main()
9659 {
9660 vertex_out.val2 = inputAttribute;
9661 vertex_out.val1 = inputAttribute[0];
9662 gl_Position = inputAttribute;
9663 })";
9664
9665 constexpr char kFS[] = R"(#version 300 es
9666 precision mediump float;
9667 struct S {
9668 float val1;
9669 vec4 val3;
9670 };
9671 in S vertex_out;
9672 layout (location = 0) out vec4 frag_out;
9673 void main()
9674 {
9675 frag_out = vec4(vertex_out.val1, 0.0, 0.0, 1.0);
9676 })";
9677
9678 validateComponentsInErrorMessage(kVS, kFS, "Field names", "varying 'vertex_out'");
9679 }
9680
9681 // Validate error messages when the link mismatch occurs on the type of a varying field.
TEST_P(GLSLTest_ES3,ErrorMessageOfVaryingStructFieldMismatch)9682 TEST_P(GLSLTest_ES3, ErrorMessageOfVaryingStructFieldMismatch)
9683 {
9684 constexpr char kVS[] = R"(#version 300 es
9685 in vec4 inputAttribute;
9686 struct S {
9687 float val1;
9688 vec4 val2;
9689 };
9690 out S vertex_out;
9691 void main()
9692 {
9693 vertex_out.val2 = inputAttribute;
9694 vertex_out.val1 = inputAttribute[0];
9695 gl_Position = inputAttribute;
9696 })";
9697
9698 constexpr char kFS[] = R"(#version 300 es
9699 precision mediump float;
9700 struct S {
9701 float val1;
9702 vec2 val2;
9703 };
9704 in S vertex_out;
9705 layout (location = 0) out vec4 frag_out;
9706 void main()
9707 {
9708 frag_out = vec4(vertex_out.val1, 0.0, 0.0, 1.0);
9709 })";
9710
9711 validateComponentsInErrorMessage(kVS, kFS, "Types",
9712 "varying 'vertex_out' member 'vertex_out.val2'");
9713 }
9714
9715 // Validate error messages when the link mismatch occurs on the name of a struct member of a uniform
9716 // field.
TEST_P(GLSLTest,ErrorMessageOfLinkUniformStructFieldNameMismatch)9717 TEST_P(GLSLTest, ErrorMessageOfLinkUniformStructFieldNameMismatch)
9718 {
9719 constexpr char kVS[] = R"(
9720 struct T
9721 {
9722 vec2 t1;
9723 vec3 t2;
9724 };
9725 struct S {
9726 T val1;
9727 vec4 val2;
9728 };
9729 uniform S uni;
9730
9731 attribute vec4 inputAttribute;
9732 varying vec4 vertex_out;
9733 void main()
9734 {
9735 vertex_out = uni.val2;
9736 gl_Position = inputAttribute;
9737 })";
9738
9739 constexpr char kFS[] = R"(precision highp float;
9740 struct T
9741 {
9742 vec2 t1;
9743 vec3 t3;
9744 };
9745 struct S {
9746 T val1;
9747 vec4 val2;
9748 };
9749 uniform S uni;
9750
9751 varying vec4 vertex_out;
9752 void main()
9753 {
9754 gl_FragColor = vec4(uni.val1.t1[0], 0.0, 0.0, 1.0);
9755 })";
9756
9757 validateComponentsInErrorMessage(kVS, kFS, "Field names", "uniform 'uni' member 'uni.val1'");
9758 }
9759
9760 // Validate error messages when the link mismatch occurs on the type of a non-struct uniform block
9761 // field.
TEST_P(GLSLTest_ES3,ErrorMessageOfLinkInterfaceBlockFieldMismatch)9762 TEST_P(GLSLTest_ES3, ErrorMessageOfLinkInterfaceBlockFieldMismatch)
9763 {
9764 constexpr char kVS[] = R"(#version 300 es
9765 uniform S {
9766 vec2 val1;
9767 vec4 val2;
9768 } uni;
9769
9770 in vec4 inputAttribute;
9771 out vec4 vertex_out;
9772 void main()
9773 {
9774 vertex_out = uni.val2;
9775 gl_Position = inputAttribute;
9776 })";
9777
9778 constexpr char kFS[] = R"(#version 300 es
9779 precision highp float;
9780 uniform S {
9781 vec2 val1;
9782 vec3 val2;
9783 } uni;
9784
9785 in vec4 vertex_out;
9786 layout (location = 0) out vec4 frag_out;
9787 void main()
9788 {
9789 frag_out = vec4(uni.val1[0], 0.0, 0.0, 1.0);
9790 })";
9791
9792 validateComponentsInErrorMessage(kVS, kFS, "Types", "uniform block 'S' member 'S.val2'");
9793 }
9794
9795 // Validate error messages when the link mismatch occurs on the type of a member of a uniform block
9796 // struct field.
TEST_P(GLSLTest_ES3,ErrorMessageOfLinkInterfaceBlockStructFieldMismatch)9797 TEST_P(GLSLTest_ES3, ErrorMessageOfLinkInterfaceBlockStructFieldMismatch)
9798 {
9799 constexpr char kVS[] = R"(#version 300 es
9800 struct T
9801 {
9802 vec2 t1;
9803 vec3 t2;
9804 };
9805 uniform S {
9806 T val1;
9807 vec4 val2;
9808 } uni;
9809
9810 in vec4 inputAttribute;
9811 out vec4 vertex_out;
9812 void main()
9813 {
9814 vertex_out = uni.val2;
9815 gl_Position = inputAttribute;
9816 })";
9817
9818 constexpr char kFS[] = R"(#version 300 es
9819 precision highp float;
9820 struct T
9821 {
9822 vec2 t1;
9823 vec4 t2;
9824 };
9825 uniform S {
9826 T val1;
9827 vec4 val2;
9828 } uni;
9829
9830 in vec4 vertex_out;
9831 layout (location = 0) out vec4 frag_out;
9832 void main()
9833 {
9834 frag_out = vec4(uni.val1.t1[0], 0.0, 0.0, 1.0);
9835 })";
9836
9837 validateComponentsInErrorMessage(kVS, kFS, "Types", "uniform block 'S' member 'S.val1.t2'");
9838 }
9839
9840 // Test a vertex shader that doesn't declare any varyings with a fragment shader that statically
9841 // uses a varying, but in a statement that gets trivially optimized out by the compiler.
TEST_P(GLSLTest_ES3,FragmentShaderStaticallyUsesVaryingMissingFromVertex)9842 TEST_P(GLSLTest_ES3, FragmentShaderStaticallyUsesVaryingMissingFromVertex)
9843 {
9844 constexpr char kVS[] = R"(#version 300 es
9845 precision mediump float;
9846
9847 void main()
9848 {
9849 gl_Position = vec4(0, 1, 0, 1);
9850 })";
9851
9852 constexpr char kFS[] = R"(#version 300 es
9853 precision mediump float;
9854 in float foo;
9855 out vec4 my_FragColor;
9856
9857 void main()
9858 {
9859 if (false)
9860 {
9861 float unreferenced = foo;
9862 }
9863 my_FragColor = vec4(0, 1, 0, 1);
9864 })";
9865
9866 validateComponentsInErrorMessage(kVS, kFS, "does not match any", "foo");
9867 }
9868
9869 // Test a varying that is statically used but not active in the fragment shader.
TEST_P(GLSLTest_ES3,VaryingStaticallyUsedButNotActiveInFragmentShader)9870 TEST_P(GLSLTest_ES3, VaryingStaticallyUsedButNotActiveInFragmentShader)
9871 {
9872 constexpr char kVS[] = R"(#version 300 es
9873 precision mediump float;
9874 in vec4 iv;
9875 out vec4 v;
9876 void main()
9877 {
9878 gl_Position = iv;
9879 v = iv;
9880 })";
9881
9882 constexpr char kFS[] = R"(#version 300 es
9883 precision mediump float;
9884 in vec4 v;
9885 out vec4 color;
9886 void main()
9887 {
9888 color = true ? vec4(0.0) : v;
9889 })";
9890
9891 ANGLE_GL_PROGRAM(program, kVS, kFS);
9892 }
9893
9894 // Test that linking varyings by location works.
TEST_P(GLSLTest_ES31,LinkVaryingsByLocation)9895 TEST_P(GLSLTest_ES31, LinkVaryingsByLocation)
9896 {
9897 constexpr char kVS[] = R"(#version 310 es
9898 precision highp float;
9899 in vec4 position;
9900 layout(location = 1) out vec4 shaderOutput;
9901 void main() {
9902 gl_Position = position;
9903 shaderOutput = vec4(0.0, 1.0, 0.0, 1.0);
9904 })";
9905
9906 constexpr char kFS[] = R"(#version 310 es
9907 precision highp float;
9908 layout(location = 1) in vec4 shaderInput;
9909 out vec4 outColor;
9910 void main() {
9911 outColor = shaderInput;
9912 })";
9913
9914 ANGLE_GL_PROGRAM(program, kVS, kFS);
9915 drawQuad(program, "position", 0.5f);
9916 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9917 }
9918
9919 // Test nesting floor() calls with a large multiplier inside.
TEST_P(GLSLTest_ES3,NestedFloorWithLargeMultiplierInside)9920 TEST_P(GLSLTest_ES3, NestedFloorWithLargeMultiplierInside)
9921 {
9922 // D3D11 seems to ignore the floor() calls in this particular case, so one of the corners ends
9923 // up red. http://crbug.com/838885
9924 ANGLE_SKIP_TEST_IF(IsD3D11());
9925
9926 constexpr char kFS[] = R"(#version 300 es
9927 precision highp float;
9928 out vec4 my_FragColor;
9929 void main()
9930 {
9931 vec2 coord = gl_FragCoord.xy / 500.0;
9932 my_FragColor = vec4(1, 0, 0, 1);
9933 if (coord.y + 0.1 > floor(1e-6 * floor(coord.x*4e5)))
9934 {
9935 my_FragColor = vec4(0, 1, 0, 1);
9936 }
9937 })";
9938
9939 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9940 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
9941 // Verify that all the corners of the rendered result are green.
9942 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9943 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
9944 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, 0, GLColor::green);
9945 EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() - 1, GLColor::green);
9946 }
9947
9948 // Verify that a link error is generated when the sum of the number of active image uniforms and
9949 // active shader storage blocks in a rendering pipeline exceeds
9950 // GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES.
TEST_P(GLSLTest_ES31,ExceedCombinedShaderOutputResourcesInVSAndFS)9951 TEST_P(GLSLTest_ES31, ExceedCombinedShaderOutputResourcesInVSAndFS)
9952 {
9953 // TODO(jiawei.shao@intel.com): enable this test when shader storage buffer is supported on
9954 // D3D11 back-ends.
9955 ANGLE_SKIP_TEST_IF(IsD3D11());
9956
9957 GLint maxVertexShaderStorageBlocks;
9958 GLint maxVertexImageUniforms;
9959 GLint maxFragmentShaderStorageBlocks;
9960 GLint maxFragmentImageUniforms;
9961 GLint maxCombinedShaderStorageBlocks;
9962 GLint maxCombinedImageUniforms;
9963 glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &maxVertexShaderStorageBlocks);
9964 glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &maxVertexImageUniforms);
9965 glGetIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &maxFragmentShaderStorageBlocks);
9966 glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &maxFragmentImageUniforms);
9967 glGetIntegerv(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, &maxCombinedShaderStorageBlocks);
9968 glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS, &maxCombinedImageUniforms);
9969
9970 ASSERT_GE(maxCombinedShaderStorageBlocks, maxVertexShaderStorageBlocks);
9971 ASSERT_GE(maxCombinedShaderStorageBlocks, maxFragmentShaderStorageBlocks);
9972 ASSERT_GE(maxCombinedImageUniforms, maxVertexImageUniforms);
9973 ASSERT_GE(maxCombinedImageUniforms, maxFragmentImageUniforms);
9974
9975 GLint vertexSSBOs = maxVertexShaderStorageBlocks;
9976 GLint fragmentSSBOs = maxFragmentShaderStorageBlocks;
9977 // Limit the sum of ssbos in vertex and fragment shaders to maxCombinedShaderStorageBlocks.
9978 if (vertexSSBOs + fragmentSSBOs > maxCombinedShaderStorageBlocks)
9979 {
9980 fragmentSSBOs = maxCombinedShaderStorageBlocks - vertexSSBOs;
9981 }
9982
9983 GLint vertexImages = maxVertexImageUniforms;
9984 GLint fragmentImages = maxFragmentImageUniforms;
9985 // Limit the sum of images in vertex and fragment shaders to maxCombinedImageUniforms.
9986 if (vertexImages + fragmentImages > maxCombinedImageUniforms)
9987 {
9988 vertexImages = maxCombinedImageUniforms - fragmentImages;
9989 }
9990
9991 GLint maxDrawBuffers;
9992 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
9993
9994 GLint maxCombinedShaderOutputResources;
9995 glGetIntegerv(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, &maxCombinedShaderOutputResources);
9996 ASSERT_GL_NO_ERROR();
9997
9998 ANGLE_SKIP_TEST_IF(vertexSSBOs + fragmentSSBOs + vertexImages + fragmentImages +
9999 maxDrawBuffers <=
10000 maxCombinedShaderOutputResources);
10001
10002 std::ostringstream vertexStream;
10003 vertexStream << "#version 310 es\n";
10004 for (int i = 0; i < vertexSSBOs; ++i)
10005 {
10006 vertexStream << "layout(shared, binding = " << i << ") buffer blockName" << i
10007 << "{\n"
10008 " float data;\n"
10009 "} ssbo"
10010 << i << ";\n";
10011 }
10012 vertexStream << "layout(r32f, binding = 0) uniform highp image2D imageArray[" << vertexImages
10013 << "];\n";
10014 vertexStream << "void main()\n"
10015 "{\n"
10016 " float val = 0.1;\n"
10017 " vec4 val2 = vec4(0.0);\n";
10018 for (int i = 0; i < vertexSSBOs; ++i)
10019 {
10020 vertexStream << " val += ssbo" << i << ".data; \n";
10021 }
10022 for (int i = 0; i < vertexImages; ++i)
10023 {
10024 vertexStream << " val2 += imageLoad(imageArray[" << i << "], ivec2(0, 0)); \n";
10025 }
10026 vertexStream << " gl_Position = vec4(val, val2);\n"
10027 "}\n";
10028
10029 std::ostringstream fragmentStream;
10030 fragmentStream << "#version 310 es\n" << "precision highp float;\n";
10031 for (int i = 0; i < fragmentSSBOs; ++i)
10032 {
10033 fragmentStream << "layout(shared, binding = " << i << ") buffer blockName" << i
10034 << "{\n"
10035 " float data;\n"
10036 "} ssbo"
10037 << i << ";\n";
10038 }
10039 fragmentStream << "layout(r32f, binding = 0) uniform highp image2D imageArray["
10040 << fragmentImages << "];\n";
10041 fragmentStream << "layout (location = 0) out vec4 foutput[" << maxDrawBuffers << "];\n";
10042
10043 fragmentStream << "void main()\n"
10044 "{\n"
10045 " float val = 0.1;\n"
10046 " vec4 val2 = vec4(0.0);\n";
10047 for (int i = 0; i < fragmentSSBOs; ++i)
10048 {
10049 fragmentStream << " val += ssbo" << i << ".data; \n";
10050 }
10051 for (int i = 0; i < fragmentImages; ++i)
10052 {
10053 fragmentStream << " val2 += imageLoad(imageArray[" << i << "], ivec2(0, 0)); \n";
10054 }
10055 for (int i = 0; i < maxDrawBuffers; ++i)
10056 {
10057 fragmentStream << " foutput[" << i << "] = vec4(val, val2);\n";
10058 }
10059 fragmentStream << "}\n";
10060
10061 GLuint program = CompileProgram(vertexStream.str().c_str(), fragmentStream.str().c_str());
10062 EXPECT_EQ(0u, program);
10063
10064 ASSERT_GL_NO_ERROR();
10065 }
10066
10067 // Test that assigning an assignment expression to a swizzled vector field in a user-defined
10068 // function works correctly.
TEST_P(GLSLTest_ES3,AssignToSwizzled)10069 TEST_P(GLSLTest_ES3, AssignToSwizzled)
10070 {
10071 constexpr char kFS[] = R"(#version 300 es
10072 precision highp float;
10073 out vec4 my_FragColor;
10074
10075 uniform float uzero;
10076
10077 vec3 fun(float s, float v)
10078 {
10079 vec3 r = vec3(0);
10080 if (s < 1.0) {
10081 r.x = r.y = r.z = v;
10082 return r;
10083 }
10084 return r;
10085 }
10086
10087 void main()
10088 {
10089 my_FragColor.a = 1.0;
10090 my_FragColor.rgb = fun(uzero, 1.0);
10091 })";
10092
10093 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
10094 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
10095 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
10096 }
10097
10098 // Similar to AssignToSwizzled, but uses other assignment operators than `=`.
TEST_P(GLSLTest_ES3,AssignToSwizzled2)10099 TEST_P(GLSLTest_ES3, AssignToSwizzled2)
10100 {
10101 constexpr char kFS[] = R"(#version 300 es
10102 precision highp float;
10103 out vec4 my_FragColor;
10104
10105 uniform float uzero;
10106
10107 vec3 fun(float s, float v)
10108 {
10109 vec3 r = vec3(0.125, 0.5, 0.);
10110 if (s < 1.0) {
10111 r.x /= r.y *= r.z += v;
10112 return r;
10113 }
10114 return r;
10115 }
10116
10117 void main()
10118 {
10119 my_FragColor.a = 1.0;
10120 my_FragColor.rgb = fun(uzero, 1.0);
10121 })";
10122
10123 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
10124 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
10125 EXPECT_PIXEL_NEAR(0, 0, 63, 127, 255, 255, 1);
10126 }
10127
10128 // Test a fragment shader that returns inside if (that being the only branch that actually gets
10129 // executed). Regression test for http://anglebug.com/2325
TEST_P(GLSLTest,IfElseIfAndReturn)10130 TEST_P(GLSLTest, IfElseIfAndReturn)
10131 {
10132 constexpr char kVS[] = R"(attribute vec4 a_position;
10133 varying vec2 vPos;
10134 void main()
10135 {
10136 gl_Position = a_position;
10137 vPos = a_position.xy;
10138 })";
10139
10140 constexpr char kFS[] = R"(precision mediump float;
10141 varying vec2 vPos;
10142 void main()
10143 {
10144 if (vPos.x < 1.0) // This colors the whole canvas green
10145 {
10146 gl_FragColor = vec4(0, 1, 0, 1);
10147 return;
10148 }
10149 else if (vPos.x < 1.1) // This should have no effect
10150 {
10151 gl_FragColor = vec4(1, 0, 0, 1);
10152 }
10153 })";
10154
10155 ANGLE_GL_PROGRAM(program, kVS, kFS);
10156 drawQuad(program, "a_position", 0.5f);
10157 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10158 }
10159
10160 // Test that if-else blocks whose contents get pruned due to compile-time constant conditions work.
TEST_P(GLSLTest,IfElsePrunedBlocks)10161 TEST_P(GLSLTest, IfElsePrunedBlocks)
10162 {
10163 constexpr char kFS[] = R"(precision mediump float;
10164 uniform float u;
10165 void main()
10166 {
10167 // if with only a pruned true block
10168 if (u > 0.0)
10169 if (false) discard;
10170
10171 // if with a pruned true block and a false block
10172 if (u > 0.0)
10173 {
10174 if (false) discard;
10175 }
10176 else
10177 ;
10178
10179 // if with a true block and a pruned false block
10180 if (u > 0.0)
10181 ;
10182 else
10183 if (false) discard;
10184
10185 // if with a pruned true block and a pruned false block
10186 if (u > 0.0)
10187 {
10188 if (false) discard;
10189 }
10190 else
10191 if (false) discard;
10192
10193 gl_FragColor = vec4(0, 1, 0, 1);
10194 })";
10195
10196 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
10197 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
10198 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10199 }
10200
10201 // Tests that PointCoord behaves the same betweeen a user FBO and the back buffer.
TEST_P(GLSLTest,PointCoordConsistency)10202 TEST_P(GLSLTest, PointCoordConsistency)
10203 {
10204 constexpr char kPointCoordVS[] = R"(attribute vec2 position;
10205 uniform vec2 viewportSize;
10206 void main()
10207 {
10208 gl_Position = vec4(position, 0, 1);
10209 gl_PointSize = viewportSize.x;
10210 })";
10211
10212 constexpr char kPointCoordFS[] = R"(void main()
10213 {
10214 gl_FragColor = vec4(gl_PointCoord.xy, 0, 1);
10215 })";
10216
10217 ANGLE_GL_PROGRAM(program, kPointCoordVS, kPointCoordFS);
10218 glUseProgram(program);
10219
10220 GLint uniLoc = glGetUniformLocation(program, "viewportSize");
10221 ASSERT_NE(-1, uniLoc);
10222 glUniform2f(uniLoc, static_cast<GLfloat>(getWindowWidth()),
10223 static_cast<GLfloat>(getWindowHeight()));
10224
10225 // Draw to backbuffer.
10226 glClear(GL_COLOR_BUFFER_BIT);
10227 glDrawArrays(GL_POINTS, 0, 1);
10228 ASSERT_GL_NO_ERROR();
10229
10230 std::vector<GLColor> backbufferData(getWindowWidth() * getWindowHeight());
10231 glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
10232 backbufferData.data());
10233
10234 GLTexture tex;
10235 glBindTexture(GL_TEXTURE_2D, tex);
10236 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
10237 GL_UNSIGNED_BYTE, nullptr);
10238
10239 GLFramebuffer fbo;
10240 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
10241 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
10242 ASSERT_GL_NO_ERROR();
10243 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
10244
10245 // Draw to user FBO.
10246 glClear(GL_COLOR_BUFFER_BIT);
10247 glDrawArrays(GL_POINTS, 0, 1);
10248 ASSERT_GL_NO_ERROR();
10249
10250 std::vector<GLColor> userFBOData(getWindowWidth() * getWindowHeight());
10251 glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
10252 userFBOData.data());
10253
10254 ASSERT_GL_NO_ERROR();
10255 ASSERT_EQ(userFBOData.size(), backbufferData.size());
10256 EXPECT_EQ(userFBOData, backbufferData);
10257 }
10258
SubrectEquals(const std::vector<GLColor> & bigArray,const std::vector<GLColor> & smallArray,int bigSize,int offset,int smallSize)10259 bool SubrectEquals(const std::vector<GLColor> &bigArray,
10260 const std::vector<GLColor> &smallArray,
10261 int bigSize,
10262 int offset,
10263 int smallSize)
10264 {
10265 int badPixels = 0;
10266 for (int y = 0; y < smallSize; y++)
10267 {
10268 for (int x = 0; x < smallSize; x++)
10269 {
10270 int bigOffset = (y + offset) * bigSize + x + offset;
10271 int smallOffset = y * smallSize + x;
10272 if (bigArray[bigOffset] != smallArray[smallOffset])
10273 badPixels++;
10274 }
10275 }
10276 return badPixels == 0;
10277 }
10278
10279 // Tests that FragCoord behaves the same betweeen a user FBO and the back buffer.
TEST_P(GLSLTest,FragCoordConsistency)10280 TEST_P(GLSLTest, FragCoordConsistency)
10281 {
10282 constexpr char kFragCoordShader[] = R"(uniform mediump vec2 viewportSize;
10283 void main()
10284 {
10285 gl_FragColor = vec4(gl_FragCoord.xy / viewportSize, 0, 1);
10286 })";
10287
10288 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragCoordShader);
10289 glUseProgram(program);
10290
10291 GLint uniLoc = glGetUniformLocation(program, "viewportSize");
10292 ASSERT_NE(-1, uniLoc);
10293 glUniform2f(uniLoc, static_cast<GLfloat>(getWindowWidth()),
10294 static_cast<GLfloat>(getWindowHeight()));
10295
10296 // Draw to backbuffer.
10297 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
10298 ASSERT_GL_NO_ERROR();
10299
10300 std::vector<GLColor> backbufferData(getWindowWidth() * getWindowHeight());
10301 glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
10302 backbufferData.data());
10303
10304 GLTexture tex;
10305 glBindTexture(GL_TEXTURE_2D, tex);
10306 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
10307 GL_UNSIGNED_BYTE, nullptr);
10308
10309 GLFramebuffer fbo;
10310 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
10311 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
10312 ASSERT_GL_NO_ERROR();
10313 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
10314
10315 // Draw to user FBO.
10316 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
10317 ASSERT_GL_NO_ERROR();
10318
10319 std::vector<GLColor> userFBOData(getWindowWidth() * getWindowHeight());
10320 glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
10321 userFBOData.data());
10322
10323 ASSERT_GL_NO_ERROR();
10324 ASSERT_EQ(userFBOData.size(), backbufferData.size());
10325 EXPECT_EQ(userFBOData, backbufferData)
10326 << "FragCoord should be the same to default and user FBO";
10327
10328 // Repeat the same test but with a smaller viewport.
10329 ASSERT_EQ(getWindowHeight(), getWindowWidth());
10330 const int kQuarterSize = getWindowWidth() >> 2;
10331 glViewport(kQuarterSize, kQuarterSize, kQuarterSize * 2, kQuarterSize * 2);
10332
10333 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
10334 glClear(GL_COLOR_BUFFER_BIT);
10335 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
10336
10337 std::vector<GLColor> userFBOViewportData(kQuarterSize * kQuarterSize * 4);
10338 glReadPixels(kQuarterSize, kQuarterSize, kQuarterSize * 2, kQuarterSize * 2, GL_RGBA,
10339 GL_UNSIGNED_BYTE, userFBOViewportData.data());
10340
10341 glBindFramebuffer(GL_FRAMEBUFFER, 0);
10342 glClear(GL_COLOR_BUFFER_BIT);
10343 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
10344
10345 std::vector<GLColor> defaultFBOViewportData(kQuarterSize * kQuarterSize * 4);
10346 glReadPixels(kQuarterSize, kQuarterSize, kQuarterSize * 2, kQuarterSize * 2, GL_RGBA,
10347 GL_UNSIGNED_BYTE, defaultFBOViewportData.data());
10348 ASSERT_GL_NO_ERROR();
10349 EXPECT_EQ(userFBOViewportData, defaultFBOViewportData)
10350 << "FragCoord should be the same to default and user FBO even with a custom viewport";
10351
10352 // Check that the subrectangles are the same between the viewport and non-viewport modes.
10353 EXPECT_TRUE(SubrectEquals(userFBOData, userFBOViewportData, getWindowWidth(), kQuarterSize,
10354 kQuarterSize * 2));
10355 EXPECT_TRUE(SubrectEquals(backbufferData, defaultFBOViewportData, getWindowWidth(),
10356 kQuarterSize, kQuarterSize * 2));
10357 }
10358
10359 // Ensure that using defined in a macro works in this simple case. This mirrors a dEQP test.
TEST_P(GLSLTest,DefinedInMacroSucceeds)10360 TEST_P(GLSLTest, DefinedInMacroSucceeds)
10361 {
10362 constexpr char kVS[] = R"(precision mediump float;
10363 attribute highp vec4 position;
10364 varying vec2 out0;
10365
10366 void main()
10367 {
10368 #define AAA defined(BBB)
10369
10370 #if !AAA
10371 out0 = vec2(0.0, 1.0);
10372 #else
10373 out0 = vec2(1.0, 0.0);
10374 #endif
10375 gl_Position = position;
10376 })";
10377
10378 constexpr char kFS[] = R"(precision mediump float;
10379 varying vec2 out0;
10380 void main()
10381 {
10382 gl_FragColor = vec4(out0, 0, 1);
10383 })";
10384
10385 ANGLE_GL_PROGRAM(program, kVS, kFS);
10386 drawQuad(program, "position", 0.5f);
10387 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10388 }
10389
10390 // Validate the defined operator is evaluated when the macro is called, not when defined.
TEST_P(GLSLTest,DefinedInMacroWithUndef)10391 TEST_P(GLSLTest, DefinedInMacroWithUndef)
10392 {
10393 constexpr char kVS[] = R"(precision mediump float;
10394 attribute highp vec4 position;
10395 varying vec2 out0;
10396
10397 void main()
10398 {
10399 #define BBB 1
10400 #define AAA defined(BBB)
10401 #undef BBB
10402
10403 #if AAA
10404 out0 = vec2(1.0, 0.0);
10405 #else
10406 out0 = vec2(0.0, 1.0);
10407 #endif
10408 gl_Position = position;
10409 })";
10410
10411 constexpr char kFS[] = R"(precision mediump float;
10412 varying vec2 out0;
10413 void main()
10414 {
10415 gl_FragColor = vec4(out0, 0, 1);
10416 })";
10417
10418 ANGLE_GL_PROGRAM(program, kVS, kFS);
10419 drawQuad(program, "position", 0.5f);
10420 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10421 }
10422
10423 // Validate the defined operator is evaluated when the macro is called, not when defined.
TEST_P(GLSLTest,DefinedAfterMacroUsage)10424 TEST_P(GLSLTest, DefinedAfterMacroUsage)
10425 {
10426 constexpr char kVS[] = R"(precision mediump float;
10427 attribute highp vec4 position;
10428 varying vec2 out0;
10429
10430 void main()
10431 {
10432 #define AAA defined(BBB)
10433 #define BBB 1
10434
10435 #if AAA
10436 out0 = vec2(0.0, 1.0);
10437 #else
10438 out0 = vec2(1.0, 0.0);
10439 #endif
10440 gl_Position = position;
10441 })";
10442
10443 constexpr char kFS[] = R"(precision mediump float;
10444 varying vec2 out0;
10445 void main()
10446 {
10447 gl_FragColor = vec4(out0, 0, 1);
10448 })";
10449
10450 ANGLE_GL_PROGRAM(program, kVS, kFS);
10451 drawQuad(program, "position", 0.5f);
10452 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10453 }
10454
10455 // Test generating "defined" by concatenation when a macro is called. This is not allowed.
TEST_P(GLSLTest,DefinedInMacroConcatenationNotAllowed)10456 TEST_P(GLSLTest, DefinedInMacroConcatenationNotAllowed)
10457 {
10458 constexpr char kVS[] = R"(precision mediump float;
10459 attribute highp vec4 position;
10460 varying vec2 out0;
10461
10462 void main()
10463 {
10464 #define BBB 1
10465 #define AAA(defi, ned) defi ## ned(BBB)
10466
10467 #if AAA(defi, ned)
10468 out0 = vec2(0.0, 1.0);
10469 #else
10470 out0 = vec2(1.0, 0.0);
10471 #endif
10472 gl_Position = position;
10473 })";
10474
10475 constexpr char kFS[] = R"(precision mediump float;
10476 varying vec2 out0;
10477 void main()
10478 {
10479 gl_FragColor = vec4(out0, 0, 1);
10480 })";
10481
10482 GLuint program = CompileProgram(kVS, kFS);
10483 EXPECT_EQ(0u, program);
10484 glDeleteProgram(program);
10485 }
10486
10487 // Test using defined in a macro parameter name. This is not allowed.
TEST_P(GLSLTest,DefinedAsParameterNameNotAllowed)10488 TEST_P(GLSLTest, DefinedAsParameterNameNotAllowed)
10489 {
10490 constexpr char kVS[] = R"(precision mediump float;
10491 attribute highp vec4 position;
10492 varying vec2 out0;
10493
10494 void main()
10495 {
10496 #define BBB 1
10497 #define AAA(defined) defined(BBB)
10498
10499 #if AAA(defined)
10500 out0 = vec2(0.0, 1.0);
10501 #else
10502 out0 = vec2(1.0, 0.0);
10503 #endif
10504 gl_Position = position;
10505 })";
10506
10507 constexpr char kFS[] = R"(precision mediump float;
10508 varying vec2 out0;
10509 void main()
10510 {
10511 gl_FragColor = vec4(out0, 0, 1);
10512 })";
10513
10514 GLuint program = CompileProgram(kVS, kFS);
10515 EXPECT_EQ(0u, program);
10516 glDeleteProgram(program);
10517 }
10518
10519 // Ensure that defined in a macro is no accepted in WebGL.
TEST_P(WebGLGLSLTest,DefinedInMacroFails)10520 TEST_P(WebGLGLSLTest, DefinedInMacroFails)
10521 {
10522 constexpr char kVS[] = R"(precision mediump float;
10523 attribute highp vec4 position;
10524 varying float out0;
10525
10526 void main()
10527 {
10528 #define AAA defined(BBB)
10529
10530 #if !AAA
10531 out0 = 1.0;
10532 #else
10533 out0 = 0.0;
10534 #endif
10535 gl_Position = dEQP_Position;
10536 })";
10537
10538 constexpr char kFS[] = R"(precision mediump float;
10539 varying float out0;
10540 void main()
10541 {
10542 gl_FragColor = vec4(out0, 0, 0, 1);
10543 })";
10544
10545 GLuint program = CompileProgram(kVS, kFS);
10546 EXPECT_EQ(0u, program);
10547 glDeleteProgram(program);
10548 }
10549
10550 // Simple test using a define macro in WebGL.
TEST_P(WebGLGLSLTest,DefinedGLESSymbol)10551 TEST_P(WebGLGLSLTest, DefinedGLESSymbol)
10552 {
10553 constexpr char kVS[] = R"(void main()
10554 {
10555 gl_Position = vec4(1, 0, 0, 1);
10556 })";
10557
10558 constexpr char kFS[] = R"(#if defined(GL_ES)
10559 precision mediump float;
10560 void main()
10561 {
10562 gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
10563 }
10564 #else
10565 foo
10566 #endif
10567 )";
10568
10569 ANGLE_GL_PROGRAM(program, kVS, kFS);
10570 }
10571
10572 // Test that inactive output variables compile ok in combination with initOutputVariables
10573 // (which is enabled on WebGL).
TEST_P(WebGL2GLSLTest,InactiveOutput)10574 TEST_P(WebGL2GLSLTest, InactiveOutput)
10575 {
10576 constexpr char kFS[] = R"(#version 300 es
10577 precision highp float;
10578 out vec4 _cassgl_2_;
10579 void main()
10580 {
10581 })";
10582
10583 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
10584 EXPECT_NE(shader, 0u);
10585 }
10586
10587 // Test that clamp applied on non-literal indices is correct on es 100 shaders.
TEST_P(GLSLTest,ValidIndexClampES100)10588 TEST_P(GLSLTest, ValidIndexClampES100)
10589 {
10590 // http://anglebug.com/6027
10591 ANGLE_SKIP_TEST_IF(IsD3D9());
10592
10593 constexpr char kFS[] = R"(
10594 precision mediump float;
10595 uniform int u;
10596 uniform mat4 m[2];
10597 void main()
10598 {
10599 gl_FragColor = vec4(m[u][1].xyz, 1);
10600 }
10601 )";
10602
10603 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
10604 glUseProgram(program);
10605
10606 GLint uniformLocation = glGetUniformLocation(program, "u");
10607 ASSERT_NE(-1, uniformLocation);
10608
10609 GLint matrixLocation = glGetUniformLocation(program, "m");
10610 ASSERT_NE(matrixLocation, -1);
10611 const std::array<GLfloat, 32> mValue = {{0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f,
10612 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f,
10613 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
10614 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}};
10615 glUniformMatrix4fv(matrixLocation, 2, false, mValue.data());
10616
10617 glUniform1i(uniformLocation, 1);
10618 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
10619 EXPECT_GL_NO_ERROR();
10620
10621 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10622 }
10623
10624 // Test that clamp applied on non-literal indices is correct on es 300 shaders.
TEST_P(GLSLTest_ES3,ValidIndexClampES300)10625 TEST_P(GLSLTest_ES3, ValidIndexClampES300)
10626 {
10627 constexpr char kFS[] = R"(#version 300 es
10628 precision mediump float;
10629 out vec4 color;
10630 uniform int u;
10631 mat4 m[4] = mat4[4](mat4(0.25), mat4(0.5), mat4(1), mat4(0.75));
10632 void main()
10633 {
10634 color = vec4(m[u][2].xyz, 1);
10635 }
10636 )";
10637
10638 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
10639 glUseProgram(program);
10640
10641 GLint uniformLocation = glGetUniformLocation(program, "u");
10642 ASSERT_NE(-1, uniformLocation);
10643
10644 glUniform1i(uniformLocation, 2);
10645 EXPECT_GL_NO_ERROR();
10646 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
10647 EXPECT_GL_NO_ERROR();
10648
10649 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
10650 }
10651
10652 // Tests constant folding of non-square 'matrixCompMult'.
TEST_P(GLSLTest_ES3,NonSquareMatrixCompMult)10653 TEST_P(GLSLTest_ES3, NonSquareMatrixCompMult)
10654 {
10655 constexpr char kFS[] = R"(#version 300 es
10656 precision mediump float;
10657
10658 const mat4x2 matA = mat4x2(2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0);
10659 const mat4x2 matB = mat4x2(1.0/2.0, 1.0/4.0, 1.0/8.0, 1.0/16.0, 1.0/32.0, 1.0/64.0, 1.0/128.0, 1.0/256.0);
10660
10661 out vec4 color;
10662
10663 void main()
10664 {
10665 mat4x2 result = matrixCompMult(matA, matB);
10666 vec2 vresult = result * vec4(1.0, 1.0, 1.0, 1.0);
10667 if (vresult == vec2(4.0, 4.0))
10668 {
10669 color = vec4(0.0, 1.0, 0.0, 1.0);
10670 }
10671 else
10672 {
10673 color = vec4(1.0, 0.0, 0.0, 1.0);
10674 }
10675 })";
10676
10677 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
10678 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
10679 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10680 }
10681
10682 // Test initializing an array with the same name of previously declared array
TEST_P(GLSLTest_ES3,InitSameNameArray)10683 TEST_P(GLSLTest_ES3, InitSameNameArray)
10684 {
10685 constexpr char kFS[] = R"(#version 300 es
10686 precision highp float;
10687 out vec4 my_FragColor;
10688
10689 void main()
10690 {
10691 float arr[2] = float[2](1.0, 1.0);
10692 {
10693 float arr[2] = arr;
10694 my_FragColor = vec4(0.0, arr[0], 0.0, arr[1]);
10695 }
10696 })";
10697
10698 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
10699 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
10700 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10701 }
10702
10703 // Tests using gl_FragData[0] instead of gl_FragColor.
TEST_P(GLSLTest,FragData)10704 TEST_P(GLSLTest, FragData)
10705 {
10706 constexpr char kFS[] = R"(void main() { gl_FragData[0] = vec4(1, 0, 0, 1); })";
10707 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
10708 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
10709 EXPECT_GL_NO_ERROR();
10710 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
10711 }
10712
10713 // Tests using gl_FragData[0] instead of gl_FragColor with GL_SAMPLE_ALPHA_TO_COVERAGE
10714 // Regression test for https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/5520
TEST_P(GLSLTest,FragData_AlphaToCoverage)10715 TEST_P(GLSLTest, FragData_AlphaToCoverage)
10716 {
10717 constexpr char kFS[] = R"(void main() { gl_FragData[0] = vec4(1, 0, 0, 1); })";
10718 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
10719 glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
10720 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
10721 EXPECT_GL_NO_ERROR();
10722 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
10723 }
10724
10725 // Test angle can handle big initial stack size with dynamic stack allocation.
TEST_P(GLSLTest,MemoryExhaustedTest)10726 TEST_P(GLSLTest, MemoryExhaustedTest)
10727 {
10728 GLuint program =
10729 CompileProgram(essl1_shaders::vs::Simple(), BuildBigInitialStackShader(36).c_str());
10730 EXPECT_NE(0u, program);
10731 }
10732
10733 // Test that inactive samplers in structs don't cause any errors.
TEST_P(GLSLTest,InactiveSamplersInStruct)10734 TEST_P(GLSLTest, InactiveSamplersInStruct)
10735 {
10736 constexpr char kVS[] = R"(attribute vec4 a_position;
10737 void main() {
10738 gl_Position = a_position;
10739 })";
10740
10741 constexpr char kFS[] = R"(precision highp float;
10742 struct S
10743 {
10744 vec4 v;
10745 sampler2D t[10];
10746 };
10747 uniform S s;
10748 void main() {
10749 gl_FragColor = s.v;
10750 })";
10751
10752 ANGLE_GL_PROGRAM(program, kVS, kFS);
10753
10754 drawQuad(program, "a_position", 0.5f);
10755 }
10756
10757 // Helper functions for MixedRowAndColumnMajorMatrices* tests
10758
10759 // Round up to alignment, assuming it's a power of 2
RoundUpPow2(uint32_t value,uint32_t alignment)10760 uint32_t RoundUpPow2(uint32_t value, uint32_t alignment)
10761 {
10762 return (value + alignment - 1) & ~(alignment - 1);
10763 }
10764
CreateOutputBuffer(GLBuffer * buffer,uint32_t binding)10765 void CreateOutputBuffer(GLBuffer *buffer, uint32_t binding)
10766 {
10767 unsigned int outputInitData = 0;
10768 glBindBuffer(GL_SHADER_STORAGE_BUFFER, *buffer);
10769 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
10770 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, binding, *buffer);
10771 EXPECT_GL_NO_ERROR();
10772 }
10773
10774 // Fill provided buffer with matrices based on the given dimensions. The buffer should be large
10775 // enough to accomodate the data.
FillBuffer(const std::pair<uint32_t,uint32_t> matrixDims[],const bool matrixIsColMajor[],size_t matrixCount,float data[],bool isStd430,bool isTransposed)10776 uint32_t FillBuffer(const std::pair<uint32_t, uint32_t> matrixDims[],
10777 const bool matrixIsColMajor[],
10778 size_t matrixCount,
10779 float data[],
10780 bool isStd430,
10781 bool isTransposed)
10782 {
10783 size_t offset = 0;
10784 for (size_t m = 0; m < matrixCount; ++m)
10785 {
10786 uint32_t cols = matrixDims[m].first;
10787 uint32_t rows = matrixDims[m].second;
10788 bool isColMajor = matrixIsColMajor[m] != isTransposed;
10789
10790 uint32_t arraySize = isColMajor ? cols : rows;
10791 uint32_t arrayElementComponents = isColMajor ? rows : cols;
10792 // Note: stride is generally 4 with std140, except for scalar and gvec2 types (which
10793 // MixedRowAndColumnMajorMatrices* tests don't use). With std430, small matrices can have
10794 // a stride of 2 between rows/columns.
10795 uint32_t stride = isStd430 ? RoundUpPow2(arrayElementComponents, 2) : 4;
10796
10797 offset = RoundUpPow2(offset, stride);
10798
10799 for (uint32_t i = 0; i < arraySize; ++i)
10800 {
10801 for (uint32_t c = 0; c < arrayElementComponents; ++c)
10802 {
10803 uint32_t row = isColMajor ? c : i;
10804 uint32_t col = isColMajor ? i : c;
10805
10806 data[offset + i * stride + c] = col * 4 + row;
10807 }
10808 }
10809
10810 offset += arraySize * stride;
10811 }
10812 return offset;
10813 }
10814
10815 // Initialize and bind the buffer.
10816 template <typename T>
InitBuffer(GLuint program,const char * name,GLuint buffer,uint32_t bindingIndex,const T data[],uint32_t dataSize,bool isUniform)10817 void InitBuffer(GLuint program,
10818 const char *name,
10819 GLuint buffer,
10820 uint32_t bindingIndex,
10821 const T data[],
10822 uint32_t dataSize,
10823 bool isUniform)
10824 {
10825 GLenum bindPoint = isUniform ? GL_UNIFORM_BUFFER : GL_SHADER_STORAGE_BUFFER;
10826
10827 glBindBufferBase(bindPoint, bindingIndex, buffer);
10828 glBufferData(bindPoint, dataSize * sizeof(*data), data, GL_STATIC_DRAW);
10829
10830 if (isUniform)
10831 {
10832 GLint blockIndex = glGetUniformBlockIndex(program, name);
10833 glUniformBlockBinding(program, blockIndex, bindingIndex);
10834 }
10835 }
10836
10837 // Verify that buffer data is written by the shader as expected.
10838 template <typename T>
VerifyBuffer(GLuint buffer,const T data[],uint32_t dataSize)10839 bool VerifyBuffer(GLuint buffer, const T data[], uint32_t dataSize)
10840 {
10841 uint32_t sizeInBytes = dataSize * sizeof(*data);
10842
10843 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
10844
10845 glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
10846
10847 const T *ptr = reinterpret_cast<const T *>(
10848 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeInBytes, GL_MAP_READ_BIT));
10849
10850 bool isCorrect = memcmp(ptr, data, sizeInBytes) == 0;
10851 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
10852
10853 return isCorrect;
10854 }
10855
10856 // Verify that the success output of the shader is as expected.
VerifySuccess(GLuint buffer)10857 bool VerifySuccess(GLuint buffer)
10858 {
10859 uint32_t success = 1;
10860 return VerifyBuffer(buffer, reinterpret_cast<const float *>(&success), 1);
10861 }
10862
10863 // Test reading from UBOs and SSBOs and writing to SSBOs with mixed row- and colum-major layouts in
10864 // both std140 and std430 layouts. Tests many combinations of std140 vs std430, struct being used
10865 // as row- or column-major in different UBOs, reading from UBOs and SSBOs and writing to SSBOs,
10866 // nested structs, matrix arrays, inout parameters etc.
10867 //
10868 // Some very specific corner cases that are not covered here are tested in the subsequent tests.
TEST_P(GLSLTest_ES31,MixedRowAndColumnMajorMatrices)10869 TEST_P(GLSLTest_ES31, MixedRowAndColumnMajorMatrices)
10870 {
10871 GLint maxComputeShaderStorageBlocks;
10872 glGetIntegerv(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, &maxComputeShaderStorageBlocks);
10873
10874 // The test uses 9 SSBOs. Skip if not that many are supported.
10875 ANGLE_SKIP_TEST_IF(maxComputeShaderStorageBlocks < 9);
10876
10877 // Fails on Nvidia because having |Matrices| qualified as row-major in one UBO makes the other
10878 // UBO also see it as row-major despite explicit column-major qualifier.
10879 // http://anglebug.com/3830
10880 ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGL());
10881
10882 // Fails on mesa because in the first UBO which is qualified as column-major, |Matrices| is
10883 // read column-major despite explicit row-major qualifier. http://anglebug.com/3837
10884 ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsOpenGL());
10885
10886 // Fails on windows AMD on GL: http://anglebug.com/3838
10887 ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL() && IsAMD());
10888
10889 // Fails to compile the shader on Android. http://anglebug.com/3839
10890 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
10891
10892 // Fails on assertion in translation to D3D. http://anglebug.com/3841
10893 ANGLE_SKIP_TEST_IF(IsD3D11());
10894
10895 // Fails on SSBO validation on Android/Vulkan. http://anglebug.com/3840
10896 ANGLE_SKIP_TEST_IF(IsAndroid() && IsVulkan());
10897
10898 // Fails input verification as well as std140 SSBO validation. http://anglebug.com/3844
10899 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());
10900
10901 // Fails on ARM on Vulkan. http://anglebug.com/4492
10902 ANGLE_SKIP_TEST_IF(IsARM() && IsVulkan());
10903
10904 constexpr char kCS[] = R"(#version 310 es
10905 precision highp float;
10906 layout(local_size_x=1) in;
10907
10908 struct Inner
10909 {
10910 mat3x4 m3c4r;
10911 mat4x3 m4c3r;
10912 };
10913
10914 struct Matrices
10915 {
10916 mat2 m2c2r;
10917 mat2x3 m2c3r[2];
10918 mat3x2 m3c2r;
10919 Inner inner;
10920 };
10921
10922 // For simplicity, the layouts are either of:
10923 // - col-major mat4, row-major rest
10924 // - row-major mat4, col-major rest
10925 //
10926 // The former is tagged with c, the latter with r.
10927 layout(std140, column_major) uniform Ubo140c
10928 {
10929 mat4 m4c4r;
10930 layout(row_major) Matrices m;
10931 } ubo140cIn;
10932
10933 layout(std140, row_major) uniform Ubo140r
10934 {
10935 mat4 m4c4r;
10936 layout(column_major) Matrices m;
10937 } ubo140rIn;
10938
10939 layout(std140, row_major, binding = 0) buffer Ssbo140c
10940 {
10941 layout(column_major) mat4 m4c4r;
10942 Matrices m;
10943 } ssbo140cIn;
10944
10945 layout(std140, column_major, binding = 1) buffer Ssbo140r
10946 {
10947 layout(row_major) mat4 m4c4r;
10948 Matrices m;
10949 } ssbo140rIn;
10950
10951 layout(std430, column_major, binding = 2) buffer Ssbo430c
10952 {
10953 mat4 m4c4r;
10954 layout(row_major) Matrices m;
10955 } ssbo430cIn;
10956
10957 layout(std430, row_major, binding = 3) buffer Ssbo430r
10958 {
10959 mat4 m4c4r;
10960 layout(column_major) Matrices m;
10961 } ssbo430rIn;
10962
10963 layout(std140, row_major, binding = 4) buffer Ssbo140cOut
10964 {
10965 layout(column_major) mat4 m4c4r;
10966 Matrices m;
10967 } ssbo140cOut;
10968
10969 layout(std140, column_major, binding = 5) buffer Ssbo140rOut
10970 {
10971 layout(row_major) mat4 m4c4r;
10972 Matrices m;
10973 } ssbo140rOut;
10974
10975 layout(std430, column_major, binding = 6) buffer Ssbo430cOut
10976 {
10977 mat4 m4c4r;
10978 layout(row_major) Matrices m;
10979 } ssbo430cOut;
10980
10981 layout(std430, row_major, binding = 7) buffer Ssbo430rOut
10982 {
10983 mat4 m4c4r;
10984 layout(column_major) Matrices m;
10985 } ssbo430rOut;
10986
10987 layout(std140, binding = 8) buffer Result
10988 {
10989 uint success;
10990 } resultOut;
10991
10992 #define EXPECT(result, expression, value) if ((expression) != value) { result = false; }
10993 #define EXPECTV(result, expression, value) if (any(notEqual(expression, value))) { result = false; }
10994
10995 #define VERIFY_IN(result, mat, cols, rows) \
10996 EXPECT(result, mat[0].x, 0.0); \
10997 EXPECT(result, mat[0][1], 1.0); \
10998 EXPECTV(result, mat[0].xy, vec2(0, 1)); \
10999 EXPECTV(result, mat[1].xy, vec2(4, 5)); \
11000 for (int c = 0; c < cols; ++c) \
11001 { \
11002 for (int r = 0; r < rows; ++r) \
11003 { \
11004 EXPECT(result, mat[c][r], float(c * 4 + r)); \
11005 } \
11006 }
11007
11008 #define COPY(matIn, matOut, cols, rows) \
11009 matOut = matOut + matIn; \
11010 /* random operations for testing */ \
11011 matOut[0].x += matIn[0].x + matIn[1].x; \
11012 matOut[0].x -= matIn[1].x; \
11013 matOut[0][1] += matIn[0][1]; \
11014 matOut[1] += matIn[1]; \
11015 matOut[1].xy -= matIn[1].xy; \
11016 /* undo the above to get back matIn */ \
11017 matOut[0].x -= matIn[0].x; \
11018 matOut[0][1] -= matIn[0][1]; \
11019 matOut[1] -= matIn[1]; \
11020 matOut[1].xy += matIn[1].xy;
11021
11022 bool verifyMatrices(in Matrices m)
11023 {
11024 bool result = true;
11025 VERIFY_IN(result, m.m2c2r, 2, 2);
11026 VERIFY_IN(result, m.m2c3r[0], 2, 3);
11027 VERIFY_IN(result, m.m2c3r[1], 2, 3);
11028 VERIFY_IN(result, m.m3c2r, 3, 2);
11029 VERIFY_IN(result, m.inner.m3c4r, 3, 4);
11030 VERIFY_IN(result, m.inner.m4c3r, 4, 3);
11031 return result;
11032 }
11033
11034 mat4 copyMat4(in mat4 m)
11035 {
11036 return m;
11037 }
11038
11039 void copyMatrices(in Matrices mIn, inout Matrices mOut)
11040 {
11041 COPY(mIn.m2c2r, mOut.m2c2r, 2, 2);
11042 COPY(mIn.m2c3r[0], mOut.m2c3r[0], 2, 3);
11043 COPY(mIn.m2c3r[1], mOut.m2c3r[1], 2, 3);
11044 COPY(mIn.m3c2r, mOut.m3c2r, 3, 2);
11045 COPY(mIn.inner.m3c4r, mOut.inner.m3c4r, 3, 4);
11046 COPY(mIn.inner.m4c3r, mOut.inner.m4c3r, 4, 3);
11047 }
11048
11049 void main()
11050 {
11051 bool result = true;
11052
11053 VERIFY_IN(result, ubo140cIn.m4c4r, 4, 4);
11054 VERIFY_IN(result, ubo140cIn.m.m2c3r[0], 2, 3);
11055 EXPECT(result, verifyMatrices(ubo140cIn.m), true);
11056
11057 VERIFY_IN(result, ubo140rIn.m4c4r, 4, 4);
11058 VERIFY_IN(result, ubo140rIn.m.m2c2r, 2, 2);
11059 EXPECT(result, verifyMatrices(ubo140rIn.m), true);
11060
11061 VERIFY_IN(result, ssbo140cIn.m4c4r, 4, 4);
11062 VERIFY_IN(result, ssbo140cIn.m.m3c2r, 3, 2);
11063 EXPECT(result, verifyMatrices(ssbo140cIn.m), true);
11064
11065 VERIFY_IN(result, ssbo140rIn.m4c4r, 4, 4);
11066 VERIFY_IN(result, ssbo140rIn.m.inner.m4c3r, 4, 3);
11067 EXPECT(result, verifyMatrices(ssbo140rIn.m), true);
11068
11069 VERIFY_IN(result, ssbo430cIn.m4c4r, 4, 4);
11070 VERIFY_IN(result, ssbo430cIn.m.m2c3r[1], 2, 3);
11071 EXPECT(result, verifyMatrices(ssbo430cIn.m), true);
11072
11073 VERIFY_IN(result, ssbo430rIn.m4c4r, 4, 4);
11074 VERIFY_IN(result, ssbo430rIn.m.inner.m3c4r, 3, 4);
11075 EXPECT(result, verifyMatrices(ssbo430rIn.m), true);
11076
11077 // Only assign to SSBO from a single invocation.
11078 if (gl_GlobalInvocationID.x == 0u)
11079 {
11080 ssbo140cOut.m4c4r = copyMat4(ssbo140cIn.m4c4r);
11081 copyMatrices(ssbo430cIn.m, ssbo140cOut.m);
11082 ssbo140cOut.m.m2c3r[1] = mat2x3(0);
11083 COPY(ssbo430cIn.m.m2c3r[1], ssbo140cOut.m.m2c3r[1], 2, 3);
11084
11085 ssbo140rOut.m4c4r = copyMat4(ssbo140rIn.m4c4r);
11086 copyMatrices(ssbo430rIn.m, ssbo140rOut.m);
11087 ssbo140rOut.m.inner.m3c4r = mat3x4(0);
11088 COPY(ssbo430rIn.m.inner.m3c4r, ssbo140rOut.m.inner.m3c4r, 3, 4);
11089
11090 ssbo430cOut.m4c4r = copyMat4(ssbo430cIn.m4c4r);
11091 copyMatrices(ssbo140cIn.m, ssbo430cOut.m);
11092 ssbo430cOut.m.m3c2r = mat3x2(0);
11093 COPY(ssbo430cIn.m.m3c2r, ssbo430cOut.m.m3c2r, 3, 2);
11094
11095 ssbo430rOut.m4c4r = copyMat4(ssbo430rIn.m4c4r);
11096 copyMatrices(ssbo140rIn.m, ssbo430rOut.m);
11097 ssbo430rOut.m.inner.m4c3r = mat4x3(0);
11098 COPY(ssbo430rIn.m.inner.m4c3r, ssbo430rOut.m.inner.m4c3r, 4, 3);
11099
11100 resultOut.success = uint(result);
11101 }
11102 })";
11103
11104 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
11105 EXPECT_GL_NO_ERROR();
11106
11107 constexpr size_t kMatrixCount = 7;
11108 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
11109 {4, 4}, {2, 2}, {2, 3}, {2, 3}, {3, 2}, {3, 4}, {4, 3},
11110 };
11111 constexpr bool kMatrixIsColMajor[kMatrixCount] = {
11112 true, false, false, false, false, false, false,
11113 };
11114
11115 float dataStd140ColMajor[kMatrixCount * 4 * 4] = {};
11116 float dataStd140RowMajor[kMatrixCount * 4 * 4] = {};
11117 float dataStd430ColMajor[kMatrixCount * 4 * 4] = {};
11118 float dataStd430RowMajor[kMatrixCount * 4 * 4] = {};
11119 float dataZeros[kMatrixCount * 4 * 4] = {};
11120
11121 const uint32_t sizeStd140ColMajor =
11122 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, dataStd140ColMajor, false, false);
11123 const uint32_t sizeStd140RowMajor =
11124 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, dataStd140RowMajor, false, true);
11125 const uint32_t sizeStd430ColMajor =
11126 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, dataStd430ColMajor, true, false);
11127 const uint32_t sizeStd430RowMajor =
11128 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, dataStd430RowMajor, true, true);
11129
11130 GLBuffer uboStd140ColMajor, uboStd140RowMajor;
11131 GLBuffer ssboStd140ColMajor, ssboStd140RowMajor;
11132 GLBuffer ssboStd430ColMajor, ssboStd430RowMajor;
11133 GLBuffer ssboStd140ColMajorOut, ssboStd140RowMajorOut;
11134 GLBuffer ssboStd430ColMajorOut, ssboStd430RowMajorOut;
11135
11136 InitBuffer(program, "Ubo140c", uboStd140ColMajor, 0, dataStd140ColMajor, sizeStd140ColMajor,
11137 true);
11138 InitBuffer(program, "Ubo140r", uboStd140RowMajor, 1, dataStd140RowMajor, sizeStd140RowMajor,
11139 true);
11140 InitBuffer(program, "Ssbo140c", ssboStd140ColMajor, 0, dataStd140ColMajor, sizeStd140ColMajor,
11141 false);
11142 InitBuffer(program, "Ssbo140r", ssboStd140RowMajor, 1, dataStd140RowMajor, sizeStd140RowMajor,
11143 false);
11144 InitBuffer(program, "Ssbo430c", ssboStd430ColMajor, 2, dataStd430ColMajor, sizeStd430ColMajor,
11145 false);
11146 InitBuffer(program, "Ssbo430r", ssboStd430RowMajor, 3, dataStd430RowMajor, sizeStd430RowMajor,
11147 false);
11148 InitBuffer(program, "Ssbo140cOut", ssboStd140ColMajorOut, 4, dataZeros, sizeStd140ColMajor,
11149 false);
11150 InitBuffer(program, "Ssbo140rOut", ssboStd140RowMajorOut, 5, dataZeros, sizeStd140RowMajor,
11151 false);
11152 InitBuffer(program, "Ssbo430cOut", ssboStd430ColMajorOut, 6, dataZeros, sizeStd430ColMajor,
11153 false);
11154 InitBuffer(program, "Ssbo430rOut", ssboStd430RowMajorOut, 7, dataZeros, sizeStd430RowMajor,
11155 false);
11156 EXPECT_GL_NO_ERROR();
11157
11158 GLBuffer outputBuffer;
11159 CreateOutputBuffer(&outputBuffer, 8);
11160
11161 glUseProgram(program);
11162 glDispatchCompute(1, 1, 1);
11163 EXPECT_GL_NO_ERROR();
11164 EXPECT_TRUE(VerifySuccess(outputBuffer));
11165
11166 EXPECT_TRUE(VerifyBuffer(ssboStd140ColMajorOut, dataStd140ColMajor, sizeStd140ColMajor));
11167 EXPECT_TRUE(VerifyBuffer(ssboStd140RowMajorOut, dataStd140RowMajor, sizeStd140RowMajor));
11168 EXPECT_TRUE(VerifyBuffer(ssboStd430ColMajorOut, dataStd430ColMajor, sizeStd430ColMajor));
11169 EXPECT_TRUE(VerifyBuffer(ssboStd430RowMajorOut, dataStd430RowMajor, sizeStd430RowMajor));
11170 }
11171
11172 // Test that array UBOs are transformed correctly.
TEST_P(GLSLTest_ES3,RowMajorMatrix_ReadMat4Test)11173 TEST_P(GLSLTest_ES3, RowMajorMatrix_ReadMat4Test)
11174 {
11175 constexpr char kFS[] = R"(#version 300 es
11176 precision highp float;
11177 out vec4 outColor;
11178
11179 layout(std140, row_major) uniform Ubo
11180 {
11181 mat4 m1;
11182 };
11183
11184 void main()
11185 {
11186 outColor = m1[3] / 255.0;
11187 })";
11188
11189 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11190 EXPECT_GL_NO_ERROR();
11191
11192 constexpr size_t kMatrixCount = 1;
11193 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
11194 {4, 4},
11195 };
11196 constexpr bool kMatrixIsColMajor[kMatrixCount] = {
11197 false,
11198 };
11199
11200 float data[kMatrixCount * 4 * 4] = {};
11201
11202 const uint32_t size =
11203 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
11204
11205 GLBuffer ubos;
11206
11207 InitBuffer(program, "Ubo", ubos, 0, data, size, true);
11208
11209 EXPECT_GL_NO_ERROR();
11210
11211 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
11212 EXPECT_PIXEL_NEAR(0, 0, 12, 13, 14, 15, 0);
11213 }
11214
11215 // Test that array UBOs are transformed correctly.
TEST_P(GLSLTest_ES3,RowMajorMatrix_ReadMat2x3Test)11216 TEST_P(GLSLTest_ES3, RowMajorMatrix_ReadMat2x3Test)
11217 {
11218 constexpr char kFS[] = R"(#version 300 es
11219 precision highp float;
11220 out vec4 outColor;
11221
11222 layout(std140, row_major) uniform Ubo
11223 {
11224 mat2x3 m1;
11225 };
11226
11227 void main()
11228 {
11229 outColor = vec4(m1[1], 0) / 255.0;
11230 })";
11231
11232 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11233 EXPECT_GL_NO_ERROR();
11234
11235 constexpr size_t kMatrixCount = 1;
11236 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
11237 {2, 3},
11238 };
11239 constexpr bool kMatrixIsColMajor[kMatrixCount] = {
11240 false,
11241 };
11242
11243 float data[kMatrixCount * 3 * 4] = {};
11244
11245 const uint32_t size =
11246 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
11247
11248 GLBuffer ubos;
11249
11250 InitBuffer(program, "Ubo", ubos, 0, data, size, true);
11251
11252 EXPECT_GL_NO_ERROR();
11253
11254 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
11255 EXPECT_PIXEL_NEAR(0, 0, 4, 5, 6, 0, 0);
11256 }
11257
TEST_P(GLSLTest_ES3,RowMajorMatrix_ReadMat3x2Test)11258 TEST_P(GLSLTest_ES3, RowMajorMatrix_ReadMat3x2Test)
11259 {
11260 constexpr char kFS[] = R"(#version 300 es
11261 precision highp float;
11262 out vec4 outColor;
11263
11264 layout(std140, row_major) uniform Ubo
11265 {
11266 mat3x2 m1;
11267 };
11268
11269 void main()
11270 {
11271 outColor = vec4(m1[2], 0, 0) / 255.0;
11272 })";
11273
11274 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11275 EXPECT_GL_NO_ERROR();
11276
11277 constexpr size_t kMatrixCount = 1;
11278 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
11279 {3, 2},
11280 };
11281 constexpr bool kMatrixIsColMajor[kMatrixCount] = {
11282 false,
11283 };
11284
11285 float data[kMatrixCount * 2 * 4] = {};
11286
11287 const uint32_t size =
11288 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
11289
11290 GLBuffer ubos;
11291
11292 InitBuffer(program, "Ubo", ubos, 0, data, size, true);
11293
11294 EXPECT_GL_NO_ERROR();
11295
11296 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
11297 EXPECT_PIXEL_NEAR(0, 0, 8, 9, 0, 0, 0);
11298 }
11299
TEST_P(GLSLTest_ES3,RowMajorMatrix_NestedExpression)11300 TEST_P(GLSLTest_ES3, RowMajorMatrix_NestedExpression)
11301 {
11302 // Many OpenGL drivers seem to fail this
11303 ANGLE_SKIP_TEST_IF((IsLinux() || IsMac()) && IsOpenGL());
11304
11305 constexpr char kFS[] = R"(#version 300 es
11306 precision mediump float;
11307
11308 uniform Ubo {
11309 layout(row_major) mat4 u_mat[3];
11310 layout(row_major) mat4 u_ndx[3];
11311 } stuff;
11312
11313 precision highp float;
11314 out vec4 outColor;
11315
11316 void main() {
11317 outColor = stuff.u_mat[int(stuff.u_ndx[1][1][3])][2] / 255.0;
11318 }
11319 )";
11320
11321 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11322 EXPECT_GL_NO_ERROR();
11323
11324 typedef float vec4[4];
11325 typedef vec4 mat4[4];
11326
11327 constexpr size_t kMatrixCount = 6;
11328 mat4 data[] = {
11329 {
11330 {0, 1, 2, 3}, //
11331 {4, 5, 6, 7}, //
11332 {8, 9, 10, 11}, //
11333 {12, 13, 14, 15}, //
11334 },
11335 {
11336 // +-- we should be looking up this column
11337 // V
11338 {0, 4, 8, 12}, //
11339 {1, 5, 9, 13}, //
11340 {2, 6, 10, 14}, //
11341 {3, 7, 11, 15}, //
11342 },
11343 {
11344 {0, 2, 4, 6}, //
11345 {8, 10, 12, 14}, //
11346 {16, 18, 20, 22}, //
11347 {24, 26, 28, 30}, //
11348 },
11349 {
11350 {0, 0, 0, 0}, //
11351 {0, 0, 0, 0}, //
11352 {0, 0, 0, 0}, //
11353 {0, 0, 0, 0}, //
11354 },
11355 {
11356 {0, 0, 0, 0}, //
11357 {0, 0, 0, 2}, //
11358 {0, 0, 0, 0}, //
11359 {0, 1, 0, 0},
11360 // ^
11361 // +-- we should be using this element
11362 },
11363 {
11364 {0, 0, 0, 0}, //
11365 {0, 0, 0, 0}, //
11366 {0, 0, 0, 0}, //
11367 {0, 0, 0, 0}, //
11368 },
11369 };
11370
11371 GLBuffer ubos;
11372 InitBuffer(program, "Ubo", ubos, 0, data, kMatrixCount, true);
11373 EXPECT_GL_NO_ERROR();
11374
11375 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
11376 EXPECT_PIXEL_NEAR(0, 0, 8, 9, 10, 11, 0);
11377 }
11378
11379 // Test that array UBOs are transformed correctly.
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ArrayBufferDeclaration)11380 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ArrayBufferDeclaration)
11381 {
11382 // Fails to compile the shader on Android: http://anglebug.com/3839
11383 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
11384
11385 // http://anglebug.com/3837
11386 ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsOpenGL());
11387
11388 // Fails on Mac on Intel and AMD: http://anglebug.com/3842
11389 ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL() && (IsIntel() || IsAMD()));
11390
11391 // Fails on windows AMD on GL: http://anglebug.com/3838
11392 ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL() && IsAMD());
11393
11394 // Fails on D3D due to mistranslation: http://anglebug.com/3841
11395 ANGLE_SKIP_TEST_IF(IsD3D11());
11396
11397 constexpr char kFS[] = R"(#version 300 es
11398 precision highp float;
11399 out vec4 outColor;
11400
11401 layout(std140, column_major) uniform Ubo
11402 {
11403 mat4 m1;
11404 layout(row_major) mat4 m2;
11405 } ubo[3];
11406
11407 #define EXPECT(result, expression, value) if ((expression) != value) { result = false; }
11408
11409 #define VERIFY_IN(result, mat, cols, rows) \
11410 for (int c = 0; c < cols; ++c) \
11411 { \
11412 for (int r = 0; r < rows; ++r) \
11413 { \
11414 EXPECT(result, mat[c][r], float(c * 4 + r)); \
11415 } \
11416 }
11417
11418 void main()
11419 {
11420 bool result = true;
11421
11422 VERIFY_IN(result, ubo[0].m1, 4, 4);
11423 VERIFY_IN(result, ubo[0].m2, 4, 4);
11424
11425 VERIFY_IN(result, ubo[1].m1, 4, 4);
11426 VERIFY_IN(result, ubo[1].m2, 4, 4);
11427
11428 VERIFY_IN(result, ubo[2].m1, 4, 4);
11429 VERIFY_IN(result, ubo[2].m2, 4, 4);
11430
11431 outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
11432 })";
11433
11434 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11435 EXPECT_GL_NO_ERROR();
11436
11437 constexpr size_t kMatrixCount = 2;
11438 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
11439 {4, 4},
11440 {4, 4},
11441 };
11442 constexpr bool kMatrixIsColMajor[kMatrixCount] = {
11443 true,
11444 false,
11445 };
11446
11447 float data[kMatrixCount * 4 * 4] = {};
11448
11449 const uint32_t size =
11450 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
11451
11452 GLBuffer ubos[3];
11453
11454 InitBuffer(program, "Ubo[0]", ubos[0], 0, data, size, true);
11455 InitBuffer(program, "Ubo[1]", ubos[1], 0, data, size, true);
11456 InitBuffer(program, "Ubo[2]", ubos[2], 0, data, size, true);
11457
11458 EXPECT_GL_NO_ERROR();
11459
11460 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
11461 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
11462 }
11463
11464 // Test that side effects when transforming read operations are preserved.
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ReadSideEffect)11465 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ReadSideEffect)
11466 {
11467 // Fails on Mac on Intel and AMD: http://anglebug.com/3842
11468 ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL() && (IsIntel() || IsAMD()));
11469
11470 // Fails on D3D due to mistranslation: http://anglebug.com/3841
11471 ANGLE_SKIP_TEST_IF(IsD3D11());
11472
11473 constexpr char kFS[] = R"(#version 300 es
11474 precision highp float;
11475 out vec4 outColor;
11476
11477 struct S
11478 {
11479 mat2x3 m2[3];
11480 };
11481
11482 layout(std140, column_major) uniform Ubo
11483 {
11484 mat4 m1;
11485 layout(row_major) S s[2];
11486 } ubo;
11487
11488 #define EXPECT(result, expression, value) if ((expression) != value) { result = false; }
11489
11490 #define VERIFY_IN(result, mat, cols, rows) \
11491 for (int c = 0; c < cols; ++c) \
11492 { \
11493 for (int r = 0; r < rows; ++r) \
11494 { \
11495 EXPECT(result, mat[c][r], float(c * 4 + r)); \
11496 } \
11497 }
11498
11499 bool verify2x3(mat2x3 mat)
11500 {
11501 bool result = true;
11502
11503 for (int c = 0; c < 2; ++c)
11504 {
11505 for (int r = 0; r < 3; ++r)
11506 {
11507 EXPECT(result, mat[c][r], float(c * 4 + r));
11508 }
11509 }
11510
11511 return result;
11512 }
11513
11514 void main()
11515 {
11516 bool result = true;
11517
11518 int sideEffect = 0;
11519 VERIFY_IN(result, ubo.m1, 4, 4);
11520 EXPECT(result, verify2x3(ubo.s[0].m2[0]), true);
11521 EXPECT(result, verify2x3(ubo.s[0].m2[sideEffect += 1]), true);
11522 EXPECT(result, verify2x3(ubo.s[0].m2[sideEffect += 1]), true);
11523
11524 EXPECT(result, sideEffect, 2);
11525
11526 EXPECT(result, verify2x3(ubo.s[sideEffect = 1].m2[0]), true);
11527 EXPECT(result, verify2x3(ubo.s[1].m2[(sideEffect = 4) - 3]), true);
11528 EXPECT(result, verify2x3(ubo.s[1].m2[sideEffect - 2]), true);
11529
11530 EXPECT(result, sideEffect, 4);
11531
11532 outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
11533 })";
11534
11535 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11536 EXPECT_GL_NO_ERROR();
11537
11538 constexpr size_t kMatrixCount = 7;
11539 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
11540 {4, 4}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3},
11541 };
11542 constexpr bool kMatrixIsColMajor[kMatrixCount] = {
11543 true, false, false, false, false, false, false,
11544 };
11545
11546 float data[kMatrixCount * 4 * 4] = {};
11547
11548 const uint32_t size =
11549 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
11550
11551 GLBuffer ubo;
11552 InitBuffer(program, "Ubo", ubo, 0, data, size, true);
11553
11554 EXPECT_GL_NO_ERROR();
11555
11556 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
11557 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
11558 }
11559
11560 // Test that side effects respect the order of logical expression operands.
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ReadSideEffectOrder)11561 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ReadSideEffectOrder)
11562 {
11563 // http://anglebug.com/3837
11564 ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsOpenGL());
11565
11566 // IntermTraverser::insertStatementsInParentBlock that's used to move side effects does not
11567 // respect the order of evaluation of logical expressions. http://anglebug.com/3829.
11568 ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
11569
11570 constexpr char kFS[] = R"(#version 300 es
11571 precision highp float;
11572 out vec4 outColor;
11573
11574 layout(std140, column_major) uniform Ubo
11575 {
11576 mat4 m1;
11577 layout(row_major) mat4 m2[2];
11578 } ubo;
11579
11580 void main()
11581 {
11582 bool result = true;
11583
11584 int x = 0;
11585 if (x == 0 && ubo.m2[x = 1][1][1] == 5.0)
11586 {
11587 result = true;
11588 }
11589 else
11590 {
11591 result = false;
11592 }
11593
11594 outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
11595 })";
11596
11597 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11598 EXPECT_GL_NO_ERROR();
11599
11600 constexpr size_t kMatrixCount = 3;
11601 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
11602 {4, 4},
11603 {4, 4},
11604 {4, 4},
11605 };
11606 constexpr bool kMatrixIsColMajor[kMatrixCount] = {true, false, false};
11607
11608 float data[kMatrixCount * 4 * 4] = {};
11609
11610 const uint32_t size =
11611 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
11612
11613 GLBuffer ubo;
11614 InitBuffer(program, "Ubo", ubo, 0, data, size, true);
11615
11616 EXPECT_GL_NO_ERROR();
11617
11618 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
11619 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
11620 }
11621
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ReadSideEffectOrderSurroundedByLoop)11622 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ReadSideEffectOrderSurroundedByLoop)
11623 {
11624 // http://anglebug.com/3837
11625 ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsOpenGL());
11626
11627 // IntermTraverser::insertStatementsInParentBlock that's used to move side effects does not
11628 // respect the order of evaluation of logical expressions. http://anglebug.com/3829.
11629 ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
11630
11631 constexpr char kFS[] = R"(#version 300 es
11632 precision highp float;
11633 out vec4 outColor;
11634
11635 layout(std140, column_major) uniform Ubo
11636 {
11637 mat4 m1;
11638 layout(row_major) mat4 m2[2];
11639 } ubo;
11640
11641 void main()
11642 {
11643 bool result = false;
11644
11645 for(int x = 0; x < 1; ++x)
11646 {
11647 if (x == 0 && ubo.m2[x = 1][1][1] == 5.0) {
11648 result = true;
11649 }
11650 }
11651 outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
11652 })";
11653
11654 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11655 EXPECT_GL_NO_ERROR();
11656
11657 constexpr size_t kMatrixCount = 3;
11658 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
11659 {4, 4},
11660 {4, 4},
11661 {4, 4},
11662 };
11663 constexpr bool kMatrixIsColMajor[kMatrixCount] = {true, false, false};
11664
11665 float data[kMatrixCount * 4 * 4] = {};
11666
11667 const uint32_t size =
11668 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
11669
11670 GLBuffer ubo;
11671 InitBuffer(program, "Ubo", ubo, 0, data, size, true);
11672
11673 EXPECT_GL_NO_ERROR();
11674
11675 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
11676 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
11677 }
11678
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ReadSideEffectOrderInALoop)11679 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ReadSideEffectOrderInALoop)
11680 {
11681 // http://anglebug.com/3837
11682 ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsOpenGL());
11683
11684 // IntermTraverser::insertStatementsInParentBlock that's used to move side effects does not
11685 // respect the order of evaluation of logical expressions. http://anglebug.com/3829.
11686 ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
11687
11688 constexpr char kFS[] = R"(#version 300 es
11689 precision highp float;
11690 out vec4 outColor;
11691
11692 layout(std140, column_major) uniform Ubo
11693 {
11694 mat4 m1;
11695 layout(row_major) mat4 m2[2];
11696 } ubo;
11697
11698 void main()
11699 {
11700 bool result = false;
11701
11702 for(int x = 0; x == 0 && ubo.m2[x = 1][1][1] == 5.0;)
11703 {
11704 result = true;
11705 }
11706 outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
11707 })";
11708
11709 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11710 EXPECT_GL_NO_ERROR();
11711
11712 constexpr size_t kMatrixCount = 3;
11713 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
11714 {4, 4},
11715 {4, 4},
11716 {4, 4},
11717 };
11718 constexpr bool kMatrixIsColMajor[kMatrixCount] = {true, false, false};
11719
11720 float data[kMatrixCount * 4 * 4] = {};
11721
11722 const uint32_t size =
11723 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
11724
11725 GLBuffer ubo;
11726 InitBuffer(program, "Ubo", ubo, 0, data, size, true);
11727
11728 EXPECT_GL_NO_ERROR();
11729
11730 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
11731 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
11732 }
11733
11734 // Test that side effects respect short-circuit.
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ReadSideEffectShortCircuit)11735 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ReadSideEffectShortCircuit)
11736 {
11737 // Fails on Android: http://anglebug.com/3839
11738 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
11739
11740 // IntermTraverser::insertStatementsInParentBlock that's used to move side effects does not
11741 // respect the order of evaluation of logical expressions. http://anglebug.com/3829.
11742 ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
11743
11744 constexpr char kFS[] = R"(#version 300 es
11745 precision highp float;
11746 out vec4 outColor;
11747
11748 layout(std140, column_major) uniform Ubo
11749 {
11750 mat4 m1;
11751 layout(row_major) mat4 m2[2];
11752 } ubo;
11753
11754 void main()
11755 {
11756 bool result = true;
11757
11758 int x = 0;
11759 if (x == 1 && ubo.m2[x = 1][1][1] == 5.0)
11760 {
11761 // First x == 1 should prevent the side effect of the second expression (x = 1) from
11762 // being executed. If x = 1 is run before the if, the condition of the if would be true,
11763 // which is a failure.
11764 result = false;
11765 }
11766 if (x == 1)
11767 {
11768 result = false;
11769 }
11770
11771 outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
11772 })";
11773
11774 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11775 EXPECT_GL_NO_ERROR();
11776
11777 constexpr size_t kMatrixCount = 3;
11778 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
11779 {4, 4},
11780 {4, 4},
11781 {4, 4},
11782 };
11783 constexpr bool kMatrixIsColMajor[kMatrixCount] = {true, false, false};
11784
11785 float data[kMatrixCount * 4 * 4] = {};
11786
11787 const uint32_t size =
11788 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
11789
11790 GLBuffer ubo;
11791 InitBuffer(program, "Ubo", ubo, 0, data, size, true);
11792
11793 EXPECT_GL_NO_ERROR();
11794
11795 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
11796 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
11797 }
11798
11799 // Test that dynamic indexing of swizzled l-values should work.
11800 // A simple porting of sdk/tests/conformance2/glsl3/vector-dynamic-indexing-swizzled-lvalue.html
TEST_P(GLSLTest_ES3,DynamicIndexingOfSwizzledLValuesShouldWork)11801 TEST_P(GLSLTest_ES3, DynamicIndexingOfSwizzledLValuesShouldWork)
11802 {
11803 // The shader first assigns v.x to v.z (1.0)
11804 // Then v.y to v.y (2.0)
11805 // Then v.z to v.x (1.0)
11806 constexpr char kFS[] = R"(#version 300 es
11807 precision highp float;
11808 out vec4 my_FragColor;
11809 void main() {
11810 vec3 v = vec3(1.0, 2.0, 3.0);
11811 for (int i = 0; i < 3; i++) {
11812 v.zyx[i] = v[i];
11813 }
11814 my_FragColor = distance(v, vec3(1.0, 2.0, 1.0)) < 0.01 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
11815 })";
11816
11817 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11818 EXPECT_GL_NO_ERROR();
11819 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
11820 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
11821 }
11822
11823 // Test that dead code after discard, return, continue and branch are pruned.
TEST_P(GLSLTest_ES3,DeadCodeIsPruned)11824 TEST_P(GLSLTest_ES3, DeadCodeIsPruned)
11825 {
11826 constexpr char kFS[] = R"(#version 300 es
11827 precision mediump float;
11828 out vec4 color;
11829
11830 vec4 f(vec4 c)
11831 {
11832 return c;
11833 // dead code
11834 c = vec4(0, 0, 1, 1);
11835 return c;
11836 }
11837
11838 void main()
11839 {
11840 vec4 result = vec4(0, 0.5, 0, 1);
11841 int var = int(result.y * 2.2);
11842
11843 {
11844 if (result.x > 1.0)
11845 {
11846 discard;
11847 // dead code
11848 result = vec4(1, 0, 0, 1);
11849 }
11850 for (int i = 0; i < 3; ++i)
11851 {
11852 if (i < 2)
11853 {
11854 result = f(result);
11855 continue;
11856 // dead code
11857 result = vec4(1, 0, 1, 1);
11858 }
11859 result = f(result);
11860 break;
11861 // dead code
11862 result = vec4(1, 0, 1, 0);
11863 }
11864 while (true)
11865 {
11866 if (result.x > -1.0)
11867 {
11868 {
11869 result = f(result);
11870 {
11871 break;
11872 // dead code
11873 result = vec4(1, 0, 0, 0);
11874 }
11875 // dead code
11876 for (int j = 0; j < 3; ++j)
11877 {
11878 if (j > 1) continue;
11879 result = vec4(0, 0, 1, 0);
11880 color = vec4(0.5, 0, 0.5, 0.5);
11881 return;
11882 }
11883 }
11884 // dead code
11885 result = vec4(0.5, 0, 0, 0);
11886 }
11887 }
11888 switch (var)
11889 {
11890 case 2:
11891 return;
11892 // dead code
11893 color = vec4(0.25, 0, 0.25, 0.25);
11894 case 1:
11895 {
11896 // Make sure this path is not pruned due to the return in the previous case.
11897 result.y += 0.5;
11898 break;
11899 // dead code
11900 color = vec4(0.25, 0, 0, 0);
11901 }
11902 // dead code
11903 color = vec4(0, 0, 0.25, 0);
11904 break;
11905 default:
11906 break;
11907 }
11908
11909 color = result;
11910 return;
11911 // dead code
11912 color = vec4(0, 0, 0.5, 0);
11913 }
11914 // dead code
11915 color = vec4(0, 0, 0, 0.5);
11916 })";
11917
11918 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11919
11920 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
11921 EXPECT_GL_NO_ERROR();
11922
11923 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
11924 }
11925
11926 // Regression test based on fuzzer issue. If a case has statements that are pruned, and those
11927 // pruned statements in turn have branches, and another case follows, a prior implementation of
11928 // dead-code elimination doubly pruned some statements.
TEST_P(GLSLTest_ES3,DeadCodeBranchInPrunedStatementsInCaseBeforeAnotherCase)11929 TEST_P(GLSLTest_ES3, DeadCodeBranchInPrunedStatementsInCaseBeforeAnotherCase)
11930 {
11931 constexpr char kFS[] = R"(#version 300 es
11932 precision mediump float;
11933 out vec4 color;
11934 void main()
11935 {
11936 color = vec4(0, 1, 0, 1);
11937 switch(0)
11938 {
11939 case 0:
11940 break;
11941 break;
11942 color = vec4(1, 0, 0, 1); // The bug was pruning this statement twice
11943 default:
11944 color = vec4(0, 0, 1, 1);
11945 break;
11946 }
11947 })";
11948
11949 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11950
11951 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
11952 EXPECT_GL_NO_ERROR();
11953
11954 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
11955 }
11956
11957 // Test shader with all resources (default uniform, UBO, SSBO, image, sampler and atomic counter) to
11958 // make sure they are all linked ok. The front-end sorts these resources and traverses the list of
11959 // "uniforms" to find the range for each resource. A bug there was causing some resource ranges to
11960 // be empty in the presence of other resources.
TEST_P(GLSLTest_ES31,MixOfAllResources)11961 TEST_P(GLSLTest_ES31, MixOfAllResources)
11962 {
11963 // http://anglebug.com/5072
11964 ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
11965
11966 constexpr char kComputeShader[] = R"(#version 310 es
11967 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
11968 layout(binding = 1, std430) buffer Output {
11969 uint ubo_value;
11970 uint default_value;
11971 uint sampler_value;
11972 uint ac_value;
11973 uint image_value;
11974 } outbuf;
11975 uniform Input {
11976 uint input_value;
11977 } inbuf;
11978 uniform uint default_uniform;
11979 uniform sampler2D smplr;
11980 layout(binding=0) uniform atomic_uint ac;
11981 layout(r32ui) uniform highp readonly uimage2D image;
11982
11983 void main(void)
11984 {
11985 outbuf.ubo_value = inbuf.input_value;
11986 outbuf.default_value = default_uniform;
11987 outbuf.sampler_value = uint(texture(smplr, vec2(0.5, 0.5)).x * 255.0);
11988 outbuf.ac_value = atomicCounterIncrement(ac);
11989 outbuf.image_value = imageLoad(image, ivec2(0, 0)).x;
11990 }
11991 )";
11992 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
11993 EXPECT_GL_NO_ERROR();
11994
11995 glUseProgram(program);
11996
11997 unsigned int inputData = 89u;
11998 GLBuffer inputBuffer;
11999 glBindBuffer(GL_UNIFORM_BUFFER, inputBuffer);
12000 glBufferData(GL_UNIFORM_BUFFER, sizeof(inputData), &inputData, GL_STATIC_DRAW);
12001 GLuint inputBufferIndex = glGetUniformBlockIndex(program, "Input");
12002 ASSERT_NE(inputBufferIndex, GL_INVALID_INDEX);
12003 glUniformBlockBinding(program, inputBufferIndex, 0);
12004 glBindBufferBase(GL_UNIFORM_BUFFER, 0, inputBuffer);
12005
12006 unsigned int outputInitData[5] = {0x12345678u, 0x09ABCDEFu, 0x56789ABCu, 0x0DEF1234u,
12007 0x13579BDFu};
12008 GLBuffer outputBuffer;
12009 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
12010 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), outputInitData, GL_STATIC_DRAW);
12011 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
12012 EXPECT_GL_NO_ERROR();
12013
12014 unsigned int uniformData = 456u;
12015 GLint uniformLocation = glGetUniformLocation(program, "default_uniform");
12016 ASSERT_NE(uniformLocation, -1);
12017 glUniform1ui(uniformLocation, uniformData);
12018
12019 unsigned int acData = 2u;
12020 GLBuffer atomicCounterBuffer;
12021 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
12022 glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(acData), &acData, GL_STATIC_DRAW);
12023 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
12024 EXPECT_GL_NO_ERROR();
12025
12026 unsigned int imageData = 33u;
12027 GLTexture image;
12028 glBindTexture(GL_TEXTURE_2D, image);
12029 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
12030 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &imageData);
12031 glBindImageTexture(0, image, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
12032 EXPECT_GL_NO_ERROR();
12033
12034 GLColor textureData(127, 18, 189, 211);
12035 GLTexture texture;
12036 glBindTexture(GL_TEXTURE_2D, texture);
12037 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &textureData);
12038 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12039 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12040 ASSERT_GL_NO_ERROR();
12041
12042 glDispatchCompute(1, 1, 1);
12043 EXPECT_GL_NO_ERROR();
12044
12045 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
12046
12047 // read back
12048 const GLuint *ptr = reinterpret_cast<const GLuint *>(
12049 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
12050 EXPECT_EQ(ptr[0], inputData);
12051 EXPECT_EQ(ptr[1], uniformData);
12052 EXPECT_NEAR(ptr[2], textureData.R, 1.0);
12053 EXPECT_EQ(ptr[3], acData);
12054 EXPECT_EQ(ptr[4], imageData);
12055
12056 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
12057 }
12058
12059 // Test that sending mixture of resources to functions works.
TEST_P(GLSLTest_ES31,MixOfResourcesAsFunctionArgs)12060 TEST_P(GLSLTest_ES31, MixOfResourcesAsFunctionArgs)
12061 {
12062 // http://anglebug.com/5546
12063 ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
12064
12065 // anglebug.com/3832 - no sampler array params on Android
12066 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
12067
12068 constexpr char kComputeShader[] = R"(#version 310 es
12069 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
12070
12071 layout(binding = 1, std430) buffer Output {
12072 uint success;
12073 } outbuf;
12074
12075 uniform uint initialAcValue;
12076 uniform sampler2D smplr[2][3];
12077 layout(binding=0) uniform atomic_uint ac;
12078
12079 bool sampler1DAndAtomicCounter(uvec3 sExpect, in sampler2D s[3], in atomic_uint a, uint aExpect)
12080 {
12081 uvec3 sResult = uvec3(uint(texture(s[0], vec2(0.5, 0.5)).x * 255.0),
12082 uint(texture(s[1], vec2(0.5, 0.5)).x * 255.0),
12083 uint(texture(s[2], vec2(0.5, 0.5)).x * 255.0));
12084 uint aResult = atomicCounterIncrement(a);
12085
12086 return sExpect == sResult && aExpect == aResult;
12087 }
12088
12089 bool sampler2DAndAtomicCounter(in sampler2D s[2][3], uint aInitial, in atomic_uint a)
12090 {
12091 bool success = true;
12092 success = sampler1DAndAtomicCounter(uvec3(0, 127, 255), s[0], a, aInitial) && success;
12093 success = sampler1DAndAtomicCounter(uvec3(31, 63, 191), s[1], a, aInitial + 1u) && success;
12094 return success;
12095 }
12096
12097 void main(void)
12098 {
12099 outbuf.success = uint(sampler2DAndAtomicCounter(smplr, initialAcValue, ac));
12100 }
12101 )";
12102 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
12103 EXPECT_GL_NO_ERROR();
12104
12105 glUseProgram(program);
12106
12107 unsigned int outputInitData = 0x12345678u;
12108 GLBuffer outputBuffer;
12109 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
12110 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
12111 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
12112 EXPECT_GL_NO_ERROR();
12113
12114 unsigned int acData = 2u;
12115 GLint uniformLocation = glGetUniformLocation(program, "initialAcValue");
12116 ASSERT_NE(uniformLocation, -1);
12117 glUniform1ui(uniformLocation, acData);
12118
12119 GLBuffer atomicCounterBuffer;
12120 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
12121 glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(acData), &acData, GL_STATIC_DRAW);
12122 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
12123 EXPECT_GL_NO_ERROR();
12124
12125 const std::array<GLColor, 6> kTextureData = {
12126 GLColor(0, 0, 0, 0), GLColor(127, 0, 0, 0), GLColor(255, 0, 0, 0),
12127 GLColor(31, 0, 0, 0), GLColor(63, 0, 0, 0), GLColor(191, 0, 0, 0),
12128 };
12129 GLTexture textures[2][3];
12130
12131 for (int dim1 = 0; dim1 < 2; ++dim1)
12132 {
12133 for (int dim2 = 0; dim2 < 3; ++dim2)
12134 {
12135 int textureUnit = dim1 * 3 + dim2;
12136 glActiveTexture(GL_TEXTURE0 + textureUnit);
12137 glBindTexture(GL_TEXTURE_2D, textures[dim1][dim2]);
12138 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
12139 &kTextureData[textureUnit]);
12140 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12141 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12142
12143 std::stringstream uniformName;
12144 uniformName << "smplr[" << dim1 << "][" << dim2 << "]";
12145 GLint samplerLocation = glGetUniformLocation(program, uniformName.str().c_str());
12146 EXPECT_NE(samplerLocation, -1);
12147 glUniform1i(samplerLocation, textureUnit);
12148 }
12149 }
12150 ASSERT_GL_NO_ERROR();
12151
12152 glDispatchCompute(1, 1, 1);
12153 EXPECT_GL_NO_ERROR();
12154
12155 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
12156
12157 // read back
12158 const GLuint *ptr = reinterpret_cast<const GLuint *>(
12159 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
12160 EXPECT_EQ(ptr[0], 1u);
12161
12162 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
12163 }
12164
12165 // Test that array of array of samplers used as function parameter with an index that has a
12166 // side-effect works.
TEST_P(GLSLTest_ES31,ArrayOfArrayOfSamplerAsFunctionParameterIndexedWithSideEffect)12167 TEST_P(GLSLTest_ES31, ArrayOfArrayOfSamplerAsFunctionParameterIndexedWithSideEffect)
12168 {
12169 // http://anglebug.com/5546
12170 ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
12171
12172 // anglebug.com/3832 - no sampler array params on Android
12173 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
12174
12175 // Skip if EXT_gpu_shader5 is not enabled.
12176 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
12177
12178 constexpr char kComputeShader[] = R"(#version 310 es
12179 #extension GL_EXT_gpu_shader5 : require
12180
12181 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
12182
12183 layout(binding = 1, std430) buffer Output {
12184 uint success;
12185 } outbuf;
12186
12187 uniform sampler2D smplr[2][3];
12188 layout(binding=0) uniform atomic_uint ac;
12189
12190 bool sampler1DAndAtomicCounter(uvec3 sExpect, in sampler2D s[3], in atomic_uint a, uint aExpect)
12191 {
12192 uvec3 sResult = uvec3(uint(texture(s[0], vec2(0.5, 0.5)).x * 255.0),
12193 uint(texture(s[1], vec2(0.5, 0.5)).x * 255.0),
12194 uint(texture(s[2], vec2(0.5, 0.5)).x * 255.0));
12195 uint aResult = atomicCounter(a);
12196
12197 return sExpect == sResult && aExpect == aResult;
12198 }
12199
12200 bool sampler2DAndAtomicCounter(in sampler2D s[2][3], uint aInitial, in atomic_uint a)
12201 {
12202 bool success = true;
12203 success = sampler1DAndAtomicCounter(uvec3(0, 127, 255),
12204 s[atomicCounterIncrement(ac)], a, aInitial + 1u) && success;
12205 success = sampler1DAndAtomicCounter(uvec3(31, 63, 191),
12206 s[atomicCounterIncrement(ac)], a, aInitial + 2u) && success;
12207 return success;
12208 }
12209
12210 void main(void)
12211 {
12212 outbuf.success = uint(sampler2DAndAtomicCounter(smplr, 0u, ac));
12213 }
12214 )";
12215 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
12216 EXPECT_GL_NO_ERROR();
12217
12218 glUseProgram(program);
12219
12220 unsigned int outputInitData = 0x12345678u;
12221 GLBuffer outputBuffer;
12222 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
12223 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
12224 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
12225 EXPECT_GL_NO_ERROR();
12226
12227 unsigned int acData = 0u;
12228 GLBuffer atomicCounterBuffer;
12229 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
12230 glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(acData), &acData, GL_STATIC_DRAW);
12231 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
12232 EXPECT_GL_NO_ERROR();
12233
12234 const std::array<GLColor, 6> kTextureData = {
12235 GLColor(0, 0, 0, 0), GLColor(127, 0, 0, 0), GLColor(255, 0, 0, 0),
12236 GLColor(31, 0, 0, 0), GLColor(63, 0, 0, 0), GLColor(191, 0, 0, 0),
12237 };
12238 GLTexture textures[2][3];
12239
12240 for (int dim1 = 0; dim1 < 2; ++dim1)
12241 {
12242 for (int dim2 = 0; dim2 < 3; ++dim2)
12243 {
12244 int textureUnit = dim1 * 3 + dim2;
12245 glActiveTexture(GL_TEXTURE0 + textureUnit);
12246 glBindTexture(GL_TEXTURE_2D, textures[dim1][dim2]);
12247 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
12248 &kTextureData[textureUnit]);
12249 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12250 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12251
12252 std::stringstream uniformName;
12253 uniformName << "smplr[" << dim1 << "][" << dim2 << "]";
12254 GLint samplerLocation = glGetUniformLocation(program, uniformName.str().c_str());
12255 EXPECT_NE(samplerLocation, -1);
12256 glUniform1i(samplerLocation, textureUnit);
12257 }
12258 }
12259 ASSERT_GL_NO_ERROR();
12260
12261 glDispatchCompute(1, 1, 1);
12262 EXPECT_GL_NO_ERROR();
12263
12264 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
12265
12266 // read back
12267 const GLuint *ptr = reinterpret_cast<const GLuint *>(
12268 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
12269 EXPECT_EQ(ptr[0], 1u);
12270
12271 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
12272 }
12273
testArrayOfArrayOfSamplerDynamicIndex(const APIExtensionVersion usedExtension)12274 void GLSLTest_ES31::testArrayOfArrayOfSamplerDynamicIndex(const APIExtensionVersion usedExtension)
12275 {
12276 ASSERT(usedExtension == APIExtensionVersion::EXT || usedExtension == APIExtensionVersion::OES);
12277
12278 int maxTextureImageUnits = 0;
12279 glGetIntegerv(GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
12280 ANGLE_SKIP_TEST_IF(maxTextureImageUnits < 24);
12281
12282 // anglebug.com/3832 - no sampler array params on Android
12283 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
12284
12285 // http://anglebug.com/5546
12286 ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
12287
12288 std::string computeShader;
12289 constexpr char kGLSLVersion[] = R"(#version 310 es
12290 )";
12291 constexpr char kGPUShaderEXT[] = R"(#extension GL_EXT_gpu_shader5 : require
12292 )";
12293 constexpr char kGPUShaderOES[] = R"(#extension GL_OES_gpu_shader5 : require
12294 )";
12295
12296 computeShader.append(kGLSLVersion);
12297 if (usedExtension == APIExtensionVersion::EXT)
12298 {
12299 computeShader.append(kGPUShaderEXT);
12300 }
12301 else
12302 {
12303 computeShader.append(kGPUShaderOES);
12304 }
12305
12306 constexpr char kComputeShaderBody[] = R"(
12307 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
12308
12309 layout(binding = 1, std430) buffer Output {
12310 uint success;
12311 } outbuf;
12312
12313 uniform sampler2D smplr[2][3][4];
12314 layout(binding=0) uniform atomic_uint ac;
12315
12316 bool sampler1DAndAtomicCounter(uvec4 sExpect, in sampler2D s[4], in atomic_uint a, uint aExpect)
12317 {
12318 uvec4 sResult = uvec4(uint(texture(s[0], vec2(0.5, 0.5)).x * 255.0),
12319 uint(texture(s[1], vec2(0.5, 0.5)).x * 255.0),
12320 uint(texture(s[2], vec2(0.5, 0.5)).x * 255.0),
12321 uint(texture(s[3], vec2(0.5, 0.5)).x * 255.0));
12322 uint aResult = atomicCounter(a);
12323
12324 return sExpect == sResult && aExpect == aResult;
12325 }
12326
12327 bool sampler3DAndAtomicCounter(in sampler2D s[2][3][4], uint aInitial, in atomic_uint a)
12328 {
12329 bool success = true;
12330 // [0][0]
12331 success = sampler1DAndAtomicCounter(uvec4(0, 8, 16, 24),
12332 s[atomicCounterIncrement(ac)][0], a, aInitial + 1u) && success;
12333 // [1][0]
12334 success = sampler1DAndAtomicCounter(uvec4(96, 104, 112, 120),
12335 s[atomicCounterIncrement(ac)][0], a, aInitial + 2u) && success;
12336 // [0][1]
12337 success = sampler1DAndAtomicCounter(uvec4(32, 40, 48, 56),
12338 s[0][atomicCounterIncrement(ac) - 1u], a, aInitial + 3u) && success;
12339 // [0][2]
12340 success = sampler1DAndAtomicCounter(uvec4(64, 72, 80, 88),
12341 s[0][atomicCounterIncrement(ac) - 1u], a, aInitial + 4u) && success;
12342 // [1][1]
12343 success = sampler1DAndAtomicCounter(uvec4(128, 136, 144, 152),
12344 s[1][atomicCounterIncrement(ac) - 3u], a, aInitial + 5u) && success;
12345 // [1][2]
12346 uint acValue = atomicCounterIncrement(ac); // Returns 5
12347 success = sampler1DAndAtomicCounter(uvec4(160, 168, 176, 184),
12348 s[acValue - 4u][atomicCounterIncrement(ac) - 4u], a, aInitial + 7u) && success;
12349
12350 return success;
12351 }
12352
12353 void main(void)
12354 {
12355 outbuf.success = uint(sampler3DAndAtomicCounter(smplr, 0u, ac));
12356 }
12357 )";
12358 computeShader.append(kComputeShaderBody);
12359
12360 ANGLE_GL_COMPUTE_PROGRAM(program, computeShader.c_str());
12361 EXPECT_GL_NO_ERROR();
12362
12363 glUseProgram(program);
12364
12365 unsigned int outputInitData = 0x12345678u;
12366 GLBuffer outputBuffer;
12367 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
12368 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
12369 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
12370 EXPECT_GL_NO_ERROR();
12371
12372 unsigned int acData = 0u;
12373 GLBuffer atomicCounterBuffer;
12374 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
12375 glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(acData), &acData, GL_STATIC_DRAW);
12376 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
12377 EXPECT_GL_NO_ERROR();
12378
12379 const std::array<GLColor, 24> kTextureData = {
12380 GLColor(0, 0, 0, 0), GLColor(8, 0, 0, 0), GLColor(16, 0, 0, 0), GLColor(24, 0, 0, 0),
12381 GLColor(32, 0, 0, 0), GLColor(40, 0, 0, 0), GLColor(48, 0, 0, 0), GLColor(56, 0, 0, 0),
12382 GLColor(64, 0, 0, 0), GLColor(72, 0, 0, 0), GLColor(80, 0, 0, 0), GLColor(88, 0, 0, 0),
12383 GLColor(96, 0, 0, 0), GLColor(104, 0, 0, 0), GLColor(112, 0, 0, 0), GLColor(120, 0, 0, 0),
12384 GLColor(128, 0, 0, 0), GLColor(136, 0, 0, 0), GLColor(144, 0, 0, 0), GLColor(152, 0, 0, 0),
12385 GLColor(160, 0, 0, 0), GLColor(168, 0, 0, 0), GLColor(176, 0, 0, 0), GLColor(184, 0, 0, 0),
12386 };
12387 GLTexture textures[2][3][4];
12388
12389 for (int dim1 = 0; dim1 < 2; ++dim1)
12390 {
12391 for (int dim2 = 0; dim2 < 3; ++dim2)
12392 {
12393 for (int dim3 = 0; dim3 < 4; ++dim3)
12394 {
12395 int textureUnit = (dim1 * 3 + dim2) * 4 + dim3;
12396 glActiveTexture(GL_TEXTURE0 + textureUnit);
12397 glBindTexture(GL_TEXTURE_2D, textures[dim1][dim2][dim3]);
12398 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
12399 &kTextureData[textureUnit]);
12400 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12401 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12402
12403 std::stringstream uniformName;
12404 uniformName << "smplr[" << dim1 << "][" << dim2 << "][" << dim3 << "]";
12405 GLint samplerLocation = glGetUniformLocation(program, uniformName.str().c_str());
12406 EXPECT_NE(samplerLocation, -1);
12407 glUniform1i(samplerLocation, textureUnit);
12408 }
12409 }
12410 }
12411 ASSERT_GL_NO_ERROR();
12412
12413 glDispatchCompute(1, 1, 1);
12414 EXPECT_GL_NO_ERROR();
12415
12416 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
12417
12418 // read back
12419 const GLuint *ptr = reinterpret_cast<const GLuint *>(
12420 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
12421 EXPECT_EQ(ptr[0], 1u);
12422
12423 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
12424 }
12425
12426 // Test that array of array of samplers can be indexed correctly with dynamic indices.
TEST_P(GLSLTest_ES31,ArrayOfArrayOfSamplerDynamicIndexEXT)12427 TEST_P(GLSLTest_ES31, ArrayOfArrayOfSamplerDynamicIndexEXT)
12428 {
12429 // Skip if EXT_gpu_shader5 is not enabled.
12430 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
12431 testArrayOfArrayOfSamplerDynamicIndex(APIExtensionVersion::EXT);
12432 }
12433
12434 // Test that array of array of samplers can be indexed correctly with dynamic indices.
TEST_P(GLSLTest_ES31,ArrayOfArrayOfSamplerDynamicIndexOES)12435 TEST_P(GLSLTest_ES31, ArrayOfArrayOfSamplerDynamicIndexOES)
12436 {
12437 // Skip if OES_gpu_shader5 is not enabled.
12438 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_gpu_shader5"));
12439 testArrayOfArrayOfSamplerDynamicIndex(APIExtensionVersion::OES);
12440 }
12441
12442 // Test that array of array of samplers can be indexed correctly with dynamic indices. Uses
12443 // samplers in structs.
TEST_P(GLSLTest_ES31,ArrayOfArrayOfSamplerInStructDynamicIndex)12444 TEST_P(GLSLTest_ES31, ArrayOfArrayOfSamplerInStructDynamicIndex)
12445 {
12446 // Skip if EXT_gpu_shader5 is not enabled.
12447 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
12448
12449 int maxTextureImageUnits = 0;
12450 glGetIntegerv(GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
12451 ANGLE_SKIP_TEST_IF(maxTextureImageUnits < 24);
12452
12453 // http://anglebug.com/5072
12454 ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
12455
12456 // anglebug.com/3832 - no sampler array params on Android
12457 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
12458
12459 // http://anglebug.com/5546
12460 ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
12461
12462 constexpr char kComputeShader[] = R"(#version 310 es
12463 #extension GL_EXT_gpu_shader5 : require
12464
12465 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
12466
12467 layout(binding = 1, std430) buffer Output {
12468 uint success;
12469 } outbuf;
12470
12471 struct I
12472 {
12473 uint index;
12474 };
12475
12476 struct S
12477 {
12478 sampler2D smplr[4];
12479 I nested;
12480 };
12481
12482 struct T
12483 {
12484 S nested[3];
12485 uint tIndex;
12486 };
12487
12488 uniform T u[2];
12489
12490 uint getValue(in sampler2D s)
12491 {
12492 return uint(texture(s, vec2(0.5, 0.5)).x * 255.0);
12493 }
12494
12495 bool sampler1DTest(uvec4 sExpect, in sampler2D s[4])
12496 {
12497 uvec4 sResult = uvec4(getValue(s[0]), getValue(s[1]),
12498 getValue(s[2]), getValue(s[3]));
12499
12500 return sExpect == sResult;
12501 }
12502
12503 bool samplerTest(T t, uint N)
12504 {
12505 // u[N].tIndex == 0 + N*4
12506 // u[N].nested[0].nested.index == 1 + N*4
12507 // u[N].nested[1].nested.index == 2 + N*4
12508 // u[N].nested[2].nested.index == 3 + N*4
12509
12510 uvec4 colorOffset = N * 3u * 4u * uvec4(8);
12511
12512 bool success = true;
12513 // [N][0]
12514 success = sampler1DTest(uvec4(0, 8, 16, 24) + colorOffset,
12515 t.nested[t.nested[0].nested.index - t.tIndex - 1u].smplr) && success;
12516 // [N][1]
12517 success = sampler1DTest(uvec4(32, 40, 48, 56) + colorOffset,
12518 t.nested[t.nested[1].nested.index - t.tIndex - 1u].smplr) && success;
12519 // [N][2]
12520 success = sampler1DTest(uvec4(64, 72, 80, 88) + colorOffset,
12521 t.nested[t.nested[2].nested.index - t.tIndex - 1u].smplr) && success;
12522
12523 return success;
12524 }
12525
12526 bool uniformTest(T t, uint N)
12527 {
12528 // Also verify that expressions that involve structs-with-samplers are correct when not
12529 // referecing the sampler.
12530
12531 bool success = true;
12532 success = (t.nested[0].nested.index - t.tIndex == 1u) && success;
12533 success = (t.nested[1].nested.index - t.tIndex == 2u) && success;
12534 success = (t.nested[2].nested.index - t.tIndex == 3u) && success;
12535
12536 success = (t.nested[t.nested[0].nested.index - t.tIndex - 1u].nested.index - t.tIndex == 1u)
12537 && success;
12538 success = (t.nested[t.nested[0].nested.index - t.tIndex ].nested.index - t.tIndex == 2u)
12539 && success;
12540 success = (t.nested[t.nested[0].nested.index - t.tIndex + 1u].nested.index - t.tIndex == 3u)
12541 && success;
12542
12543 success = (t.nested[
12544 t.nested[
12545 t.nested[2].nested.index - t.tIndex - 1u // 2
12546 ].nested.index - t.tIndex - 2u // 1
12547 ].nested.index - t.tIndex // 2
12548 == 2u) && success;
12549
12550 return success;
12551 }
12552
12553 void main(void)
12554 {
12555 bool success = samplerTest(u[0], 0u) && samplerTest(u[1], 1u)
12556 && uniformTest(u[0], 0u) && uniformTest(u[1], 1u);
12557 outbuf.success = uint(success);
12558 }
12559 )";
12560 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
12561 EXPECT_GL_NO_ERROR();
12562
12563 glUseProgram(program);
12564
12565 unsigned int outputInitData = 0x12345678u;
12566 GLBuffer outputBuffer;
12567 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
12568 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
12569 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
12570 EXPECT_GL_NO_ERROR();
12571
12572 const std::array<GLColor, 24> kTextureData = {
12573 GLColor(0, 0, 0, 0), GLColor(8, 0, 0, 0), GLColor(16, 0, 0, 0), GLColor(24, 0, 0, 0),
12574 GLColor(32, 0, 0, 0), GLColor(40, 0, 0, 0), GLColor(48, 0, 0, 0), GLColor(56, 0, 0, 0),
12575 GLColor(64, 0, 0, 0), GLColor(72, 0, 0, 0), GLColor(80, 0, 0, 0), GLColor(88, 0, 0, 0),
12576 GLColor(96, 0, 0, 0), GLColor(104, 0, 0, 0), GLColor(112, 0, 0, 0), GLColor(120, 0, 0, 0),
12577 GLColor(128, 0, 0, 0), GLColor(136, 0, 0, 0), GLColor(144, 0, 0, 0), GLColor(152, 0, 0, 0),
12578 GLColor(160, 0, 0, 0), GLColor(168, 0, 0, 0), GLColor(176, 0, 0, 0), GLColor(184, 0, 0, 0),
12579 };
12580 GLTexture textures[2][3][4];
12581
12582 for (int dim1 = 0; dim1 < 2; ++dim1)
12583 {
12584 for (int dim2 = 0; dim2 < 3; ++dim2)
12585 {
12586 for (int dim3 = 0; dim3 < 4; ++dim3)
12587 {
12588 int textureUnit = (dim1 * 3 + dim2) * 4 + dim3;
12589 glActiveTexture(GL_TEXTURE0 + textureUnit);
12590 glBindTexture(GL_TEXTURE_2D, textures[dim1][dim2][dim3]);
12591 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
12592 &kTextureData[textureUnit]);
12593 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12594 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12595
12596 std::stringstream uniformName;
12597 uniformName << "u[" << dim1 << "].nested[" << dim2 << "].smplr[" << dim3 << "]";
12598 GLint samplerLocation = glGetUniformLocation(program, uniformName.str().c_str());
12599 EXPECT_NE(samplerLocation, -1);
12600 glUniform1i(samplerLocation, textureUnit);
12601 }
12602
12603 std::stringstream uniformName;
12604 uniformName << "u[" << dim1 << "].nested[" << dim2 << "].nested.index";
12605 GLint nestedIndexLocation = glGetUniformLocation(program, uniformName.str().c_str());
12606 EXPECT_NE(nestedIndexLocation, -1);
12607 glUniform1ui(nestedIndexLocation, dim1 * 4 + dim2 + 1);
12608 }
12609
12610 std::stringstream uniformName;
12611 uniformName << "u[" << dim1 << "].tIndex";
12612 GLint indexLocation = glGetUniformLocation(program, uniformName.str().c_str());
12613 EXPECT_NE(indexLocation, -1);
12614 glUniform1ui(indexLocation, dim1 * 4);
12615 }
12616 ASSERT_GL_NO_ERROR();
12617
12618 glDispatchCompute(1, 1, 1);
12619 EXPECT_GL_NO_ERROR();
12620
12621 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
12622
12623 // read back
12624 const GLuint *ptr = reinterpret_cast<const GLuint *>(
12625 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
12626 EXPECT_EQ(ptr[0], 1u);
12627
12628 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
12629 }
12630
12631 // Test that array of array of samplers work when indexed with an expression that's derived from an
12632 // array of array of samplers.
TEST_P(GLSLTest_ES31,ArrayOfArrayOfSamplerIndexedWithArrayOfArrayOfSamplers)12633 TEST_P(GLSLTest_ES31, ArrayOfArrayOfSamplerIndexedWithArrayOfArrayOfSamplers)
12634 {
12635 // Skip if EXT_gpu_shader5 is not enabled.
12636 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
12637
12638 // anglebug.com/3832 - no sampler array params on Android
12639 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
12640
12641 constexpr char kComputeShader[] = R"(#version 310 es
12642 #extension GL_EXT_gpu_shader5 : require
12643
12644 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
12645
12646 layout(binding = 1, std430) buffer Output {
12647 uint success;
12648 } outbuf;
12649
12650 uniform sampler2D smplr[2][3];
12651
12652 uint getValue(in sampler2D s)
12653 {
12654 return uint(texture(s, vec2(0.5, 0.5)).x * 255.0);
12655 }
12656
12657 bool runTest(in sampler2D s[2][3])
12658 {
12659 // s[0][0] should contain 2
12660 // s[0][1] should contain 0
12661 // s[0][2] should contain 1
12662 // s[1][0] should contain 1
12663 // s[1][1] should contain 2
12664 // s[1][2] should contain 0
12665
12666 uint result = getValue(
12667 s[
12668 getValue(
12669 s[
12670 getValue(s[0][1]) // 0
12671 ][
12672 getValue(s[0][0]) // 2
12673 ]
12674 ) // s[0][2] -> 1
12675 ][
12676 getValue(
12677 s[
12678 getValue(s[1][0]) // 1
12679 ][
12680 getValue(s[1][1]) // 2
12681 ]
12682 ) // s[1][2] -> 0
12683 ]
12684 ); // s[1][0] -> 1
12685
12686 return result == 1u;
12687 }
12688
12689 void main(void)
12690 {
12691 outbuf.success = uint(runTest(smplr));
12692 }
12693 )";
12694 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
12695 EXPECT_GL_NO_ERROR();
12696
12697 glUseProgram(program);
12698
12699 unsigned int outputInitData = 0x12345678u;
12700 GLBuffer outputBuffer;
12701 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
12702 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
12703 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
12704 EXPECT_GL_NO_ERROR();
12705
12706 const std::array<GLColor, 6> kTextureData = {
12707 GLColor(2, 0, 0, 0), GLColor(0, 0, 0, 0), GLColor(1, 0, 0, 0),
12708 GLColor(1, 0, 0, 0), GLColor(2, 0, 0, 0), GLColor(0, 0, 0, 0),
12709 };
12710 GLTexture textures[2][3];
12711
12712 for (int dim1 = 0; dim1 < 2; ++dim1)
12713 {
12714 for (int dim2 = 0; dim2 < 3; ++dim2)
12715 {
12716 int textureUnit = dim1 * 3 + dim2;
12717 glActiveTexture(GL_TEXTURE0 + textureUnit);
12718 glBindTexture(GL_TEXTURE_2D, textures[dim1][dim2]);
12719 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
12720 &kTextureData[textureUnit]);
12721 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12722 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12723
12724 std::stringstream uniformName;
12725 uniformName << "smplr[" << dim1 << "][" << dim2 << "]";
12726 GLint samplerLocation = glGetUniformLocation(program, uniformName.str().c_str());
12727 EXPECT_NE(samplerLocation, -1);
12728 glUniform1i(samplerLocation, textureUnit);
12729 }
12730 }
12731 ASSERT_GL_NO_ERROR();
12732
12733 glDispatchCompute(1, 1, 1);
12734 EXPECT_GL_NO_ERROR();
12735
12736 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
12737
12738 // read back
12739 const GLuint *ptr = reinterpret_cast<const GLuint *>(
12740 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
12741 EXPECT_EQ(ptr[0], 1u);
12742
12743 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
12744 }
12745
12746 // Test that multiple nested assignments are handled correctly.
TEST_P(GLSLTest_ES31,MixedRowAndColumnMajorMatrices_WriteSideEffect)12747 TEST_P(GLSLTest_ES31, MixedRowAndColumnMajorMatrices_WriteSideEffect)
12748 {
12749 // http://anglebug.com/3831
12750 ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGL());
12751
12752 // Fails on windows AMD on GL: http://anglebug.com/3838
12753 ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL() && IsAMD());
12754 // http://anglebug.com/5384
12755 ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
12756
12757 // Fails on D3D due to mistranslation: http://anglebug.com/3841
12758 ANGLE_SKIP_TEST_IF(IsD3D11());
12759
12760 constexpr char kCS[] = R"(#version 310 es
12761 precision highp float;
12762 layout(local_size_x=1) in;
12763
12764 layout(std140, column_major) uniform Ubo
12765 {
12766 mat4 m1;
12767 layout(row_major) mat4 m2;
12768 } ubo;
12769
12770 layout(std140, row_major, binding = 0) buffer Ssbo
12771 {
12772 layout(column_major) mat4 m1;
12773 mat4 m2;
12774 } ssbo;
12775
12776 layout(std140, binding = 1) buffer Result
12777 {
12778 uint success;
12779 } resultOut;
12780
12781 void main()
12782 {
12783 bool result = true;
12784
12785 // Only assign to SSBO from a single invocation.
12786 if (gl_GlobalInvocationID.x == 0u)
12787 {
12788 if ((ssbo.m2 = ssbo.m1 = ubo.m1) != ubo.m2)
12789 {
12790 result = false;
12791 }
12792
12793 resultOut.success = uint(result);
12794 }
12795 })";
12796
12797 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
12798 EXPECT_GL_NO_ERROR();
12799
12800 constexpr size_t kMatrixCount = 2;
12801 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
12802 {4, 4},
12803 {4, 4},
12804 };
12805 constexpr bool kMatrixIsColMajor[kMatrixCount] = {
12806 true,
12807 false,
12808 };
12809
12810 float data[kMatrixCount * 4 * 4] = {};
12811 float zeros[kMatrixCount * 4 * 4] = {};
12812
12813 const uint32_t size =
12814 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
12815
12816 GLBuffer ubo, ssbo;
12817
12818 InitBuffer(program, "Ubo", ubo, 0, data, size, true);
12819 InitBuffer(program, "Ssbo", ssbo, 0, zeros, size, false);
12820 EXPECT_GL_NO_ERROR();
12821
12822 GLBuffer outputBuffer;
12823 CreateOutputBuffer(&outputBuffer, 1);
12824
12825 glUseProgram(program);
12826 glDispatchCompute(1, 1, 1);
12827 EXPECT_GL_NO_ERROR();
12828 EXPECT_TRUE(VerifySuccess(outputBuffer));
12829
12830 EXPECT_TRUE(VerifyBuffer(ssbo, data, size));
12831 }
12832
12833 // Test that assignments to array of array of matrices are handled correctly.
TEST_P(GLSLTest_ES31,MixedRowAndColumnMajorMatrices_WriteArrayOfArray)12834 TEST_P(GLSLTest_ES31, MixedRowAndColumnMajorMatrices_WriteArrayOfArray)
12835 {
12836 // Fails on windows AMD on GL: http://anglebug.com/3838
12837 ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL() && IsAMD());
12838 // http://anglebug.com/5384
12839 ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
12840
12841 // Fails on D3D due to mistranslation: http://anglebug.com/3841
12842 ANGLE_SKIP_TEST_IF(IsD3D11());
12843
12844 // Fails compiling shader on Android/Vulkan. http://anglebug.com/4290
12845 ANGLE_SKIP_TEST_IF(IsAndroid() && IsVulkan());
12846
12847 // Fails on ARM on Vulkan. http://anglebug.com/4492
12848 ANGLE_SKIP_TEST_IF(IsARM() && IsVulkan());
12849
12850 constexpr char kCS[] = R"(#version 310 es
12851 precision highp float;
12852 layout(local_size_x=1) in;
12853
12854 layout(std140, column_major) uniform Ubo
12855 {
12856 mat4 m1;
12857 layout(row_major) mat4 m2[2][3];
12858 } ubo;
12859
12860 layout(std140, row_major, binding = 0) buffer Ssbo
12861 {
12862 layout(column_major) mat4 m1;
12863 mat4 m2[2][3];
12864 } ssbo;
12865
12866 layout(std140, binding = 1) buffer Result
12867 {
12868 uint success;
12869 } resultOut;
12870
12871 void main()
12872 {
12873 bool result = true;
12874
12875 // Only assign to SSBO from a single invocation.
12876 if (gl_GlobalInvocationID.x == 0u)
12877 {
12878 ssbo.m1 = ubo.m1;
12879 ssbo.m2 = ubo.m2;
12880
12881 resultOut.success = uint(result);
12882 }
12883 })";
12884
12885 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
12886 EXPECT_GL_NO_ERROR();
12887
12888 constexpr size_t kMatrixCount = 7;
12889 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
12890 {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4},
12891 };
12892 constexpr bool kMatrixIsColMajor[kMatrixCount] = {
12893 true, false, false, false, false, false, false,
12894 };
12895
12896 float data[kMatrixCount * 4 * 4] = {};
12897 float zeros[kMatrixCount * 4 * 4] = {};
12898
12899 const uint32_t size =
12900 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
12901
12902 GLBuffer ubo, ssbo;
12903
12904 InitBuffer(program, "Ubo", ubo, 0, data, size, true);
12905 InitBuffer(program, "Ssbo", ssbo, 0, zeros, size, false);
12906 EXPECT_GL_NO_ERROR();
12907
12908 GLBuffer outputBuffer;
12909 CreateOutputBuffer(&outputBuffer, 1);
12910
12911 glUseProgram(program);
12912 glDispatchCompute(1, 1, 1);
12913 EXPECT_GL_NO_ERROR();
12914 EXPECT_TRUE(VerifySuccess(outputBuffer));
12915
12916 EXPECT_TRUE(VerifyBuffer(ssbo, data, size));
12917 }
12918
12919 // Verify that types used differently (in different block storages, differently qualified etc) work
12920 // when copied around.
TEST_P(GLSLTest_ES31,TypesUsedInDifferentBlockStorages)12921 TEST_P(GLSLTest_ES31, TypesUsedInDifferentBlockStorages)
12922 {
12923 constexpr char kCS[] = R"(#version 310 es
12924 precision highp float;
12925 layout(local_size_x=1) in;
12926
12927 struct Inner
12928 {
12929 mat3x2 m;
12930 float f[3];
12931 uvec2 u[2][4];
12932 ivec3 i;
12933 mat2x3 m2[3][2];
12934 };
12935
12936 struct Outer
12937 {
12938 Inner i[2];
12939 };
12940
12941 layout(std140, column_major) uniform Ubo140c
12942 {
12943 mat2 m;
12944 layout(row_major) Outer o;
12945 } ubo140cIn;
12946
12947 layout(std430, row_major, binding = 0) buffer Ubo430r
12948 {
12949 mat2 m;
12950 layout(column_major) Outer o;
12951 } ubo430rIn;
12952
12953 layout(std140, column_major, binding = 1) buffer Ssbo140c
12954 {
12955 layout(row_major) mat2 m[2];
12956 Outer o;
12957 layout(row_major) Inner i;
12958 } ssbo140cOut;
12959
12960 layout(std430, row_major, binding = 2) buffer Ssbo430r
12961 {
12962 layout(column_major) mat2 m[2];
12963 Outer o;
12964 layout(column_major) Inner i;
12965 } ssbo430rOut;
12966
12967 void writeArgToStd140(uvec2 u[2][4], int innerIndex)
12968 {
12969 ssbo140cOut.o.i[innerIndex].u = u;
12970 }
12971
12972 void writeBlockArgToStd140(Inner i, int innerIndex)
12973 {
12974 ssbo140cOut.o.i[innerIndex] = i;
12975 }
12976
12977 mat2x3[3][2] readFromStd140(int innerIndex)
12978 {
12979 return ubo140cIn.o.i[0].m2;
12980 }
12981
12982 Inner readBlockFromStd430(int innerIndex)
12983 {
12984 return ubo430rIn.o.i[innerIndex];
12985 }
12986
12987 void copyFromStd140(out Inner i)
12988 {
12989 i = ubo140cIn.o.i[1];
12990 }
12991
12992 void main(){
12993 // Directly copy from one layout to another.
12994 ssbo140cOut.m[0] = ubo140cIn.m;
12995 ssbo140cOut.m[1] = ubo430rIn.m;
12996 ssbo140cOut.o.i[0].m = ubo140cIn.o.i[0].m;
12997 ssbo140cOut.o.i[0].f = ubo140cIn.o.i[0].f;
12998 ssbo140cOut.o.i[0].i = ubo140cIn.o.i[0].i;
12999
13000 // Read from block and pass to function.
13001 writeArgToStd140(ubo140cIn.o.i[0].u, 0);
13002 writeBlockArgToStd140(ubo430rIn.o.i[0], 1);
13003
13004 // Have function return value read from block.
13005 ssbo140cOut.o.i[0].m2 = readFromStd140(0);
13006
13007 // Have function fill in value as out parameter.
13008 copyFromStd140(ssbo140cOut.i);
13009
13010 // Initialize local variable.
13011 mat2 mStd140 = ubo140cIn.m;
13012
13013 // Copy to variable, through multiple assignments.
13014 mat2 mStd430, temp;
13015 mStd430 = temp = ubo430rIn.m;
13016
13017 // Copy from local variable
13018 ssbo430rOut.m[0] = mStd140;
13019 ssbo430rOut.m[1] = mStd430;
13020
13021 // Construct from struct.
13022 Inner iStd140 = ubo140cIn.o.i[1];
13023 Outer oStd140 = Outer(Inner[2](iStd140, ubo430rIn.o.i[1]));
13024
13025 // Copy struct from local variable.
13026 ssbo430rOut.o = oStd140;
13027
13028 // Construct from arrays
13029 Inner iStd430 = Inner(ubo430rIn.o.i[1].m,
13030 ubo430rIn.o.i[1].f,
13031 ubo430rIn.o.i[1].u,
13032 ubo430rIn.o.i[1].i,
13033 ubo430rIn.o.i[1].m2);
13034 ssbo430rOut.i = iStd430;
13035 })";
13036
13037 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
13038 EXPECT_GL_NO_ERROR();
13039
13040 // Test data, laid out with padding (0) based on std140/std430 rules.
13041 // clang-format off
13042 const std::vector<float> ubo140cData = {
13043 // m (mat2, column-major)
13044 1, 2, 0, 0, 3, 4, 0, 0,
13045
13046 // o.i[0].m (mat3x2, row-major)
13047 5, 7, 9, 0, 6, 8, 10, 0,
13048 // o.i[0].f (float[3])
13049 12, 0, 0, 0, 13, 0, 0, 0, 14, 0, 0, 0,
13050 // o.i[0].u (uvec2[2][4])
13051 15, 16, 0, 0, 17, 18, 0, 0, 19, 20, 0, 0, 21, 22, 0, 0,
13052 23, 24, 0, 0, 25, 26, 0, 0, 27, 28, 0, 0, 29, 30, 0, 0,
13053 // o.i[0].i (ivec3)
13054 31, 32, 33, 0,
13055 // o.i[0].m2 (mat2x3[3][2], row-major)
13056 34, 37, 0, 0, 35, 38, 0, 0, 36, 39, 0, 0,
13057 40, 43, 0, 0, 41, 44, 0, 0, 42, 45, 0, 0,
13058 46, 49, 0, 0, 47, 50, 0, 0, 48, 51, 0, 0,
13059 52, 55, 0, 0, 53, 56, 0, 0, 54, 57, 0, 0,
13060 58, 61, 0, 0, 59, 62, 0, 0, 60, 63, 0, 0,
13061 64, 67, 0, 0, 65, 68, 0, 0, 66, 69, 0, 0,
13062
13063 // o.i[1].m (mat3x2, row-major)
13064 70, 72, 74, 0, 71, 73, 75, 0,
13065 // o.i[1].f (float[3])
13066 77, 0, 0, 0, 78, 0, 0, 0, 79, 0, 0, 0,
13067 // o.i[1].u (uvec2[2][4])
13068 80, 81, 0, 0, 82, 83, 0, 0, 84, 85, 0, 0, 86, 87, 0, 0,
13069 88, 89, 0, 0, 90, 91, 0, 0, 92, 93, 0, 0, 94, 95, 0, 0,
13070 // o.i[1].i (ivec3)
13071 96, 97, 98, 0,
13072 // o.i[1].m2 (mat2x3[3][2], row-major)
13073 99, 102, 0, 0, 100, 103, 0, 0, 101, 104, 0, 0,
13074 105, 108, 0, 0, 106, 109, 0, 0, 107, 110, 0, 0,
13075 111, 114, 0, 0, 112, 115, 0, 0, 113, 116, 0, 0,
13076 117, 120, 0, 0, 118, 121, 0, 0, 119, 122, 0, 0,
13077 123, 126, 0, 0, 124, 127, 0, 0, 125, 128, 0, 0,
13078 129, 132, 0, 0, 130, 133, 0, 0, 131, 134, 0, 0,
13079 };
13080 const std::vector<float> ubo430rData = {
13081 // m (mat2, row-major)
13082 135, 137, 136, 138,
13083
13084 // o.i[0].m (mat3x2, column-major)
13085 139, 140, 141, 142, 143, 144,
13086 // o.i[0].f (float[3])
13087 146, 147, 148, 0,
13088 // o.i[0].u (uvec2[2][4])
13089 149, 150, 151, 152, 153, 154, 155, 156,
13090 157, 158, 159, 160, 161, 162, 163, 164, 0, 0,
13091 // o.i[0].i (ivec3)
13092 165, 166, 167, 0,
13093 // o.i[0].m2 (mat2x3[3][2], column-major)
13094 168, 169, 170, 0, 171, 172, 173, 0,
13095 174, 175, 176, 0, 177, 178, 179, 0,
13096 180, 181, 182, 0, 183, 184, 185, 0,
13097 186, 187, 188, 0, 189, 190, 191, 0,
13098 192, 193, 194, 0, 195, 196, 197, 0,
13099 198, 199, 200, 0, 201, 202, 203, 0,
13100
13101 // o.i[1].m (mat3x2, column-major)
13102 204, 205, 206, 207, 208, 209,
13103 // o.i[1].f (float[3])
13104 211, 212, 213, 0,
13105 // o.i[1].u (uvec2[2][4])
13106 214, 215, 216, 217, 218, 219, 220, 221,
13107 222, 223, 224, 225, 226, 227, 228, 229, 0, 0,
13108 // o.i[1].i (ivec3)
13109 230, 231, 232, 0,
13110 // o.i[1].m2 (mat2x3[3][2], column-major)
13111 233, 234, 235, 0, 236, 237, 238, 0,
13112 239, 240, 241, 0, 242, 243, 244, 0,
13113 245, 246, 247, 0, 248, 249, 250, 0,
13114 251, 252, 253, 0, 254, 255, 256, 0,
13115 257, 258, 259, 0, 260, 261, 262, 0,
13116 263, 264, 265, 0, 266, 267, 268, 0,
13117 };
13118 const std::vector<float> ssbo140cExpect = {
13119 // m (mat2[2], row-major), m[0] copied from ubo140cIn.m, m[1] from ubo430rIn.m
13120 1, 3, 0, 0, 2, 4, 0, 0,
13121 135, 137, 0, 0, 136, 138, 0, 0,
13122
13123 // o.i[0].m (mat3x2, column-major), copied from ubo140cIn.o.i[0].m
13124 5, 6, 0, 0, 7, 8, 0, 0, 9, 10, 0, 0,
13125 // o.i[0].f (float[3]), copied from ubo140cIn.o.i[0].f
13126 12, 0, 0, 0, 13, 0, 0, 0, 14, 0, 0, 0,
13127 // o.i[0].u (uvec2[2][4]), copied from ubo140cIn.o.i[0].u
13128 15, 16, 0, 0, 17, 18, 0, 0, 19, 20, 0, 0, 21, 22, 0, 0,
13129 23, 24, 0, 0, 25, 26, 0, 0, 27, 28, 0, 0, 29, 30, 0, 0,
13130 // o.i[0].i (ivec3), copied from ubo140cIn.o.i[0].i
13131 31, 32, 33, 0,
13132 // o.i[0].m2 (mat2x3[3][2], column-major), copied from ubo140cIn.o.i[0].m2
13133 34, 35, 36, 0, 37, 38, 39, 0,
13134 40, 41, 42, 0, 43, 44, 45, 0,
13135 46, 47, 48, 0, 49, 50, 51, 0,
13136 52, 53, 54, 0, 55, 56, 57, 0,
13137 58, 59, 60, 0, 61, 62, 63, 0,
13138 64, 65, 66, 0, 67, 68, 69, 0,
13139
13140 // o.i[1].m (mat3x2, column-major), copied from ubo430rIn.o.i[0].m
13141 139, 140, 0, 0, 141, 142, 0, 0, 143, 144, 0, 0,
13142 // o.i[1].f (float[3]), copied from ubo430rIn.o.i[0].f
13143 146, 0, 0, 0, 147, 0, 0, 0, 148, 0, 0, 0,
13144 // o.i[1].u (uvec2[2][4]), copied from ubo430rIn.o.i[0].u
13145 149, 150, 0, 0, 151, 152, 0, 0, 153, 154, 0, 0, 155, 156, 0, 0,
13146 157, 158, 0, 0, 159, 160, 0, 0, 161, 162, 0, 0, 163, 164, 0, 0,
13147 // o.i[1].i (ivec3), copied from ubo430rIn.o.i[0].i
13148 165, 166, 167, 0,
13149 // o.i[1].m2 (mat2x3[3][2], column-major), copied from ubo430rIn.o.i[0].m2
13150 168, 169, 170, 0, 171, 172, 173, 0,
13151 174, 175, 176, 0, 177, 178, 179, 0,
13152 180, 181, 182, 0, 183, 184, 185, 0,
13153 186, 187, 188, 0, 189, 190, 191, 0,
13154 192, 193, 194, 0, 195, 196, 197, 0,
13155 198, 199, 200, 0, 201, 202, 203, 0,
13156
13157 // i.m (mat3x2, row-major), copied from ubo140cIn.o.i[1].m
13158 70, 72, 74, 0, 71, 73, 75, 0,
13159 // i.f (float[3]), copied from ubo140cIn.o.i[1].f
13160 77, 0, 0, 0, 78, 0, 0, 0, 79, 0, 0, 0,
13161 // i.u (uvec2[2][4]), copied from ubo430rIn.o.i[1].u
13162 80, 81, 0, 0, 82, 83, 0, 0, 84, 85, 0, 0, 86, 87, 0, 0,
13163 88, 89, 0, 0, 90, 91, 0, 0, 92, 93, 0, 0, 94, 95, 0, 0,
13164 // i.i (ivec3), copied from ubo140cIn.o.i[1].i
13165 96, 97, 98, 0,
13166 // i.m2 (mat2x3[3][2], row-major), copied from ubo140cIn.o.i[1].m2
13167 99, 102, 0, 0, 100, 103, 0, 0, 101, 104, 0, 0,
13168 105, 108, 0, 0, 106, 109, 0, 0, 107, 110, 0, 0,
13169 111, 114, 0, 0, 112, 115, 0, 0, 113, 116, 0, 0,
13170 117, 120, 0, 0, 118, 121, 0, 0, 119, 122, 0, 0,
13171 123, 126, 0, 0, 124, 127, 0, 0, 125, 128, 0, 0,
13172 129, 132, 0, 0, 130, 133, 0, 0, 131, 134, 0, 0,
13173 };
13174 const std::vector<float> ssbo430rExpect = {
13175 // m (mat2[2], column-major), m[0] copied from ubo140cIn.m, m[1] from ubo430rIn.m
13176 1, 2, 3, 4,
13177 135, 136, 137, 138,
13178
13179 // o.i[0].m (mat3x2, row-major), copied from ubo140cIn.o.i[1].m
13180 70, 72, 74, 0, 71, 73, 75, 0,
13181 // o.i[0].f (float[3]), copied from ubo140cIn.o.i[1].f
13182 77, 78, 79, 0,
13183 // o.i[0].u (uvec2[2][4]), copied from ubo140cIn.o.i[1].u
13184 80, 81, 82, 83, 84, 85, 86, 87,
13185 88, 89, 90, 91, 92, 93, 94, 95,
13186 // o.i[0].i (ivec3), copied from ubo140cIn.o.i[1].i
13187 96, 97, 98, 0,
13188 // o.i[0].m2 (mat2x3[3][2], row-major), copied from ubo140cIn.o.i[1].m2
13189 99, 102, 100, 103, 101, 104,
13190 105, 108, 106, 109, 107, 110,
13191 111, 114, 112, 115, 113, 116,
13192 117, 120, 118, 121, 119, 122,
13193 123, 126, 124, 127, 125, 128,
13194 129, 132, 130, 133, 131, 134,
13195
13196 // o.i[1].m (mat3x2, row-major), copied from ubo430rIn.o.i[1].m
13197 204, 206, 208, 0, 205, 207, 209, 0,
13198 // o.i[1].f (float[3]), copied from ubo430rIn.o.i[1].f
13199 211, 212, 213, 0,
13200 // o.i[1].u (uvec2[2][4]), copied from ubo430rIn.o.i[1].u
13201 214, 215, 216, 217, 218, 219, 220, 221,
13202 222, 223, 224, 225, 226, 227, 228, 229,
13203 // o.i[1].i (ivec3), copied from ubo430rIn.o.i[1].i
13204 230, 231, 232, 0,
13205 // o.i[1].m2 (mat2x3[3][2], row-major), copied from ubo430rIn.o.i[1].m2
13206 233, 236, 234, 237, 235, 238,
13207 239, 242, 240, 243, 241, 244,
13208 245, 248, 246, 249, 247, 250,
13209 251, 254, 252, 255, 253, 256,
13210 257, 260, 258, 261, 259, 262,
13211 263, 266, 264, 267, 265, 268,
13212
13213 // i.m (mat3x2, column-major), copied from ubo430rIn.o.i[1].m
13214 204, 205, 206, 207, 208, 209,
13215 // i.f (float[3]), copied from ubo430rIn.o.i[1].f
13216 211, 212, 213, 0,
13217 // i.u (uvec2[2][4]), copied from ubo430rIn.o.i[1].u
13218 214, 215, 216, 217, 218, 219, 220, 221,
13219 222, 223, 224, 225, 226, 227, 228, 229, 0, 0,
13220 // i.i (ivec3), copied from ubo430rIn.o.i[1].i
13221 230, 231, 232, 0,
13222 // i.m2 (mat2x3[3][2], column-major), copied from ubo430rIn.o.i[1].m2
13223 233, 234, 235, 0, 236, 237, 238, 0,
13224 239, 240, 241, 0, 242, 243, 244, 0,
13225 245, 246, 247, 0, 248, 249, 250, 0,
13226 251, 252, 253, 0, 254, 255, 256, 0,
13227 257, 258, 259, 0, 260, 261, 262, 0,
13228 263, 264, 265, 0, 266, 267, 268, 0,
13229 };
13230 const std::vector<float> zeros(std::max(ssbo140cExpect.size(), ssbo430rExpect.size()), 0);
13231 // clang-format on
13232
13233 GLBuffer uboStd140ColMajor, uboStd430RowMajor;
13234 GLBuffer ssboStd140ColMajor, ssboStd430RowMajor;
13235
13236 InitBuffer(program, "Ubo140c", uboStd140ColMajor, 0, ubo140cData.data(),
13237 static_cast<uint32_t>(ubo140cData.size()), true);
13238 InitBuffer(program, "Ubo430r", uboStd430RowMajor, 0, ubo430rData.data(),
13239 static_cast<uint32_t>(ubo430rData.size()), false);
13240 InitBuffer(program, "Ssbo140c", ssboStd140ColMajor, 1, zeros.data(),
13241 static_cast<uint32_t>(ssbo140cExpect.size()), false);
13242 InitBuffer(program, "Ssbo430r", ssboStd430RowMajor, 2, zeros.data(),
13243 static_cast<uint32_t>(ssbo430rExpect.size()), false);
13244 EXPECT_GL_NO_ERROR();
13245
13246 glUseProgram(program);
13247 glDispatchCompute(1, 1, 1);
13248 EXPECT_GL_NO_ERROR();
13249
13250 EXPECT_TRUE(VerifyBuffer(ssboStd140ColMajor, ssbo140cExpect.data(),
13251 static_cast<uint32_t>(ssbo140cExpect.size())));
13252 EXPECT_TRUE(VerifyBuffer(ssboStd430RowMajor, ssbo430rExpect.data(),
13253 static_cast<uint32_t>(ssbo430rExpect.size())));
13254 }
13255
13256 // Verify that bool in interface blocks work.
TEST_P(GLSLTest_ES31,BoolInInterfaceBlocks)13257 TEST_P(GLSLTest_ES31, BoolInInterfaceBlocks)
13258 {
13259 constexpr char kCS[] = R"(#version 310 es
13260 precision highp float;
13261 layout(local_size_x=1) in;
13262
13263 struct Inner
13264 {
13265 bool b;
13266 bvec2 b2;
13267 bvec3 b3;
13268 bvec4 b4;
13269 bool ba[5];
13270 bvec2 b2a[2][3];
13271 };
13272
13273 struct Outer
13274 {
13275 Inner i[2];
13276 };
13277
13278 layout(std140) uniform Ubo140
13279 {
13280 Outer o;
13281 };
13282
13283 layout(std430, binding = 0) buffer Ubo430
13284 {
13285 Outer o;
13286 } ubo430In;
13287
13288 layout(std140, binding = 1) buffer Ssbo140
13289 {
13290 bool valid;
13291 Inner i;
13292 } ssbo140Out;
13293
13294 layout(std430, binding = 2) buffer Ssbo430
13295 {
13296 bool valid;
13297 Inner i;
13298 };
13299
13300 void writeArgToStd430(bool ba[5])
13301 {
13302 i.ba = ba;
13303 }
13304
13305 bool[5] readFromStd430(uint innerIndex)
13306 {
13307 return ubo430In.o.i[innerIndex].ba;
13308 }
13309
13310 void copyFromStd430(out bvec2 b2a[2][3])
13311 {
13312 b2a = ubo430In.o.i[0].b2a;
13313 }
13314
13315 bool destroyContent(inout Inner iOut)
13316 {
13317 iOut.b = true;
13318 iOut.b2 = bvec2(true);
13319 iOut.b3 = bvec3(true);
13320 iOut.b4 = bvec4(true);
13321 iOut.ba = bool[5](true, true, true, true, true);
13322 bvec2 true3[3] = bvec2[3](iOut.b2, iOut.b2, iOut.b2);
13323 iOut.b2a = bvec2[2][3](true3, true3);
13324 return true;
13325 }
13326
13327 void main(){
13328 // Directly copy from one layout to another.
13329 i.b = o.i[0].b;
13330 i.b2 = o.i[0].b2;
13331 i.b2a = o.i[0].b2a;
13332
13333 // Copy to temp with swizzle.
13334 bvec4 t1 = o.i[0].b3.yxzy;
13335 bvec4 t2 = o.i[0].b4.xxyy;
13336 bvec4 t3 = o.i[0].b4.zzww;
13337
13338 // Copy from temp with swizzle.
13339 i.b3 = t1.ywz;
13340 i.b4.yz = bvec2(t2.z, t3.y);
13341 i.b4.wx = bvec2(t3.w, t2.x);
13342
13343 // Copy by passing argument to function.
13344 writeArgToStd430(o.i[0].ba);
13345
13346 // Copy by return value.
13347 ssbo140Out.i.ba = readFromStd430(0u);
13348
13349 // Copy by out parameter.
13350 copyFromStd430(ssbo140Out.i.b2a);
13351
13352 // Logical operations
13353 uvec4 t4 = ubo430In.o.i[0].b ? uvec4(0) : uvec4(1);
13354 ssbo140Out.i.b = all(equal(t4, uvec4(1))) && (ubo430In.o.i[0].b ? false : true);
13355 ssbo140Out.i.b2 = not(ubo430In.o.i[0].b2);
13356 ssbo140Out.i.b3 = bvec3(all(ubo430In.o.i[0].b3), any(ubo430In.o.i[0].b3), any(ubo430In.o.i[0].b3.yx));
13357 ssbo140Out.i.b4 = equal(ubo430In.o.i[0].b4, bvec4(true, false, true, false));
13358
13359 ssbo140Out.valid = true;
13360 ssbo140Out.valid = ssbo140Out.valid && all(equal(bvec3(o.i[1].b, o.i[1].b2), o.i[1].b3));
13361 ssbo140Out.valid = ssbo140Out.valid &&
13362 all(notEqual(o.i[1].b4, bvec4(o.i[1].ba[0], o.i[1].ba[1], o.i[1].ba[2], o.i[1].ba[3])));
13363 ssbo140Out.valid = ssbo140Out.valid && uint(o.i[1].ba[4]) == 1u;
13364 for (int x = 0; x < o.i[1].b2a.length(); ++x)
13365 {
13366 for (int y = 0; y < o.i[1].b2a[x].length(); ++y)
13367 {
13368 ssbo140Out.valid = ssbo140Out.valid && all(equal(uvec2(o.i[1].b2a[x][y]), uvec2(x % 2, y % 2)));
13369 }
13370 }
13371
13372 valid = o.i[1] == ubo430In.o.i[1];
13373
13374 // Make sure short-circuiting behavior is correct.
13375 bool falseVar = !valid && destroyContent(i);
13376 if (falseVar && destroyContent(ssbo140Out.i))
13377 {
13378 valid = false;
13379 }
13380
13381 if (valid || o.i[uint((i.ba = bool[5](true, true, true, true, true))[1])].b)
13382 {
13383 }
13384 else
13385 {
13386 ssbo140Out.valid = false;
13387 }
13388 })";
13389
13390 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
13391 EXPECT_GL_NO_ERROR();
13392
13393 // Test data, laid out with padding (0) based on std140/std430 rules.
13394 // clang-format off
13395 const std::vector<uint32_t> ubo140Data = {
13396 // o.i[0].b (bool)
13397 true, 0,
13398 // o.i[0].b2 (bvec2)
13399 true, false,
13400 // o.i[0].b3 (bvec3)
13401 true, true, false, 0,
13402 // o.i[0].b4 (bvec4)
13403 false, true, false, true,
13404 // o.i[0].ba (bool[5])
13405 true, 0, 0, 0,
13406 false, 0, 0, 0,
13407 false, 0, 0, 0,
13408 true, 0, 0, 0,
13409 true, 0, 0, 0,
13410 // o.i[0].b2a (bool[2][3])
13411 false, true, 0, 0, true, true, 0, 0, true, false, 0, 0,
13412 true, false, 0, 0, false, false, 0, 0, true, true, 0, 0,
13413
13414 // o.i[1].b (bool)
13415 false, 0,
13416 // o.i[1].b2 (bvec2)
13417 true, true,
13418 // o.i[1].b3 (bvec3), expected to be equal to (b, b2)
13419 false, true, true, 0,
13420 // o.i[1].b4 (bvec4)
13421 true, false, true, true,
13422 // o.i[1].ba (bool[5]), expected to be equal to (not(b4), 1)
13423 false, 0, 0, 0,
13424 true, 0, 0, 0,
13425 false, 0, 0, 0,
13426 false, 0, 0, 0,
13427 true, 0, 0, 0,
13428 // o.i[1].b2a (bvec2[2][3]), [x][y] expected to equal (x%2,y%2)
13429 false, false, 0, 0, false, true, 0, 0, false, false, 0, 0,
13430 true, false, 0, 0, true, true, 0, 0, true, false, 0, 0,
13431 };
13432 const std::vector<uint32_t> ubo430Data = {
13433 // o.i[0].b (bool)
13434 false, 0,
13435 // o.i[0].b2 (bvec2)
13436 true, true,
13437 // o.i[0].b3 (bvec3)
13438 false, false, true, 0,
13439 // o.i[0].b4 (bvec4)
13440 true, false, true, true,
13441 // o.i[0].ba (bool[5])
13442 false, false, false, true, false, 0,
13443 // o.i[0].b2a (bool[2][3])
13444 true, false, true, false, true, true,
13445 false, true, true, true, false, false, 0, 0,
13446
13447 // o.i[1] expected to be equal to ubo140In.o.i[1]
13448 // o.i[1].b (bool)
13449 false, 0,
13450 // o.i[1].b2 (bvec2)
13451 true, true,
13452 // o.i[1].b3 (bvec3)
13453 false, true, true, 0,
13454 // o.i[1].b4 (bvec4)
13455 true, false, true, true,
13456 // o.i[1].ba (bool[5])
13457 false, true, false, false, true, 0,
13458 // o.i[1].b2a (bvec2[2][3])
13459 false, false, false, true, false, false,
13460 true, false, true, true, true, false,
13461 };
13462 const std::vector<uint32_t> ssbo140Expect = {
13463 // valid, expected to be true
13464 true, 0, 0, 0,
13465
13466 // i.b (bool), ubo430In.o.i[0].b ? false : true
13467 true, 0,
13468 // i.b2 (bvec2), not(ubo430In.o.i[0].b2)
13469 false, false,
13470 // i.b3 (bvec3), all(ubo430In.o.i[0].b3), any(...b3), any(...b3.yx)
13471 false, true, false, 0,
13472 // i.b4 (bvec4), ubo430In.o.i[0].b4 == (true, false, true, false)
13473 true, true, true, false,
13474 // i.ba (bool[5]), copied from ubo430In.o.i[0].ba
13475 false, 0, 0, 0,
13476 false, 0, 0, 0,
13477 false, 0, 0, 0,
13478 true, 0, 0, 0,
13479 false, 0, 0, 0,
13480 // i.b2a (bool[2][3]), copied from ubo430In.o.i[0].b2a
13481 true, false, 0, 0, true, false, 0, 0, true, true, 0, 0,
13482 false, true, 0, 0, true, true, 0, 0, false, false, 0, 0,
13483 };
13484 const std::vector<uint32_t> ssbo430Expect = {
13485 // valid, expected to be true
13486 true, 0, 0, 0,
13487
13488 // o.i[0].b (bool), copied from (Ubo140::)o.i[0].b
13489 true, 0,
13490 // o.i[0].b2 (bvec2), copied from (Ubo140::)o.i[0].b2
13491 true, false,
13492 // o.i[0].b3 (bvec3), copied from (Ubo140::)o.i[0].b3
13493 true, true, false, 0,
13494 // o.i[0].b4 (bvec4), copied from (Ubo140::)o.i[0].b4
13495 false, true, false, true,
13496 // o.i[0].ba (bool[5]), copied from (Ubo140::)o.i[0].ba
13497 true, false, false, true, true, 0,
13498 // o.i[0].b2a (bool[2][3]), copied from (Ubo140::)o.i[0].b2a
13499 false, true, true, true, true, false,
13500 true, false, false, false, true, true, 0, 0,
13501 };
13502 const std::vector<uint32_t> zeros(std::max(ssbo140Expect.size(), ssbo430Expect.size()), 0);
13503 // clang-format on
13504
13505 GLBuffer uboStd140, uboStd430;
13506 GLBuffer ssboStd140, ssboStd430;
13507
13508 InitBuffer(program, "Ubo140", uboStd140, 0, ubo140Data.data(),
13509 static_cast<uint32_t>(ubo140Data.size()), true);
13510 InitBuffer(program, "Ubo430", uboStd430, 0, ubo430Data.data(),
13511 static_cast<uint32_t>(ubo430Data.size()), false);
13512 InitBuffer(program, "Ssbo140", ssboStd140, 1, zeros.data(),
13513 static_cast<uint32_t>(ssbo140Expect.size()), false);
13514 InitBuffer(program, "Ssbo430", ssboStd430, 2, zeros.data(),
13515 static_cast<uint32_t>(ssbo430Expect.size()), false);
13516 EXPECT_GL_NO_ERROR();
13517
13518 glUseProgram(program);
13519 glDispatchCompute(1, 1, 1);
13520 EXPECT_GL_NO_ERROR();
13521
13522 EXPECT_TRUE(VerifyBuffer(ssboStd140, ssbo140Expect.data(),
13523 static_cast<uint32_t>(ssbo140Expect.size())));
13524 EXPECT_TRUE(VerifyBuffer(ssboStd430, ssbo430Expect.data(),
13525 static_cast<uint32_t>(ssbo430Expect.size())));
13526 }
13527
13528 // Verify that ternary operator works when the operands are matrices used in different block
13529 // storage.
TEST_P(GLSLTest_ES31,TernaryOnMatricesInDifferentBlockStorages)13530 TEST_P(GLSLTest_ES31, TernaryOnMatricesInDifferentBlockStorages)
13531 {
13532 constexpr char kCS[] = R"(#version 310 es
13533 precision highp float;
13534 layout(local_size_x=1) in;
13535
13536 layout(std140, column_major) uniform Ubo140c
13537 {
13538 uint u;
13539 layout(row_major) mat3x2 m;
13540 } ubo140cIn;
13541
13542 layout(std430, row_major, binding = 0) buffer Ubo430r
13543 {
13544 uint u;
13545 layout(column_major) mat3x2 m;
13546 } ubo430rIn;
13547
13548 layout(std140, column_major, binding = 1) buffer Ssbo140c
13549 {
13550 uint u;
13551 mat3x2 m;
13552 } ssbo140cIn;
13553
13554 layout(std430, row_major, binding = 2) buffer Ssbo430r
13555 {
13556 mat3x2 m1;
13557 mat3x2 m2;
13558 } ssbo430rOut;
13559
13560 void main(){
13561 ssbo430rOut.m1 = ubo140cIn.u > ubo430rIn.u ? ubo140cIn.m : ubo430rIn.m;
13562 ssbo430rOut.m2 = ssbo140cIn.u > ubo140cIn.u ? ssbo140cIn.m : ubo140cIn.m;
13563
13564 mat3x2 m = mat3x2(0);
13565
13566 ssbo430rOut.m1 = ubo140cIn.u == 0u ? m : ssbo430rOut.m1;
13567 })";
13568
13569 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
13570 EXPECT_GL_NO_ERROR();
13571
13572 // Test data, laid out with padding (0) based on std140/std430 rules.
13573 // clang-format off
13574 const std::vector<float> ubo140cData = {
13575 // u (uint)
13576 1, 0, 0, 0,
13577
13578 // m (mat3x2, row-major)
13579 5, 7, 9, 0, 6, 8, 10, 0,
13580 };
13581 const std::vector<float> ubo430rData = {
13582 // u (uint)
13583 135, 0,
13584
13585 // m (mat3x2, column-major)
13586 139, 140, 141, 142, 143, 144,
13587 };
13588 const std::vector<float> ssbo140cData = {
13589 // u (uint)
13590 204, 0, 0, 0,
13591
13592 // m (mat3x2, column-major)
13593 205, 206, 0, 0, 207, 208, 0, 0, 209, 210, 0, 0,
13594 };
13595 const std::vector<float> ssbo430rExpect = {
13596 // m1 (mat3x2, row-major), copied from ubo430rIn.m
13597 139, 141, 143, 0, 140, 142, 144, 0,
13598
13599 // m2 (mat3x2, row-major), copied from ssbo140cIn.m
13600 205, 207, 209, 0, 206, 208, 210, 0,
13601 };
13602 const std::vector<float> zeros(ssbo430rExpect.size(), 0);
13603 // clang-format on
13604
13605 GLBuffer uboStd140ColMajor, uboStd430RowMajor;
13606 GLBuffer ssboStd140ColMajor, ssboStd430RowMajor;
13607
13608 InitBuffer(program, "Ubo140c", uboStd140ColMajor, 0, ubo140cData.data(),
13609 static_cast<uint32_t>(ubo140cData.size()), true);
13610 InitBuffer(program, "Ubo430r", uboStd430RowMajor, 0, ubo430rData.data(),
13611 static_cast<uint32_t>(ubo430rData.size()), false);
13612 InitBuffer(program, "Ssbo140c", ssboStd140ColMajor, 1, ssbo140cData.data(),
13613 static_cast<uint32_t>(ssbo140cData.size()), false);
13614 InitBuffer(program, "Ssbo430r", ssboStd430RowMajor, 2, zeros.data(),
13615 static_cast<uint32_t>(ssbo430rExpect.size()), false);
13616 EXPECT_GL_NO_ERROR();
13617
13618 glUseProgram(program);
13619 glDispatchCompute(1, 1, 1);
13620 EXPECT_GL_NO_ERROR();
13621
13622 EXPECT_TRUE(VerifyBuffer(ssboStd430RowMajor, ssbo430rExpect.data(),
13623 static_cast<uint32_t>(ssbo430rExpect.size())));
13624 }
13625
13626 // Verify that ternary operator works when the operands are structs used in different block
13627 // storage.
TEST_P(GLSLTest_ES31,TernaryOnStructsInDifferentBlockStorages)13628 TEST_P(GLSLTest_ES31, TernaryOnStructsInDifferentBlockStorages)
13629 {
13630 constexpr char kCS[] = R"(#version 310 es
13631 precision highp float;
13632 layout(local_size_x=1) in;
13633
13634 struct S
13635 {
13636 mat3x2 m[2];
13637 };
13638
13639 layout(std140, column_major) uniform Ubo140c
13640 {
13641 uint u;
13642 layout(row_major) S s;
13643 } ubo140cIn;
13644
13645 layout(std430, row_major, binding = 0) buffer Ubo430r
13646 {
13647 uint u;
13648 layout(column_major) S s;
13649 } ubo430rIn;
13650
13651 layout(std140, column_major, binding = 1) buffer Ssbo140c
13652 {
13653 uint u;
13654 S s;
13655 } ssbo140cIn;
13656
13657 layout(std430, row_major, binding = 2) buffer Ssbo430r
13658 {
13659 S s1;
13660 S s2;
13661 } ssbo430rOut;
13662
13663 void main(){
13664 ssbo430rOut.s1 = ubo140cIn.u > ubo430rIn.u ? ubo140cIn.s : ubo430rIn.s;
13665 ssbo430rOut.s2 = ssbo140cIn.u > ubo140cIn.u ? ssbo140cIn.s : ubo140cIn.s;
13666
13667 S s;
13668 s.m[0] = mat3x2(0);
13669 s.m[1] = mat3x2(0);
13670
13671 ssbo430rOut.s1 = ubo140cIn.u == 0u ? s : ssbo430rOut.s1;
13672 })";
13673
13674 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
13675 EXPECT_GL_NO_ERROR();
13676
13677 // Test data, laid out with padding (0) based on std140/std430 rules.
13678 // clang-format off
13679 const std::vector<float> ubo140cData = {
13680 // u (uint)
13681 1, 0, 0, 0,
13682
13683 // s.m[0] (mat3x2, row-major)
13684 5, 7, 9, 0, 6, 8, 10, 0,
13685 // s.m[1] (mat3x2, row-major)
13686 25, 27, 29, 0, 26, 28, 30, 0,
13687 };
13688 const std::vector<float> ubo430rData = {
13689 // u (uint)
13690 135, 0,
13691
13692 // s.m[0] (mat3x2, column-major)
13693 139, 140, 141, 142, 143, 144,
13694 // s.m[1] (mat3x2, column-major)
13695 189, 190, 191, 192, 193, 194,
13696 };
13697 const std::vector<float> ssbo140cData = {
13698 // u (uint)
13699 204, 0, 0, 0,
13700
13701 // s.m[0] (mat3x2, column-major)
13702 205, 206, 0, 0, 207, 208, 0, 0, 209, 210, 0, 0,
13703 // s.m[1] (mat3x2, column-major)
13704 245, 246, 0, 0, 247, 248, 0, 0, 249, 250, 0, 0,
13705 };
13706 const std::vector<float> ssbo430rExpect = {
13707 // s1.m[0] (mat3x2, row-major), copied from ubo430rIn.s.m[0]
13708 139, 141, 143, 0, 140, 142, 144, 0,
13709 // s1.m[1] (mat3x2, row-major), copied from ubo430rIn.s.m[0]
13710 189, 191, 193, 0, 190, 192, 194, 0,
13711
13712 // s2.m[0] (mat3x2, row-major), copied from ssbo140cIn.m
13713 205, 207, 209, 0, 206, 208, 210, 0,
13714 // s2.m[1] (mat3x2, row-major), copied from ssbo140cIn.m
13715 245, 247, 249, 0, 246, 248, 250, 0,
13716 };
13717 const std::vector<float> zeros(ssbo430rExpect.size(), 0);
13718 // clang-format on
13719
13720 GLBuffer uboStd140ColMajor, uboStd430RowMajor;
13721 GLBuffer ssboStd140ColMajor, ssboStd430RowMajor;
13722
13723 InitBuffer(program, "Ubo140c", uboStd140ColMajor, 0, ubo140cData.data(),
13724 static_cast<uint32_t>(ubo140cData.size()), true);
13725 InitBuffer(program, "Ubo430r", uboStd430RowMajor, 0, ubo430rData.data(),
13726 static_cast<uint32_t>(ubo430rData.size()), false);
13727 InitBuffer(program, "Ssbo140c", ssboStd140ColMajor, 1, ssbo140cData.data(),
13728 static_cast<uint32_t>(ssbo140cData.size()), false);
13729 InitBuffer(program, "Ssbo430r", ssboStd430RowMajor, 2, zeros.data(),
13730 static_cast<uint32_t>(ssbo430rExpect.size()), false);
13731 EXPECT_GL_NO_ERROR();
13732
13733 glUseProgram(program);
13734 glDispatchCompute(1, 1, 1);
13735 EXPECT_GL_NO_ERROR();
13736
13737 EXPECT_TRUE(VerifyBuffer(ssboStd430RowMajor, ssbo430rExpect.data(),
13738 static_cast<uint32_t>(ssbo430rExpect.size())));
13739 }
13740
13741 // Verify that uint in interface block cast to bool works.
TEST_P(GLSLTest_ES3,UintCastToBoolFromInterfaceBlocks)13742 TEST_P(GLSLTest_ES3, UintCastToBoolFromInterfaceBlocks)
13743 {
13744 constexpr char kFS[] = R"(#version 300 es
13745 precision mediump float;
13746
13747 uniform uvec4 uv4;
13748 uniform uvec2 uv2;
13749 uniform uint u1;
13750 uniform uint u2;
13751
13752 out vec4 colorOut;
13753
13754 void main()
13755 {
13756 bvec4 bv4 = bvec4(uv4);
13757 bvec2 bv2 = bvec2(uv2);
13758 bool b1 = bool(u1);
13759 bool b2 = bool(u2);
13760
13761 vec4 vv4 = mix(vec4(0), vec4(0.4), bv4);
13762 vec2 vv2 = mix(vec2(0), vec2(0.7), bv2);
13763 float v1 = b1 ? 1.0 : 0.0;
13764 float v2 = b2 ? 0.0 : 1.0;
13765
13766 colorOut = vec4(vv4.x - vv4.y + vv4.z + vv4.w,
13767 (vv2.y - vv2.x) * 1.5,
13768 v1,
13769 v2);
13770 })";
13771
13772 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
13773 EXPECT_GL_NO_ERROR();
13774
13775 glUseProgram(program);
13776 GLint uv4 = glGetUniformLocation(program, "uv4");
13777 GLint uv2 = glGetUniformLocation(program, "uv2");
13778 GLint u1 = glGetUniformLocation(program, "u1");
13779 GLint u2 = glGetUniformLocation(program, "u2");
13780 ASSERT_NE(uv4, -1);
13781 ASSERT_NE(uv2, -1);
13782 ASSERT_NE(u1, -1);
13783 ASSERT_NE(u2, -1);
13784
13785 glUniform4ui(uv4, 123, 0, 9, 8297312);
13786 glUniform2ui(uv2, 0, 90812);
13787 glUniform1ui(u1, 8979421);
13788 glUniform1ui(u2, 0);
13789
13790 glClearColor(0, 0, 0, 0);
13791 glClear(GL_COLOR_BUFFER_BIT);
13792
13793 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
13794 EXPECT_GL_NO_ERROR();
13795
13796 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
13797 }
13798
13799 // Test that the precise keyword is not reserved before ES3.1.
TEST_P(GLSLTest_ES3,PreciseNotReserved)13800 TEST_P(GLSLTest_ES3, PreciseNotReserved)
13801 {
13802 // Skip in ES3.1+ as the precise keyword is reserved/core.
13803 ANGLE_SKIP_TEST_IF(getClientMajorVersion() > 3 ||
13804 (getClientMajorVersion() == 3 && getClientMinorVersion() >= 1));
13805
13806 constexpr char kFS[] = R"(#version 300 es
13807 precision mediump float;
13808 in float precise;
13809 out vec4 my_FragColor;
13810 void main() { my_FragColor = vec4(precise, 0, 0, 1.0); })";
13811
13812 constexpr char kVS[] = R"(#version 300 es
13813 in vec4 a_position;
13814 out float precise;
13815 void main() { precise = a_position.x; gl_Position = a_position; })";
13816
13817 GLuint program = CompileProgram(kVS, kFS);
13818 EXPECT_NE(0u, program);
13819 }
13820
13821 // Test that the precise keyword is reserved on ES3.0 without GL_EXT_gpu_shader5.
TEST_P(GLSLTest_ES31,PreciseReservedWithoutExtension)13822 TEST_P(GLSLTest_ES31, PreciseReservedWithoutExtension)
13823 {
13824 // Skip if EXT_gpu_shader5 is enabled.
13825 ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
13826 // Skip in ES3.2+ as the precise keyword is core.
13827 ANGLE_SKIP_TEST_IF(getClientMajorVersion() > 3 ||
13828 (getClientMajorVersion() == 3 && getClientMinorVersion() >= 2));
13829
13830 constexpr char kFS[] = R"(#version 310 es
13831 precision mediump float;
13832 in float v_varying;
13833 out vec4 my_FragColor;
13834 void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); })";
13835
13836 constexpr char kVS[] = R"(#version 310 es
13837 in vec4 a_position;
13838 precise out float v_varying;
13839 void main() { v_varying = a_position.x; gl_Position = a_position; })";
13840
13841 // Should fail, as precise is a reserved keyword when the extension is not enabled.
13842 GLuint program = CompileProgram(kVS, kFS);
13843 EXPECT_EQ(0u, program);
13844 }
13845
13846 // Test that reusing the same variable name for different uses across stages links fine. The SPIR-V
13847 // transformation should ignore all names for non-shader-interface variables and not get confused by
13848 // them.
TEST_P(GLSLTest_ES31,VariableNameReuseAcrossStages)13849 TEST_P(GLSLTest_ES31, VariableNameReuseAcrossStages)
13850 {
13851 constexpr char kVS[] = R"(#version 310 es
13852 precision mediump float;
13853 uniform highp vec4 a;
13854 in highp vec4 b;
13855 in highp vec4 c;
13856 in highp vec4 d;
13857 out highp vec4 e;
13858
13859 vec4 f(vec4 a)
13860 {
13861 return a;
13862 }
13863
13864 vec4 g(vec4 f)
13865 {
13866 return f + f;
13867 }
13868
13869 void main() {
13870 e = f(b) + a;
13871 gl_Position = g(c) + f(d);
13872 }
13873 )";
13874
13875 constexpr char kFS[] = R"(#version 310 es
13876 precision mediump float;
13877 in highp vec4 e;
13878 uniform sampler2D f;
13879 layout(rgba8) uniform highp readonly image2D g;
13880 uniform A
13881 {
13882 vec4 x;
13883 } c;
13884 layout(std140, binding=0) buffer B
13885 {
13886 vec4 x;
13887 } d[2];
13888 out vec4 col;
13889
13890 vec4 h(vec4 c)
13891 {
13892 return texture(f, c.xy) + imageLoad(g, ivec2(c.zw));
13893 }
13894
13895 vec4 i(vec4 x, vec4 y)
13896 {
13897 return vec4(x.xy, y.zw);
13898 }
13899
13900 void main() {
13901 col = h(e) + i(c.x, d[0].x) + d[1].x;
13902 }
13903 )";
13904
13905 GLuint program = CompileProgram(kVS, kFS);
13906 EXPECT_NE(0u, program);
13907 }
13908
13909 // Test that reusing the same uniform variable name for different uses across stages links fine.
TEST_P(GLSLTest_ES31,UniformVariableNameReuseAcrossStages)13910 TEST_P(GLSLTest_ES31, UniformVariableNameReuseAcrossStages)
13911 {
13912 constexpr char kVS[] = R"(#version 310 es
13913 precision mediump float;
13914 in highp vec4 variableWithSameName;
13915
13916 void main() {
13917 gl_Position = variableWithSameName;
13918 }
13919 )";
13920
13921 constexpr char kFS[] = R"(#version 310 es
13922 precision mediump float;
13923 uniform vec4 variableWithSameName;
13924 out vec4 col;
13925
13926 void main() {
13927 col = vec4(variableWithSameName);
13928 }
13929 )";
13930
13931 GLuint program = CompileProgram(kVS, kFS);
13932 EXPECT_NE(0u, program);
13933 }
13934
13935 // Verify that precision match validation of uniforms is performed only if they are statically used
TEST_P(GLSLTest_ES31,UniformPrecisionMatchValidation)13936 TEST_P(GLSLTest_ES31, UniformPrecisionMatchValidation)
13937 {
13938 // Nvidia driver bug: http://anglebug.com/5240
13939 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsWindows() && IsNVIDIA());
13940
13941 constexpr char kVSUnused[] = R"(#version 300 es
13942 precision highp float;
13943 uniform highp vec4 positionIn;
13944
13945 void main()
13946 {
13947 gl_Position = vec4(1, 0, 0, 1);
13948 })";
13949
13950 constexpr char kVSStaticUse[] = R"(#version 300 es
13951 precision highp float;
13952 uniform highp vec4 positionIn;
13953
13954 void main()
13955 {
13956 gl_Position = positionIn;
13957 })";
13958
13959 constexpr char kFSUnused[] = R"(#version 300 es
13960 precision highp float;
13961 uniform highp vec4 positionIn;
13962 out vec4 my_FragColor;
13963
13964 void main()
13965 {
13966 my_FragColor = vec4(1, 0, 0, 1);
13967 })";
13968
13969 constexpr char kFSStaticUse[] = R"(#version 300 es
13970 precision highp float;
13971 uniform mediump vec4 positionIn;
13972 out vec4 my_FragColor;
13973
13974 void main()
13975 {
13976 my_FragColor = vec4(1, 0, 0, positionIn.z);
13977 })";
13978
13979 GLuint program = 0;
13980
13981 program = CompileProgram(kVSUnused, kFSUnused);
13982 EXPECT_NE(0u, program);
13983
13984 program = CompileProgram(kVSUnused, kFSStaticUse);
13985 EXPECT_NE(0u, program);
13986
13987 program = CompileProgram(kVSStaticUse, kFSUnused);
13988 EXPECT_NE(0u, program);
13989
13990 program = CompileProgram(kVSStaticUse, kFSStaticUse);
13991 EXPECT_EQ(0u, program);
13992 }
13993
13994 // Validate that link fails when two instanceless interface blocks with different block names but
13995 // same field names are present.
TEST_P(GLSLTest_ES31,AmbiguousInstancelessInterfaceBlockFields)13996 TEST_P(GLSLTest_ES31, AmbiguousInstancelessInterfaceBlockFields)
13997 {
13998 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
13999
14000 constexpr char kVS[] = R"(#version 310 es
14001 in highp vec4 position;
14002 layout(binding = 0) buffer BlockA { mediump float a; };
14003 void main()
14004 {
14005 a = 0.0;
14006 gl_Position = position;
14007 })";
14008
14009 constexpr char kFS[] = R"(#version 310 es
14010 precision mediump float;
14011 layout(location = 0) out mediump vec4 color;
14012 uniform BlockB { float a; };
14013 void main()
14014 {
14015 color = vec4(a, a, a, 1.0);
14016 })";
14017
14018 GLuint program = CompileProgram(kVS, kFS);
14019 EXPECT_EQ(0u, program);
14020 }
14021
14022 // Verify I/O block array locations
TEST_P(GLSLTest_ES31,IOBlockLocations)14023 TEST_P(GLSLTest_ES31, IOBlockLocations)
14024 {
14025 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14026 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
14027
14028 constexpr char kVS[] = R"(#version 310 es
14029 #extension GL_EXT_shader_io_blocks : require
14030
14031 in highp vec4 position;
14032
14033 layout(location = 0) out vec4 aOut;
14034
14035 layout(location = 6) out VSBlock
14036 {
14037 vec4 b; // location 6
14038 vec4 c; // location 7
14039 layout(location = 1) vec4 d;
14040 vec4 e; // location 2
14041 vec4 f[2]; // locations 3 and 4
14042 } blockOut;
14043
14044 layout(location = 5) out vec4 gOut;
14045
14046 void main()
14047 {
14048 aOut = vec4(0.03, 0.06, 0.09, 0.12);
14049 blockOut.b = vec4(0.15, 0.18, 0.21, 0.24);
14050 blockOut.c = vec4(0.27, 0.30, 0.33, 0.36);
14051 blockOut.d = vec4(0.39, 0.42, 0.45, 0.48);
14052 blockOut.e = vec4(0.51, 0.54, 0.57, 0.6);
14053 blockOut.f[0] = vec4(0.63, 0.66, 0.66, 0.69);
14054 blockOut.f[1] = vec4(0.72, 0.75, 0.78, 0.81);
14055 gOut = vec4(0.84, 0.87, 0.9, 0.93);
14056 gl_Position = position;
14057 })";
14058
14059 constexpr char kGS[] = R"(#version 310 es
14060 #extension GL_EXT_geometry_shader : require
14061 layout (triangles) in;
14062 layout (triangle_strip, max_vertices = 3) out;
14063
14064 // Input varyings
14065 layout(location = 0) in vec4 aIn[];
14066
14067 layout(location = 6) in VSBlock
14068 {
14069 vec4 b;
14070 vec4 c;
14071 layout(location = 1) vec4 d;
14072 vec4 e;
14073 vec4 f[2];
14074 } blockIn[];
14075
14076 layout(location = 5) in vec4 gIn[];
14077
14078 // Output varyings
14079 layout(location = 1) out vec4 aOut;
14080
14081 layout(location = 0) out GSBlock
14082 {
14083 vec4 b; // location 0
14084 layout(location = 3) vec4 c;
14085 layout(location = 7) vec4 d;
14086 layout(location = 5) vec4 e[2];
14087 layout(location = 4) vec4 f;
14088 } blockOut;
14089
14090 layout(location = 2) out vec4 gOut;
14091
14092 void main()
14093 {
14094 int n;
14095 for (n = 0; n < gl_in.length(); n++)
14096 {
14097 gl_Position = gl_in[n].gl_Position;
14098
14099 aOut = aIn[n];
14100 blockOut.b = blockIn[n].b;
14101 blockOut.c = blockIn[n].c;
14102 blockOut.d = blockIn[n].d;
14103 blockOut.e[0] = blockIn[n].e;
14104 blockOut.e[1] = blockIn[n].f[0];
14105 blockOut.f = blockIn[n].f[1];
14106 gOut = gIn[n];
14107
14108 EmitVertex();
14109 }
14110 EndPrimitive();
14111 })";
14112
14113 constexpr char kFS[] = R"(#version 310 es
14114 #extension GL_EXT_shader_io_blocks : require
14115 precision mediump float;
14116
14117 layout(location = 0) out mediump vec4 color;
14118
14119 layout(location = 1) in vec4 aIn;
14120
14121 layout(location = 0) in GSBlock
14122 {
14123 vec4 b;
14124 layout(location = 3) vec4 c;
14125 layout(location = 7) vec4 d;
14126 layout(location = 5) vec4 e[2];
14127 layout(location = 4) vec4 f;
14128 } blockIn;
14129
14130 layout(location = 2) in vec4 gIn;
14131
14132 bool isEq(vec4 a, vec4 b) { return all(lessThan(abs(a-b), vec4(0.001))); }
14133
14134 void main()
14135 {
14136 bool passR = isEq(aIn, vec4(0.03, 0.06, 0.09, 0.12));
14137 bool passG = isEq(blockIn.b, vec4(0.15, 0.18, 0.21, 0.24)) &&
14138 isEq(blockIn.c, vec4(0.27, 0.30, 0.33, 0.36)) &&
14139 isEq(blockIn.d, vec4(0.39, 0.42, 0.45, 0.48)) &&
14140 isEq(blockIn.e[0], vec4(0.51, 0.54, 0.57, 0.6)) &&
14141 isEq(blockIn.e[1], vec4(0.63, 0.66, 0.66, 0.69)) &&
14142 isEq(blockIn.f, vec4(0.72, 0.75, 0.78, 0.81));
14143 bool passB = isEq(gIn, vec4(0.84, 0.87, 0.9, 0.93));
14144
14145 color = vec4(passR, passG, passB, 1.0);
14146 })";
14147
14148 ANGLE_GL_PROGRAM_WITH_GS(program, kVS, kGS, kFS);
14149 EXPECT_GL_NO_ERROR();
14150
14151 GLTexture color;
14152 glBindTexture(GL_TEXTURE_2D, color);
14153 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
14154
14155 GLFramebuffer fbo;
14156 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
14157 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
14158
14159 drawQuad(program, "position", 0);
14160
14161 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
14162 }
14163
14164 // Test using builtins that can only be redefined with gl_PerVertex
TEST_P(GLSLTest_ES31,PerVertexRedefinition)14165 TEST_P(GLSLTest_ES31, PerVertexRedefinition)
14166 {
14167 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
14168 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_clip_cull_distance"));
14169
14170 constexpr char kVS[] = R"(#version 310 es
14171 void main()
14172 {
14173 gl_Position = vec4(1.0, 0.0, 0.0, 1.0);
14174 })";
14175
14176 constexpr char kGS[] = R"(#version 310 es
14177 #extension GL_EXT_geometry_shader : require
14178 #extension GL_EXT_clip_cull_distance : require
14179
14180 layout(lines_adjacency, invocations = 3) in;
14181 layout(points, max_vertices = 16) out;
14182
14183 out gl_PerVertex {
14184 vec4 gl_Position;
14185 float gl_ClipDistance[4];
14186 float gl_CullDistance[4];
14187 };
14188
14189 void main()
14190 {
14191 for (int n = 0; n < 16; ++n)
14192 {
14193 gl_Position = vec4(n, 0.0, 0.0, 1.0);
14194 EmitVertex();
14195 }
14196
14197 EndPrimitive();
14198 })";
14199
14200 constexpr char kFS[] = R"(#version 310 es
14201 precision highp float;
14202
14203 out vec4 result;
14204
14205 void main()
14206 {
14207 result = vec4(1.0);
14208 })";
14209
14210 ANGLE_GL_PROGRAM_WITH_GS(program, kVS, kGS, kFS);
14211 EXPECT_GL_NO_ERROR();
14212 }
14213
14214 // Negative test using builtins that can only be used when redefining gl_PerVertex
TEST_P(GLSLTest_ES31,PerVertexNegativeTest)14215 TEST_P(GLSLTest_ES31, PerVertexNegativeTest)
14216 {
14217 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
14218 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_clip_cull_distance"));
14219
14220 constexpr char kVS[] = R"(#version 310 es
14221 void main()
14222 {
14223 gl_Position = vec4(1.0, 0.0, 0.0, 1.0);
14224 })";
14225
14226 constexpr char kGS[] = R"(#version 310 es
14227 #extension GL_EXT_geometry_shader : require
14228 #extension GL_EXT_clip_cull_distance : require
14229
14230 layout(lines_adjacency, invocations = 3) in;
14231 layout(points, max_vertices = 16) out;
14232
14233 vec4 gl_Position;
14234 float gl_ClipDistance[4];
14235 float gl_CullDistance[4];
14236
14237 void main()
14238 {
14239 for (int n = 0; n < 16; ++n)
14240 {
14241 gl_Position = vec4(n, 0.0, 0.0, 1.0);
14242 EmitVertex();
14243 }
14244
14245 EndPrimitive();
14246 })";
14247
14248 constexpr char kFS[] = R"(#version 310 es
14249 precision highp float;
14250
14251 out vec4 result;
14252
14253 void main()
14254 {
14255 result = vec4(1.0);
14256 })";
14257
14258 GLuint program = CompileProgramWithGS(kVS, kGS, kFS);
14259 EXPECT_EQ(0u, program);
14260 glDeleteProgram(program);
14261 }
14262
14263 // Negative test using builtins that can only be used when redefining gl_PerVertex
14264 // but have the builtins in a differently named struct
TEST_P(GLSLTest_ES31,PerVertexRenamedNegativeTest)14265 TEST_P(GLSLTest_ES31, PerVertexRenamedNegativeTest)
14266 {
14267 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
14268 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_clip_cull_distance"));
14269
14270 constexpr char kVS[] = R"(#version 310 es
14271 void main()
14272 {
14273 gl_Position = vec4(1.0, 0.0, 0.0, 1.0);
14274 })";
14275
14276 constexpr char kGS[] = R"(#version 310 es
14277 #extension GL_EXT_geometry_shader : require
14278 #extension GL_EXT_clip_cull_distance : require
14279
14280 layout(lines_adjacency, invocations = 3) in;
14281 layout(points, max_vertices = 16) out;
14282
14283 out Block {
14284 vec4 gl_Position;
14285 float gl_ClipDistance[4];
14286 float gl_CullDistance[4];
14287 };
14288
14289 void main()
14290 {
14291 for (int n = 0; n < 16; ++n)
14292 {
14293 gl_Position = vec4(n, 0.0, 0.0, 1.0);
14294 EmitVertex();
14295 }
14296
14297 EndPrimitive();
14298 })";
14299
14300 constexpr char kFS[] = R"(#version 310 es
14301 precision highp float;
14302
14303 out vec4 result;
14304
14305 void main()
14306 {
14307 result = vec4(1.0);
14308 })";
14309
14310 GLuint program = CompileProgramWithGS(kVS, kGS, kFS);
14311 EXPECT_EQ(0u, program);
14312 glDeleteProgram(program);
14313 }
14314
14315 // Test varying packing in presence of multiple I/O blocks
TEST_P(GLSLTest_ES31,MultipleIOBlocks)14316 TEST_P(GLSLTest_ES31, MultipleIOBlocks)
14317 {
14318 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14319
14320 constexpr char kVS[] = R"(#version 310 es
14321 #extension GL_EXT_shader_io_blocks : require
14322
14323 in highp vec4 position;
14324
14325 out VSBlock1
14326 {
14327 vec4 a;
14328 vec4 b[2];
14329 } blockOut1;
14330
14331 out VSBlock2
14332 {
14333 vec4 c[2];
14334 vec4 d;
14335 } blockOut2;
14336
14337 void main()
14338 {
14339 blockOut1.a = vec4(0.15, 0.18, 0.21, 0.24);
14340 blockOut1.b[0] = vec4(0.27, 0.30, 0.33, 0.36);
14341 blockOut1.b[1] = vec4(0.39, 0.42, 0.45, 0.48);
14342 blockOut2.c[0] = vec4(0.51, 0.54, 0.57, 0.6);
14343 blockOut2.c[1] = vec4(0.63, 0.66, 0.66, 0.69);
14344 blockOut2.d = vec4(0.72, 0.75, 0.78, 0.81);
14345 gl_Position = position;
14346 })";
14347
14348 constexpr char kFS[] = R"(#version 310 es
14349 #extension GL_EXT_shader_io_blocks : require
14350 precision mediump float;
14351
14352 layout(location = 0) out mediump vec4 color;
14353
14354 in VSBlock1
14355 {
14356 vec4 a;
14357 vec4 b[2];
14358 } blockIn1;
14359
14360 in VSBlock2
14361 {
14362 vec4 c[2];
14363 vec4 d;
14364 } blockIn2;
14365
14366 bool isEq(vec4 a, vec4 b) { return all(lessThan(abs(a-b), vec4(0.001))); }
14367
14368 void main()
14369 {
14370 bool passR = isEq(blockIn1.a, vec4(0.15, 0.18, 0.21, 0.24));
14371 bool passG = isEq(blockIn1.b[0], vec4(0.27, 0.30, 0.33, 0.36)) &&
14372 isEq(blockIn1.b[1], vec4(0.39, 0.42, 0.45, 0.48));
14373 bool passB = isEq(blockIn2.c[0], vec4(0.51, 0.54, 0.57, 0.6)) &&
14374 isEq(blockIn2.c[1], vec4(0.63, 0.66, 0.66, 0.69));
14375 bool passA = isEq(blockIn2.d, vec4(0.72, 0.75, 0.78, 0.81));
14376
14377 color = vec4(passR, passG, passB, passA);
14378 })";
14379
14380 ANGLE_GL_PROGRAM(program, kVS, kFS);
14381 EXPECT_GL_NO_ERROR();
14382
14383 GLTexture color;
14384 glBindTexture(GL_TEXTURE_2D, color);
14385 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
14386
14387 GLFramebuffer fbo;
14388 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
14389 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
14390
14391 drawQuad(program, "position", 0);
14392
14393 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
14394 }
14395
14396 // Test varying packing in presence of I/O block arrays
TEST_P(GLSLTest_ES31,IOBlockArray)14397 TEST_P(GLSLTest_ES31, IOBlockArray)
14398 {
14399 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14400
14401 constexpr char kVS[] = R"(#version 310 es
14402 #extension GL_EXT_shader_io_blocks : require
14403
14404 in highp vec4 position;
14405
14406 out VSBlock1
14407 {
14408 vec4 b[2];
14409 } blockOut1[2];
14410
14411 out VSBlock2
14412 {
14413 vec4 d;
14414 } blockOut2[3];
14415
14416 void main()
14417 {
14418 blockOut1[0].b[0] = vec4(0.15, 0.18, 0.21, 0.24);
14419 blockOut1[0].b[1] = vec4(0.27, 0.30, 0.33, 0.36);
14420 blockOut1[1].b[0] = vec4(0.39, 0.42, 0.45, 0.48);
14421 blockOut1[1].b[1] = vec4(0.51, 0.54, 0.57, 0.6);
14422 blockOut2[0].d = vec4(0.63, 0.66, 0.66, 0.69);
14423 blockOut2[1].d = vec4(0.72, 0.75, 0.78, 0.81);
14424 blockOut2[2].d = vec4(0.84, 0.87, 0.9, 0.93);
14425 gl_Position = position;
14426 })";
14427
14428 constexpr char kFS[] = R"(#version 310 es
14429 #extension GL_EXT_shader_io_blocks : require
14430 precision mediump float;
14431
14432 layout(location = 0) out mediump vec4 color;
14433
14434 in VSBlock1
14435 {
14436 vec4 b[2];
14437 } blockIn1[2];
14438
14439 in VSBlock2
14440 {
14441 vec4 d;
14442 } blockIn2[3];
14443
14444 bool isEq(vec4 a, vec4 b) { return all(lessThan(abs(a-b), vec4(0.001))); }
14445
14446 void main()
14447 {
14448 bool passR = isEq(blockIn1[0].b[0], vec4(0.15, 0.18, 0.21, 0.24)) &&
14449 isEq(blockIn1[0].b[1], vec4(0.27, 0.30, 0.33, 0.36));
14450 bool passG = isEq(blockIn1[1].b[0], vec4(0.39, 0.42, 0.45, 0.48)) &&
14451 isEq(blockIn1[1].b[1], vec4(0.51, 0.54, 0.57, 0.6));
14452 bool passB = isEq(blockIn2[0].d, vec4(0.63, 0.66, 0.66, 0.69));
14453 bool passA = isEq(blockIn2[1].d, vec4(0.72, 0.75, 0.78, 0.81)) &&
14454 isEq(blockIn2[2].d, vec4(0.84, 0.87, 0.9, 0.93));
14455
14456 color = vec4(passR, passG, passB, passA);
14457 })";
14458
14459 ANGLE_GL_PROGRAM(program, kVS, kFS);
14460 EXPECT_GL_NO_ERROR();
14461
14462 GLTexture color;
14463 glBindTexture(GL_TEXTURE_2D, color);
14464 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
14465
14466 GLFramebuffer fbo;
14467 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
14468 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
14469
14470 drawQuad(program, "position", 0);
14471
14472 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
14473 }
14474
14475 // Validate that link fails with I/O block member name mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberNameMismatch)14476 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberNameMismatch)
14477 {
14478 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14479
14480 constexpr char kVS[] = R"(#version 310 es
14481 #extension GL_EXT_shader_io_blocks : require
14482 in highp vec4 position;
14483 out VSBlock { vec4 a; vec4 b[2]; } blockOut1;
14484 void main()
14485 {
14486 blockOut1.a = vec4(0);
14487 blockOut1.b[0] = vec4(0);
14488 blockOut1.b[1] = vec4(0);
14489 gl_Position = position;
14490 })";
14491
14492 constexpr char kFS[] = R"(#version 310 es
14493 #extension GL_EXT_shader_io_blocks : require
14494 precision mediump float;
14495 layout(location = 0) out mediump vec4 color;
14496 in VSBlock { vec4 c; vec4 b[2]; } blockIn1;
14497 void main()
14498 {
14499 color = vec4(blockIn1.c.x, blockIn1.b[0].y, blockIn1.b[1].z, 1.0);
14500 })";
14501
14502 GLuint program = CompileProgram(kVS, kFS);
14503 EXPECT_EQ(0u, program);
14504 }
14505
14506 // Validate that link fails with I/O block member array size mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberArraySizeMismatch)14507 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberArraySizeMismatch)
14508 {
14509 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14510
14511 constexpr char kVS[] = R"(#version 310 es
14512 #extension GL_EXT_shader_io_blocks : require
14513 in highp vec4 position;
14514 out VSBlock { vec4 a; vec4 b[2]; } blockOut1;
14515 void main()
14516 {
14517 blockOut1.a = vec4(0);
14518 blockOut1.b[0] = vec4(0);
14519 blockOut1.b[1] = vec4(0);
14520 gl_Position = position;
14521 })";
14522
14523 constexpr char kFS[] = R"(#version 310 es
14524 #extension GL_EXT_shader_io_blocks : require
14525 precision mediump float;
14526 layout(location = 0) out mediump vec4 color;
14527 in VSBlock { vec4 a; vec4 b[3]; } blockIn1;
14528 void main()
14529 {
14530 color = vec4(blockIn1.a.x, blockIn1.b[0].y, blockIn1.b[1].z, 1.0);
14531 })";
14532
14533 GLuint program = CompileProgram(kVS, kFS);
14534 EXPECT_EQ(0u, program);
14535 }
14536
14537 // Validate that link fails with I/O block member type mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberTypeMismatch)14538 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberTypeMismatch)
14539 {
14540 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14541
14542 constexpr char kVS[] = R"(#version 310 es
14543 #extension GL_EXT_shader_io_blocks : require
14544 in highp vec4 position;
14545 out VSBlock { vec4 a; vec4 b[2]; } blockOut1;
14546 void main()
14547 {
14548 blockOut1.a = vec4(0);
14549 blockOut1.b[0] = vec4(0);
14550 blockOut1.b[1] = vec4(0);
14551 gl_Position = position;
14552 })";
14553
14554 constexpr char kFS[] = R"(#version 310 es
14555 #extension GL_EXT_shader_io_blocks : require
14556 precision mediump float;
14557 layout(location = 0) out mediump vec4 color;
14558 in VSBlock { vec3 a; vec4 b[2]; } blockIn1;
14559 void main()
14560 {
14561 color = vec4(blockIn1.a.x, blockIn1.b[0].y, blockIn1.b[1].z, 1.0);
14562 })";
14563
14564 GLuint program = CompileProgram(kVS, kFS);
14565 EXPECT_EQ(0u, program);
14566 }
14567
14568 // Validate that link fails with I/O block location mismatches
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkLocationMismatch)14569 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkLocationMismatch)
14570 {
14571 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14572
14573 constexpr char kVS[] = R"(#version 310 es
14574 #extension GL_EXT_shader_io_blocks : require
14575 in highp vec4 position;
14576 layout(location = 2) out VSBlock { vec4 a; vec4 b[2]; } blockOut1;
14577 void main()
14578 {
14579 blockOut1.a = vec4(0);
14580 blockOut1.b[0] = vec4(0);
14581 blockOut1.b[1] = vec4(0);
14582 gl_Position = position;
14583 })";
14584
14585 constexpr char kFS[] = R"(#version 310 es
14586 #extension GL_EXT_shader_io_blocks : require
14587 precision mediump float;
14588 layout(location = 0) out mediump vec4 color;
14589 layout(location = 1) in VSBlock { vec4 a; vec4 b[2]; } blockIn1;
14590 void main()
14591 {
14592 color = vec4(blockIn1.a.x, blockIn1.b[0].y, blockIn1.b[1].z, 1.0);
14593 })";
14594
14595 GLuint program = CompileProgram(kVS, kFS);
14596 EXPECT_EQ(0u, program);
14597 }
14598
14599 // Validate that link fails with I/O block member location mismatches
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberLocationMismatch)14600 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberLocationMismatch)
14601 {
14602 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14603
14604 constexpr char kVS[] = R"(#version 310 es
14605 #extension GL_EXT_shader_io_blocks : require
14606 in highp vec4 position;
14607 out VSBlock { vec4 a; layout(location = 2) vec4 b[2]; } blockOut1;
14608 void main()
14609 {
14610 blockOut1.a = vec4(0);
14611 blockOut1.b[0] = vec4(0);
14612 blockOut1.b[1] = vec4(0);
14613 gl_Position = position;
14614 })";
14615
14616 constexpr char kFS[] = R"(#version 310 es
14617 #extension GL_EXT_shader_io_blocks : require
14618 precision mediump float;
14619 layout(location = 0) out mediump vec4 color;
14620 in VSBlock { vec4 a; layout(location = 3) vec4 b[2]; } blockIn1;
14621 void main()
14622 {
14623 color = vec4(blockIn1.a.x, blockIn1.b[0].y, blockIn1.b[1].z, 1.0);
14624 })";
14625
14626 GLuint program = CompileProgram(kVS, kFS);
14627 EXPECT_EQ(0u, program);
14628 }
14629
14630 // Validate that link fails with I/O block member struct name mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberStructNameMismatch)14631 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberStructNameMismatch)
14632 {
14633 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14634
14635 constexpr char kVS[] = R"(#version 310 es
14636 #extension GL_EXT_shader_io_blocks : require
14637 in highp vec4 position;
14638 struct S1 { vec4 a; vec4 b[2]; };
14639 out VSBlock { S1 s; } blockOut1;
14640 void main()
14641 {
14642 blockOut1.s.a = vec4(0);
14643 blockOut1.s.b[0] = vec4(0);
14644 blockOut1.s.b[1] = vec4(0);
14645 gl_Position = position;
14646 })";
14647
14648 constexpr char kFS[] = R"(#version 310 es
14649 #extension GL_EXT_shader_io_blocks : require
14650 precision mediump float;
14651 layout(location = 0) out mediump vec4 color;
14652 struct S2 { vec4 a; vec4 b[2]; };
14653 in VSBlock { S2 s; } blockIn1;
14654 void main()
14655 {
14656 color = vec4(blockIn1.s.a.x, blockIn1.s.b[0].y, blockIn1.s.b[1].z, 1.0);
14657 })";
14658
14659 GLuint program = CompileProgram(kVS, kFS);
14660 EXPECT_EQ(0u, program);
14661 }
14662
14663 // Validate that link fails with I/O block member struct member name mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberStructMemberNameMismatch)14664 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberStructMemberNameMismatch)
14665 {
14666 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14667
14668 constexpr char kVS[] = R"(#version 310 es
14669 #extension GL_EXT_shader_io_blocks : require
14670 in highp vec4 position;
14671 struct S { vec4 c; vec4 b[2]; };
14672 out VSBlock { S s; } blockOut1;
14673 void main()
14674 {
14675 blockOut1.s.c = vec4(0);
14676 blockOut1.s.b[0] = vec4(0);
14677 blockOut1.s.b[1] = vec4(0);
14678 gl_Position = position;
14679 })";
14680
14681 constexpr char kFS[] = R"(#version 310 es
14682 #extension GL_EXT_shader_io_blocks : require
14683 precision mediump float;
14684 layout(location = 0) out mediump vec4 color;
14685 struct S { vec4 a; vec4 b[2]; };
14686 in VSBlock { S s; } blockIn1;
14687 void main()
14688 {
14689 color = vec4(blockIn1.s.a.x, blockIn1.s.b[0].y, blockIn1.s.b[1].z, 1.0);
14690 })";
14691
14692 GLuint program = CompileProgram(kVS, kFS);
14693 EXPECT_EQ(0u, program);
14694 }
14695
14696 // Validate that link fails with I/O block member struct member type mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberStructMemberTypeMismatch)14697 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberStructMemberTypeMismatch)
14698 {
14699 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14700
14701 constexpr char kVS[] = R"(#version 310 es
14702 #extension GL_EXT_shader_io_blocks : require
14703 in highp vec4 position;
14704 struct S { vec4 a; vec4 b[2]; };
14705 out VSBlock { S s; } blockOut1;
14706 void main()
14707 {
14708 blockOut1.s.a = vec4(0);
14709 blockOut1.s.b[0] = vec4(0);
14710 blockOut1.s.b[1] = vec4(0);
14711 gl_Position = position;
14712 })";
14713
14714 constexpr char kFS[] = R"(#version 310 es
14715 #extension GL_EXT_shader_io_blocks : require
14716 precision mediump float;
14717 layout(location = 0) out mediump vec4 color;
14718 struct S { vec3 a; vec4 b[2]; };
14719 in VSBlock { S s; } blockIn1;
14720 void main()
14721 {
14722 color = vec4(blockIn1.s.a.x, blockIn1.s.b[0].y, blockIn1.s.b[1].z, 1.0);
14723 })";
14724
14725 GLuint program = CompileProgram(kVS, kFS);
14726 EXPECT_EQ(0u, program);
14727 }
14728
14729 // Validate that link fails with I/O block member struct member array size mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberStructMemberArraySizeMismatch)14730 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberStructMemberArraySizeMismatch)
14731 {
14732 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14733
14734 constexpr char kVS[] = R"(#version 310 es
14735 #extension GL_EXT_shader_io_blocks : require
14736 in highp vec4 position;
14737 struct S { vec4 a; vec4 b[3]; };
14738 out VSBlock { S s; } blockOut1;
14739 void main()
14740 {
14741 blockOut1.s.a = vec4(0);
14742 blockOut1.s.b[0] = vec4(0);
14743 blockOut1.s.b[1] = vec4(0);
14744 gl_Position = position;
14745 })";
14746
14747 constexpr char kFS[] = R"(#version 310 es
14748 #extension GL_EXT_shader_io_blocks : require
14749 precision mediump float;
14750 layout(location = 0) out mediump vec4 color;
14751 struct S { vec4 a; vec4 b[2]; };
14752 in VSBlock { S s; } blockIn1;
14753 void main()
14754 {
14755 color = vec4(blockIn1.s.a.x, blockIn1.s.b[0].y, blockIn1.s.b[1].z, 1.0);
14756 })";
14757
14758 GLuint program = CompileProgram(kVS, kFS);
14759 EXPECT_EQ(0u, program);
14760 }
14761
14762 // Validate that link fails with I/O block member struct member count mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberStructMemberCountMismatch)14763 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberStructMemberCountMismatch)
14764 {
14765 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14766
14767 constexpr char kVS[] = R"(#version 310 es
14768 #extension GL_EXT_shader_io_blocks : require
14769 in highp vec4 position;
14770 struct S { vec4 a; vec4 b[2]; vec4 c; };
14771 out VSBlock { S s; } blockOut1;
14772 void main()
14773 {
14774 blockOut1.s.c = vec4(0);
14775 blockOut1.s.b[0] = vec4(0);
14776 blockOut1.s.b[1] = vec4(0);
14777 gl_Position = position;
14778 })";
14779
14780 constexpr char kFS[] = R"(#version 310 es
14781 #extension GL_EXT_shader_io_blocks : require
14782 precision mediump float;
14783 layout(location = 0) out mediump vec4 color;
14784 struct S { vec4 a; vec4 b[2]; };
14785 in VSBlock { S s; } blockIn1;
14786 void main()
14787 {
14788 color = vec4(blockIn1.s.a.x, blockIn1.s.b[0].y, blockIn1.s.b[1].z, 1.0);
14789 })";
14790
14791 GLuint program = CompileProgram(kVS, kFS);
14792 EXPECT_EQ(0u, program);
14793 }
14794
14795 // Validate that link fails with I/O block member nested struct mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberNestedStructMismatch)14796 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberNestedStructMismatch)
14797 {
14798 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14799
14800 constexpr char kVS[] = R"(#version 310 es
14801 #extension GL_EXT_shader_io_blocks : require
14802 in highp vec4 position;
14803 struct S1 { vec4 c; vec4 b[2]; };
14804 struct S2 { S1 s; };
14805 struct S3 { S2 s; };
14806 out VSBlock { S3 s; } blockOut1;
14807 void main()
14808 {
14809 blockOut1.s.s.s.c = vec4(0);
14810 blockOut1.s.s.s.b[0] = vec4(0);
14811 blockOut1.s.s.s.b[1] = vec4(0);
14812 gl_Position = position;
14813 })";
14814
14815 constexpr char kFS[] = R"(#version 310 es
14816 #extension GL_EXT_shader_io_blocks : require
14817 precision mediump float;
14818 layout(location = 0) out mediump vec4 color;
14819 struct S1 { vec4 a; vec4 b[2]; };
14820 struct S2 { S1 s; };
14821 struct S3 { S2 s; };
14822 in VSBlock { S3 s; } blockIn1;
14823 void main()
14824 {
14825 color = vec4(blockIn1.s.s.s.a.x, blockIn1.s.s.s.b[0].y, blockIn1.s.s.s.b[1].z, 1.0);
14826 })";
14827
14828 GLuint program = CompileProgram(kVS, kFS);
14829 EXPECT_EQ(0u, program);
14830 }
14831
14832 // Test that separating declarators works with structs that have been separately defined.
TEST_P(GLSLTest_ES31,SeparateDeclaratorsOfStructType)14833 TEST_P(GLSLTest_ES31, SeparateDeclaratorsOfStructType)
14834 {
14835 constexpr char kVS[] = R"(#version 310 es
14836 precision highp float;
14837
14838 struct S
14839 {
14840 mat4 a;
14841 mat4 b;
14842 };
14843
14844 S s1 = S(mat4(1), mat4(2)), s2[2][3], s3[2] = S[2](S(mat4(0), mat4(3)), S(mat4(4), mat4(5)));
14845
14846 void main() {
14847 S s4[2][3] = s2, s5 = s3[0], s6[2] = S[2](s1, s5), s7 = s5;
14848
14849 gl_Position = vec4(s3[1].a[0].x, s2[0][2].b[1].y, s4[1][0].a[2].z, s6[0].b[3].w);
14850 })";
14851
14852 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
14853
14854 const char *sourceArray[1] = {kVS};
14855 GLint lengths[1] = {static_cast<GLint>(sizeof(kVS) - 1)};
14856 glShaderSource(shader, 1, sourceArray, lengths);
14857 glCompileShader(shader);
14858
14859 GLint compileResult;
14860 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
14861 EXPECT_NE(compileResult, 0);
14862 }
14863
14864 // Test that separating declarators works with structs that are simultaneously defined.
TEST_P(GLSLTest_ES31,SeparateDeclaratorsOfStructTypeBeingSpecified)14865 TEST_P(GLSLTest_ES31, SeparateDeclaratorsOfStructTypeBeingSpecified)
14866 {
14867 constexpr char kVS[] = R"(#version 310 es
14868 precision highp float;
14869
14870 struct S
14871 {
14872 mat4 a;
14873 mat4 b;
14874 } s1 = S(mat4(1), mat4(2)), s2[2][3], s3[2] = S[2](S(mat4(0), mat4(3)), S(mat4(4), mat4(5)));
14875
14876 void main() {
14877 struct T
14878 {
14879 mat4 a;
14880 mat4 b;
14881 } s4[2][3], s5 = T(s3[0].a, s3[0].b), s6[2] = T[2](T(s1.a, s1.b), s5), s7 = s5;
14882
14883 float f1 = s3[1].a[0].x, f2 = s2[0][2].b[1].y;
14884
14885 gl_Position = vec4(f1, f2, s4[1][0].a[2].z, s6[0].b[3].w);
14886 })";
14887
14888 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
14889
14890 const char *sourceArray[1] = {kVS};
14891 GLint lengths[1] = {static_cast<GLint>(sizeof(kVS) - 1)};
14892 glShaderSource(shader, 1, sourceArray, lengths);
14893 glCompileShader(shader);
14894
14895 GLint compileResult;
14896 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
14897 EXPECT_NE(compileResult, 0);
14898 }
14899
14900 // Test that separating declarators works with structs that are simultaneously defined and that are
14901 // nameless.
TEST_P(GLSLTest_ES31,SeparateDeclaratorsOfNamelessStructType)14902 TEST_P(GLSLTest_ES31, SeparateDeclaratorsOfNamelessStructType)
14903 {
14904 constexpr char kVS[] = R"(#version 310 es
14905 precision highp float;
14906
14907 struct
14908 {
14909 mat4 a;
14910 mat4 b;
14911 } s1, s2[2][3], s3[2];
14912
14913 void main() {
14914 struct
14915 {
14916 mat4 a;
14917 mat4 b;
14918 } s4[2][3], s5, s6[2], s7 = s5;
14919
14920 float f1 = s1.a[0].x + s3[1].a[0].x, f2 = s2[0][2].b[1].y + s7.b[1].z;
14921
14922 gl_Position = vec4(f1, f2, s4[1][0].a[2].z, s6[0].b[3].w);
14923 })";
14924
14925 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
14926
14927 const char *sourceArray[1] = {kVS};
14928 GLint lengths[1] = {static_cast<GLint>(sizeof(kVS) - 1)};
14929 glShaderSource(shader, 1, sourceArray, lengths);
14930 glCompileShader(shader);
14931
14932 GLint compileResult;
14933 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
14934 EXPECT_NE(compileResult, 0);
14935 }
14936
14937 // Regression test for transformation bug which separates struct declarations from uniform
14938 // declarations. The bug was that the uniform variable usage in the initializer of a new
14939 // declaration (y below) was not being processed.
TEST_P(GLSLTest,UniformStructBug)14940 TEST_P(GLSLTest, UniformStructBug)
14941 {
14942 constexpr char kVS[] = R"(precision highp float;
14943
14944 uniform struct Global
14945 {
14946 float x;
14947 } u_global;
14948
14949 void main() {
14950 float y = u_global.x;
14951
14952 gl_Position = vec4(y);
14953 })";
14954
14955 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
14956
14957 const char *sourceArray[1] = {kVS};
14958 GLint lengths[1] = {static_cast<GLint>(sizeof(kVS) - 1)};
14959 glShaderSource(shader, 1, sourceArray, lengths);
14960 glCompileShader(shader);
14961
14962 GLint compileResult;
14963 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
14964 EXPECT_NE(compileResult, 0);
14965 }
14966
14967 // Regression test for transformation bug which separates struct declarations from uniform
14968 // declarations. The bug was that the arrayness of the declaration was not being applied to the
14969 // replaced uniform variable.
TEST_P(GLSLTest_ES31,UniformStructBug2)14970 TEST_P(GLSLTest_ES31, UniformStructBug2)
14971 {
14972 constexpr char kVS[] = R"(#version 310 es
14973 precision highp float;
14974
14975 uniform struct Global
14976 {
14977 float x;
14978 } u_global[2][3];
14979
14980 void main() {
14981 float y = u_global[0][0].x;
14982
14983 gl_Position = vec4(y);
14984 })";
14985
14986 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
14987
14988 const char *sourceArray[1] = {kVS};
14989 GLint lengths[1] = {static_cast<GLint>(sizeof(kVS) - 1)};
14990 glShaderSource(shader, 1, sourceArray, lengths);
14991 glCompileShader(shader);
14992
14993 GLint compileResult;
14994 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
14995 EXPECT_NE(compileResult, 0);
14996 }
14997
14998 // Regression test based on fuzzer issue resulting in an AST validation failure. Struct definition
14999 // was not found in the tree. Tests that struct declaration in function return value is visible to
15000 // instantiations later on.
TEST_P(GLSLTest,MissingStructDeclarationBug)15001 TEST_P(GLSLTest, MissingStructDeclarationBug)
15002 {
15003 constexpr char kVS[] = R"(
15004 struct S
15005 {
15006 vec4 i;
15007 } p();
15008 void main()
15009 {
15010 S s;
15011 })";
15012
15013 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
15014 EXPECT_NE(0u, shader);
15015 glDeleteShader(shader);
15016 }
15017
15018 // Regression test based on fuzzer issue resulting in an AST validation failure. Struct definition
15019 // was not found in the tree. Tests that struct declaration in function return value is visible to
15020 // other struct declarations.
TEST_P(GLSLTest,MissingStructDeclarationBug2)15021 TEST_P(GLSLTest, MissingStructDeclarationBug2)
15022 {
15023 constexpr char kVS[] = R"(
15024 struct T
15025 {
15026 vec4 I;
15027 } p();
15028 struct
15029 {
15030 T c;
15031 };
15032 void main()
15033 {
15034 })";
15035
15036 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
15037 EXPECT_NE(0u, shader);
15038 glDeleteShader(shader);
15039 }
15040
15041 // Regression test for bug in HLSL code generation where the for loop init expression was expected
15042 // to always have an initializer.
TEST_P(GLSLTest,HandleExcessiveLoopBug)15043 TEST_P(GLSLTest, HandleExcessiveLoopBug)
15044 {
15045 constexpr char kVS[] = R"(void main(){for(int i;i>6;);})";
15046
15047 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
15048 EXPECT_NE(0u, shader);
15049 glDeleteShader(shader);
15050 }
15051
15052 // Regression test for a validation bug in the translator where func(void, int) was accepted even
15053 // though it's illegal, and the function was callable as if the void parameter isn't there.
TEST_P(GLSLTest,NoParameterAfterVoid)15054 TEST_P(GLSLTest, NoParameterAfterVoid)
15055 {
15056 constexpr char kVS[] = R"(void f(void, int a){}
15057 void main(){f(1);})";
15058
15059 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
15060 EXPECT_EQ(0u, shader);
15061 glDeleteShader(shader);
15062 }
15063
15064 // Similar to NoParameterAfterVoid, but tests func(void, void).
TEST_P(GLSLTest,NoParameterAfterVoid2)15065 TEST_P(GLSLTest, NoParameterAfterVoid2)
15066 {
15067 constexpr char kVS[] = R"(void f(void, void){}
15068 void main(){f();})";
15069
15070 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
15071 EXPECT_EQ(0u, shader);
15072 glDeleteShader(shader);
15073 }
15074
15075 // Test that providing more components to a matrix constructor than necessary works. Based on a
15076 // clusterfuzz test that caught an OOB array write in glslang.
TEST_P(GLSLTest,MatrixConstructor)15077 TEST_P(GLSLTest, MatrixConstructor)
15078 {
15079 constexpr char kVS[] = R"(attribute vec4 aPosition;
15080 varying vec4 vColor;
15081 void main()
15082 {
15083 gl_Position = aPosition;
15084 vec4 color = vec4(aPosition.xy, 0, 1);
15085 mat4 m4 = mat4(color, color.yzwx, color.zwx, color.zwxy, color.wxyz);
15086 vColor = m4[0];
15087 })";
15088
15089 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
15090 EXPECT_NE(0u, shader);
15091 glDeleteShader(shader);
15092 }
15093
15094 // Test constructors without precision
TEST_P(GLSLTest,ConstructFromBoolVector)15095 TEST_P(GLSLTest, ConstructFromBoolVector)
15096 {
15097 constexpr char kFS[] = R"(precision mediump float;
15098 uniform float u;
15099 void main()
15100 {
15101 mat4 m = mat4(u);
15102 mat2(0, bvec3(m));
15103 gl_FragColor = vec4(m);
15104 })";
15105
15106 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
15107 EXPECT_NE(0u, shader);
15108 glDeleteShader(shader);
15109 }
15110
15111 // Test constructing vector from matrix
TEST_P(GLSLTest,VectorConstructorFromMatrix)15112 TEST_P(GLSLTest, VectorConstructorFromMatrix)
15113 {
15114 constexpr char kFS[] = R"(precision mediump float;
15115 uniform mat2 umat2;
15116 void main()
15117 {
15118 gl_FragColor = vec4(umat2);
15119 })";
15120
15121 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
15122 EXPECT_NE(0u, shader);
15123 glDeleteShader(shader);
15124 }
15125
15126 // Test constructing matrix from vectors
TEST_P(GLSLTest,MatrixConstructorFromVectors)15127 TEST_P(GLSLTest, MatrixConstructorFromVectors)
15128 {
15129 constexpr char kFS[] = R"(precision mediump float;
15130 uniform vec2 uvec2;
15131 void main()
15132 {
15133 mat2 m = mat2(uvec2, uvec2.yx);
15134 gl_FragColor = vec4(m * uvec2, uvec2);
15135 })";
15136
15137 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
15138 glUseProgram(program);
15139
15140 GLint uloc = glGetUniformLocation(program, "uvec2");
15141 ASSERT_NE(uloc, -1);
15142 glUniform2f(uloc, 0.5, 0.8);
15143
15144 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
15145 EXPECT_GL_NO_ERROR();
15146
15147 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(227, 204, 127, 204), 1);
15148 }
15149
15150 // Test that constructing vector and matrix inside multiple declarations preserves the correct order
15151 // of operations.
TEST_P(GLSLTest,ConstructorinSequenceOperator)15152 TEST_P(GLSLTest, ConstructorinSequenceOperator)
15153 {
15154 constexpr char kFS[] = R"(precision mediump float;
15155 uniform vec2 u;
15156 void main()
15157 {
15158 vec2 v = u;
15159 mat2 m = (v[0] += 1.0, mat2(v, v[1], -v[0]));
15160 gl_FragColor = vec4(m[0], m[1]);
15161 })";
15162
15163 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
15164 glUseProgram(program);
15165
15166 GLint uloc = glGetUniformLocation(program, "u");
15167 ASSERT_NE(uloc, -1);
15168 glUniform2f(uloc, -0.5, 1.0);
15169
15170 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
15171 EXPECT_GL_NO_ERROR();
15172
15173 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(127, 255, 255, 0), 1);
15174 }
15175
15176 // Test that constructing vectors inside multiple declarations preserves the correct order
15177 // of operations.
TEST_P(GLSLTest,VectorConstructorsInMultiDeclaration)15178 TEST_P(GLSLTest, VectorConstructorsInMultiDeclaration)
15179 {
15180 constexpr char kFS[] = R"(precision mediump float;
15181 uniform vec2 u;
15182 void main()
15183 {
15184 vec2 v = vec2(u[0]),
15185 w = mat2(v, v) * u;
15186 gl_FragColor = vec4(v, w);
15187 })";
15188
15189 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
15190 glUseProgram(program);
15191
15192 GLint uloc = glGetUniformLocation(program, "u");
15193 ASSERT_NE(uloc, -1);
15194 glUniform2f(uloc, 0.5, 0.8);
15195
15196 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
15197 EXPECT_GL_NO_ERROR();
15198
15199 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(127, 127, 166, 166), 1);
15200 }
15201
15202 // Test complex constructor usage.
TEST_P(GLSLTest_ES3,ComplexConstructor)15203 TEST_P(GLSLTest_ES3, ComplexConstructor)
15204 {
15205 constexpr char kFS[] = R"(#version 300 es
15206 precision mediump float;
15207 uniform vec2 u; // = vec2(0.5, 0.8)
15208 uniform vec2 v; // = vec2(-0.2, 1.0)
15209
15210 out vec4 color;
15211
15212 bool f(mat2 m)
15213 {
15214 return m[0][0] > 0.;
15215 }
15216
15217 bool isEqual(float a, float b)
15218 {
15219 return abs(a - b) < 0.01;
15220 }
15221
15222 void main()
15223 {
15224 int shouldRemainZero = 0;
15225
15226 // Test side effects inside constructor args after short-circuit
15227 if (u.x < 0. && f(mat2(shouldRemainZero += 1, u, v)))
15228 {
15229 shouldRemainZero += 2;
15230 }
15231
15232 int shouldBecomeFive = 0;
15233
15234 // Test directly nested constructors
15235 mat4x3 m = mat4x3(mat2(shouldBecomeFive += 5, v, u));
15236
15237 // Test indirectly nested constructors
15238 mat2 m2 = mat2(f(mat2(u, v)), f(mat2(v, u)), f(mat2(f(mat2(1.)))), -1.);
15239
15240 // Verify
15241 bool sideEffectsOk = shouldRemainZero == 0 && shouldBecomeFive == 5;
15242
15243 bool mOk = isEqual(m[0][0], 5.) && isEqual(m[0][1], -0.2) && isEqual(m[0][2], 0.) &&
15244 isEqual(m[1][0], 1.) && isEqual(m[1][1], 0.5) && isEqual(m[1][2], 0.) &&
15245 isEqual(m[2][0], 0.) && isEqual(m[2][1], 0.) && isEqual(m[2][2], 1.) &&
15246 isEqual(m[3][0], 0.) && isEqual(m[3][1], 0.) && isEqual(m[3][2], 0.);
15247
15248 bool m2Ok = isEqual(m2[0][0], 1.) && isEqual(m2[0][1], 0.) &&
15249 isEqual(m2[1][0], 1.) && isEqual(m2[1][1], -1.);
15250
15251 color = vec4(sideEffectsOk ? 1 : 0, mOk ? 1 : 0, m2Ok ? 1 : 0, 1);
15252 })";
15253
15254 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
15255 glUseProgram(program);
15256
15257 GLint uloc = glGetUniformLocation(program, "u");
15258 GLint vloc = glGetUniformLocation(program, "v");
15259 ASSERT_NE(uloc, -1);
15260 ASSERT_NE(vloc, -1);
15261 glUniform2f(uloc, 0.5, 0.8);
15262 glUniform2f(vloc, -0.2, 1.0);
15263
15264 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
15265 EXPECT_GL_NO_ERROR();
15266
15267 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
15268 }
15269
15270 // Test that scalar(nonScalar) constructors work.
TEST_P(GLSLTest_ES3,ScalarConstructor)15271 TEST_P(GLSLTest_ES3, ScalarConstructor)
15272 {
15273 constexpr char kFS[] = R"(#version 300 es
15274 precision mediump float;
15275 uniform vec4 u;
15276 out vec4 color;
15277 void main()
15278 {
15279 float f1 = float(u);
15280 mat3 m = mat3(u, u, u);
15281 int i = int(m);
15282 color = vec4(f1, float(i), 0, 1);
15283 })";
15284
15285 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
15286 glUseProgram(program);
15287
15288 GLint uloc = glGetUniformLocation(program, "u");
15289 ASSERT_NE(uloc, -1);
15290 glUniform4f(uloc, 1.0, 0.4, 0.2, 0.7);
15291
15292 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
15293 EXPECT_GL_NO_ERROR();
15294
15295 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
15296 }
15297
15298 // Test that initializing global variables with non-constant values work
TEST_P(GLSLTest_ES3,InitGlobalNonConstant)15299 TEST_P(GLSLTest_ES3, InitGlobalNonConstant)
15300 {
15301 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_non_constant_global_initializers"));
15302
15303 constexpr char kVS[] = R"(#version 300 es
15304 #extension GL_EXT_shader_non_constant_global_initializers : require
15305 uniform vec4 u;
15306 out vec4 color;
15307
15308 vec4 global1 = u;
15309 vec4 global2 = u + vec4(1);
15310 vec4 global3 = global1 * global2;
15311 void main()
15312 {
15313 color = global3;
15314 })";
15315
15316 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
15317 EXPECT_NE(0u, shader);
15318 glDeleteShader(shader);
15319 }
15320
15321 // Test that initializing global variables with complex constants work
TEST_P(GLSLTest_ES3,InitGlobalComplexConstant)15322 TEST_P(GLSLTest_ES3, InitGlobalComplexConstant)
15323 {
15324 constexpr char kFS[] = R"(#version 300 es
15325 precision highp float;
15326 out vec4 color;
15327
15328 struct T
15329 {
15330 float f;
15331 };
15332
15333 struct S
15334 {
15335 vec4 v;
15336 mat3x4 m[2];
15337 T t;
15338 };
15339
15340 S s = S(
15341 vec4(0, 1, 2, 3),
15342 mat3x4[2](
15343 mat3x4(
15344 vec4(4, 5, 6, 7),
15345 vec4(8, 9, 10, 11),
15346 vec4(12, 13, 14, 15)
15347 ),
15348 mat3x4(
15349 vec4(16, 17, 18, 19),
15350 vec4(20, 21, 22, 23),
15351 vec4(24, 25, 26, 27)
15352 )
15353 ),
15354 T(28.0)
15355 );
15356
15357 void main()
15358 {
15359 vec4 result = vec4(0, 1, 0, 1);
15360
15361 if (s.v != vec4(0, 1, 2, 3))
15362 result = vec4(1, 0, 0, 0);
15363
15364 for (int index = 0; index < 2; ++index)
15365 {
15366 for (int column = 0; column < 3; ++column)
15367 {
15368 int expect = index * 12 + column * 4 + 4;
15369 if (s.m[index][column] != vec4(expect, expect + 1, expect + 2, expect + 3))
15370 result = vec4(float(index + 1) / 2.0, 0, float(column + 1) / 3.0, 1);
15371 }
15372 }
15373
15374 if (s.t.f != 28.0)
15375 result = vec4(0, 0, 1, 0);
15376
15377 color = result;
15378 })";
15379
15380 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
15381
15382 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
15383 EXPECT_GL_NO_ERROR();
15384
15385 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
15386 }
15387
15388 // Test that built-ins with out parameters work
TEST_P(GLSLTest_ES31,BuiltInsWithOutParameters)15389 TEST_P(GLSLTest_ES31, BuiltInsWithOutParameters)
15390 {
15391 constexpr char kFS[] = R"(#version 310 es
15392 precision highp float;
15393 precision highp int;
15394
15395 out vec4 color;
15396
15397 uniform float f; // = 3.41
15398 uniform uvec4 u1; // = 0xFEDCBA98, 0x13579BDF, 0xFEDCBA98, 0x13579BDF
15399 uniform uvec4 u2; // = 0xECA86420, 0x12345678, 0x12345678, 0xECA86420
15400
15401 struct S
15402 {
15403 float fvalue;
15404 int ivalues[2];
15405 uvec4 uvalues[3];
15406 };
15407
15408 struct T
15409 {
15410 S s[2];
15411 };
15412
15413 void main()
15414 {
15415 float integer;
15416 float fraction = modf(f, integer);
15417
15418 T t;
15419
15420 t.s[0].fvalue = frexp(f, t.s[0].ivalues[0]);
15421 float significand = t.s[0].fvalue;
15422 int exponent = t.s[0].ivalues[0];
15423
15424 t.s[0].uvalues[0] = uaddCarry(u1, u2, t.s[0].uvalues[1].yxwz);
15425 uvec4 addResult = t.s[0].uvalues[0];
15426 uvec4 addCarry = t.s[0].uvalues[1].yxwz;
15427
15428 t.s[0].uvalues[2].wx = usubBorrow(u1.wx, u2.wx, t.s[1].uvalues[0].wx);
15429 uvec2 subResult = t.s[0].uvalues[2].wx;
15430 uvec2 subBorrow = t.s[1].uvalues[0].wx;
15431
15432 umulExtended(u1, u2, t.s[1].uvalues[1], t.s[1].uvalues[2]);
15433 uvec4 mulMsb = t.s[1].uvalues[1];
15434 uvec4 mulLsb = t.s[1].uvalues[2];
15435
15436 ivec2 imulMsb, imulLsb;
15437 imulExtended(ivec2(u1.wz), ivec2(u2.wz), imulMsb.yx, imulLsb.yx);
15438
15439 bool modfPassed = abs(fraction - 0.41) < 0.0001 && integer == 3.0;
15440 bool frexpPassed = abs(significand - 0.8525) < 0.0001 && exponent == 2;
15441 bool addPassed =
15442 addResult == uvec4(0xEB851EB8, 0x258BF257, 0x11111110, 0xFFFFFFFF) &&
15443 addCarry == uvec4(1, 0, 1, 0);
15444 bool subPassed = subResult == uvec2(0x26AF37BF, 0x12345678) && subBorrow == uvec2(1, 0);
15445 bool mulPassed =
15446 mulMsb == uvec4(0xEB9B208C, 0x01601D49, 0x121FA00A, 0x11E17CC0) &&
15447 mulLsb == uvec4(0xA83AB300, 0xD6B9FA88, 0x35068740, 0x822E97E0);
15448 bool imulPassed =
15449 imulMsb == ivec2(0xFFEB4992, 0xFE89E0E1) &&
15450 imulLsb == ivec2(0x35068740, 0x822E97E0);
15451
15452 color = vec4(modfPassed ? 1 : 0,
15453 frexpPassed ? 1 : 0,
15454 (addPassed ? 0.4 : 0.0) + (subPassed ? 0.6 : 0.0),
15455 (mulPassed ? 0.4 : 0.0) + (imulPassed ? 0.6 : 0.0));
15456 })";
15457
15458 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
15459 glUseProgram(program);
15460
15461 GLint floc = glGetUniformLocation(program, "f");
15462 GLint u1loc = glGetUniformLocation(program, "u1");
15463 GLint u2loc = glGetUniformLocation(program, "u2");
15464 ASSERT_NE(floc, -1);
15465 ASSERT_NE(u1loc, -1);
15466 ASSERT_NE(u2loc, -1);
15467 glUniform1f(floc, 3.41);
15468 glUniform4ui(u1loc, 0xFEDCBA98u, 0x13579BDFu, 0xFEDCBA98u, 0x13579BDFu);
15469 glUniform4ui(u2loc, 0xECA86420u, 0x12345678u, 0x12345678u, 0xECA86420u);
15470
15471 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
15472 EXPECT_GL_NO_ERROR();
15473
15474 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
15475 }
15476
15477 // Test that interpolateAt* work with swizzle. This test is disabled as swizzled interpolants are
15478 // only allowed in desktop GLSL.
TEST_P(GLSLTest_ES31,InterpolateAtWithSwizzle)15479 TEST_P(GLSLTest_ES31, InterpolateAtWithSwizzle)
15480 {
15481 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_multisample_interpolation"));
15482
15483 constexpr char kVS[] = R"(#version 310 es
15484
15485 out vec4 interpolant;
15486
15487 void main()
15488 {
15489 // The following triangle is being drawn over the framebuffer.
15490 //
15491 // (-1,3) |\
15492 // | \
15493 // | \
15494 // | \
15495 // | \
15496 // +--------------+
15497 // | | \
15498 // | | \
15499 // | Framebuffer | \
15500 // | | \
15501 // | | \
15502 // (-1,-1) +--------------+--------------- (3,-1)
15503 //
15504 // Interpolant is set such that interpolateAtCentroid would produce the desired value for
15505 // position == (0, 0), and interpolateAtOffset(0.5, -0.5) for position == (1,-1)
15506 if (gl_VertexID == 0)
15507 {
15508 gl_Position = vec4(-1, -1, 0, 1);
15509 interpolant = vec4(1.5, 0.5, 0, 0);
15510 }
15511 else if (gl_VertexID == 1)
15512 {
15513 gl_Position = vec4(3, -1, 0, 1);
15514 interpolant = vec4(0, 0, 1, 2);
15515 }
15516 else
15517 {
15518 gl_Position = vec4(-1, 3, 0, 1);
15519 interpolant = vec4(0, 1, -1, 2);
15520 }
15521 })";
15522
15523 constexpr char kFS[] = R"(#version 310 es
15524 #extension GL_OES_shader_multisample_interpolation : require
15525 precision highp float;
15526
15527 in vec4 interpolant;
15528 out vec4 color;
15529
15530 void main()
15531 {
15532 // Should result in (0.75, 1.0)
15533 vec2 atCentroid = interpolateAtCentroid(interpolant.xw);
15534 // Selecting the bottom-right corner, this should result in (0.5, 0.25), but interpolateAtOffset
15535 // doesn't make guarantees regarding the range and granularity of the offset. The interpolant
15536 // is given values such that the bottom-left/top-right diagonal is interpolated to a constant
15537 // value of (0, 0.5). The top-left corner has the value (-0.5, 0.75). We therefore make a
15538 // coarse test to make sure that atOffset.x > 0 and atOffset.y < 0.5, thus ensuring at least
15539 // that the offset is in the correct half of the pixel.
15540 vec2 atOffset = interpolateAtOffset(interpolant.zy, vec2(0.5, -0.5));
15541
15542 color = vec4(atCentroid, atOffset.x > 0.0 ? 1 : 0, atOffset.y < 0.5 ? 1 : 0);
15543 })";
15544
15545 GLRenderbuffer rbo;
15546 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
15547 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
15548
15549 GLFramebuffer fbo;
15550 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
15551 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
15552 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
15553
15554 ANGLE_GL_PROGRAM(program, kVS, kFS);
15555 glUseProgram(program);
15556
15557 glViewport(0, 0, 1, 1);
15558 glDrawArrays(GL_TRIANGLES, 0, 3);
15559 EXPECT_GL_NO_ERROR();
15560
15561 EXPECT_PIXEL_NEAR(0, 0, 191, 255, 255, 255, 1);
15562 }
15563
15564 class GLSLTestLoops : public GLSLTest
15565 {
15566 protected:
runTest(const char * fs)15567 void runTest(const char *fs)
15568 {
15569 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fs);
15570
15571 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
15572 EXPECT_GL_NO_ERROR();
15573
15574 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
15575 }
15576 };
15577
15578 // Test basic for loops
TEST_P(GLSLTestLoops,BasicFor)15579 TEST_P(GLSLTestLoops, BasicFor)
15580 {
15581 constexpr char kFS[] = R"(#version 300 es
15582 precision mediump float;
15583 out vec4 color;
15584
15585 void main()
15586 {
15587 int result = 0;
15588 for (int i = 0; i < 10; ++i)
15589 for (int j = 0; j < 8; ++j)
15590 {
15591 for (int k = 0; k < 2; ++k, ++j) ++result;
15592 for (int k = 0; k < 3; ++k) ++result;
15593 for (int k = 0; k < 0; ++k) ++result;
15594 }
15595
15596 color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
15597 })";
15598
15599 runTest(kFS);
15600 }
15601
15602 // Test for loop without condition
TEST_P(GLSLTestLoops,ForNoCondition)15603 TEST_P(GLSLTestLoops, ForNoCondition)
15604 {
15605 constexpr char kFS[] = R"(#version 300 es
15606 precision mediump float;
15607 out vec4 color;
15608
15609 void main()
15610 {
15611 int result = 0;
15612 for (int i = 0; i < 10; ++i)
15613 for (int j = 0; ; ++j)
15614 {
15615 for (int k = 0; k < 2; ++k, ++j) ++result;
15616 for (int k = 0; k < 3; ++k) ++result;
15617 for (int k = 0; k < 0; ++k) ++result;
15618
15619 if (j >= 8)
15620 break;
15621 }
15622
15623 color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
15624 })";
15625
15626 runTest(kFS);
15627 }
15628
15629 // Test for loop without init and expression
TEST_P(GLSLTestLoops,ForNoInitConditionOrExpression)15630 TEST_P(GLSLTestLoops, ForNoInitConditionOrExpression)
15631 {
15632 constexpr char kFS[] = R"(#version 300 es
15633 precision mediump float;
15634 out vec4 color;
15635
15636 void main()
15637 {
15638 int result = 0;
15639 for (int i = 0; i < 10; ++i)
15640 {
15641 int j = 0;
15642 for (;;)
15643 {
15644 for (int k = 0; k < 2; ++k, ++j) ++result;
15645 for (int k = 0; k < 3; ++k) ++result;
15646 for (int k = 0; k < 0; ++k) ++result;
15647
15648 if (j >= 8)
15649 break;
15650 ++j;
15651 }
15652 }
15653
15654 color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
15655 })";
15656
15657 runTest(kFS);
15658 }
15659
15660 // Test for loop with continue
TEST_P(GLSLTestLoops,ForContinue)15661 TEST_P(GLSLTestLoops, ForContinue)
15662 {
15663 constexpr char kFS[] = R"(#version 300 es
15664 precision mediump float;
15665 out vec4 color;
15666
15667 void main()
15668 {
15669 int result = 0;
15670 for (int i = 0; i < 10; ++i)
15671 for (int j = 0; j < 8; ++j)
15672 {
15673 for (int k = 0; k < 2; ++k, ++j) ++result;
15674 for (int k = 0; k < 3; ++k) ++result;
15675 if (i > 3)
15676 continue;
15677 for (int k = 0; k < 0; ++k) ++result;
15678 }
15679
15680 color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
15681 })";
15682
15683 runTest(kFS);
15684 }
15685
15686 // Test for loop with continue at the end of block
TEST_P(GLSLTestLoops,ForUnconditionalContinue)15687 TEST_P(GLSLTestLoops, ForUnconditionalContinue)
15688 {
15689 constexpr char kFS[] = R"(#version 300 es
15690 precision mediump float;
15691 out vec4 color;
15692
15693 void main()
15694 {
15695 int result = 0;
15696 for (int i = 0; i < 10; ++i)
15697 for (int j = 0; j < 8; ++j)
15698 {
15699 for (int k = 0; k < 2; ++k, ++j) ++result;
15700 for (int k = 0; k < 3; ++k) ++result;
15701 for (int k = 0; k < 0; ++k) ++result;
15702 continue;
15703 }
15704
15705 color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
15706 })";
15707
15708 runTest(kFS);
15709 }
15710
15711 // Test for loop with break at the end of block
TEST_P(GLSLTestLoops,ForUnconditionalBreak)15712 TEST_P(GLSLTestLoops, ForUnconditionalBreak)
15713 {
15714 constexpr char kFS[] = R"(#version 300 es
15715 precision mediump float;
15716 out vec4 color;
15717
15718 void main()
15719 {
15720 int result = 0;
15721 for (int i = 0; i < 10; ++i)
15722 for (int j = 0; j < 8; ++j)
15723 {
15724 for (int k = 0; k < 2; ++k, ++j) ++result;
15725 for (int k = 0; k < 3; ++k) ++result;
15726 for (int k = 0; k < 0; ++k) ++result;
15727 break;
15728 }
15729
15730 color = result == 50 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
15731 })";
15732
15733 runTest(kFS);
15734 }
15735
15736 // Test for loop with break and continue
TEST_P(GLSLTestLoops,ForBreakContinue)15737 TEST_P(GLSLTestLoops, ForBreakContinue)
15738 {
15739 constexpr char kFS[] = R"(#version 300 es
15740 precision mediump float;
15741 out vec4 color;
15742
15743 void main()
15744 {
15745 int result = 0;
15746 for (int i = 0; i < 10; ++i)
15747 for (int j = 0; j < 8; ++j)
15748 {
15749 if (j < 2) continue;
15750 if (j > 6) break;
15751 if (i < 3) continue;
15752 if (i > 8) break;
15753 ++result;
15754 }
15755
15756 color = result == 30 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
15757 })";
15758
15759 runTest(kFS);
15760 }
15761
15762 // Test basic while loops
TEST_P(GLSLTestLoops,BasicWhile)15763 TEST_P(GLSLTestLoops, BasicWhile)
15764 {
15765 constexpr char kFS[] = R"(#version 300 es
15766 precision mediump float;
15767 out vec4 color;
15768
15769 void main()
15770 {
15771 int result = 0;
15772 int i = 0;
15773 while (i < 10)
15774 {
15775 int j = 0;
15776 while (j < 8)
15777 {
15778 int k = 0;
15779 while (k < 2) { ++result; ++k; ++j; }
15780 while (k < 5) { ++result; ++k; }
15781 while (k < 4) { ++result; }
15782 ++j;
15783 }
15784 ++i;
15785 }
15786
15787 color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
15788 })";
15789
15790 runTest(kFS);
15791 }
15792
15793 // Test while loops with continue
TEST_P(GLSLTestLoops,WhileContinue)15794 TEST_P(GLSLTestLoops, WhileContinue)
15795 {
15796 constexpr char kFS[] = R"(#version 300 es
15797 precision mediump float;
15798 out vec4 color;
15799
15800 void main()
15801 {
15802 int result = 0;
15803 int i = 0;
15804 while (i < 10)
15805 {
15806 int j = 0;
15807 while (j < 8)
15808 {
15809 int k = 0;
15810 while (k < 2) { ++result; ++k; ++j; }
15811 while (k < 5) { ++result; ++k; }
15812 if (i > 3)
15813 {
15814 ++j;
15815 continue;
15816 }
15817 while (k < 4) { ++result; }
15818 ++j;
15819 }
15820 ++i;
15821 }
15822
15823 color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
15824 })";
15825
15826 runTest(kFS);
15827 }
15828
15829 // Test while loops with continue at the end of block
TEST_P(GLSLTestLoops,WhileUnconditionalContinue)15830 TEST_P(GLSLTestLoops, WhileUnconditionalContinue)
15831 {
15832 constexpr char kFS[] = R"(#version 300 es
15833 precision mediump float;
15834 out vec4 color;
15835
15836 void main()
15837 {
15838 int result = 0;
15839 int i = 0;
15840 while (i < 10)
15841 {
15842 int j = 0;
15843 while (j < 8)
15844 {
15845 int k = 0;
15846 while (k < 2) { ++result; ++k; ++j; }
15847 while (k < 5) { ++result; ++k; }
15848 while (k < 4) { ++result; }
15849 ++j;
15850 continue;
15851 }
15852 ++i;
15853 }
15854
15855 color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
15856 })";
15857
15858 runTest(kFS);
15859 }
15860
15861 // Test while loops with break
TEST_P(GLSLTestLoops,WhileBreak)15862 TEST_P(GLSLTestLoops, WhileBreak)
15863 {
15864 constexpr char kFS[] = R"(#version 300 es
15865 precision mediump float;
15866 out vec4 color;
15867
15868 void main()
15869 {
15870 int result = 0;
15871 int i = 0;
15872 while (i < 10)
15873 {
15874 int j = 0;
15875 while (true)
15876 {
15877 int k = 0;
15878 while (k < 2) { ++result; ++k; ++j; }
15879 while (k < 5) { ++result; ++k; }
15880 while (k < 4) { ++result; }
15881 ++j;
15882 if (j >= 8)
15883 break;
15884 }
15885 ++i;
15886 }
15887
15888 color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
15889 })";
15890
15891 runTest(kFS);
15892 }
15893
15894 // Test while loops with continue at the end of block
TEST_P(GLSLTestLoops,WhileUnconditionalBreak)15895 TEST_P(GLSLTestLoops, WhileUnconditionalBreak)
15896 {
15897 constexpr char kFS[] = R"(#version 300 es
15898 precision mediump float;
15899 out vec4 color;
15900
15901 void main()
15902 {
15903 int result = 0;
15904 int i = 0;
15905 while (i < 10)
15906 {
15907 int j = 0;
15908 while (j < 8)
15909 {
15910 int k = 0;
15911 while (k < 2) { ++result; ++k; ++j; }
15912 while (k < 5) { ++result; ++k; }
15913 while (k < 4) { ++result; }
15914 ++j;
15915 break;
15916 }
15917 ++i;
15918 }
15919
15920 color = result == 50 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
15921 })";
15922
15923 runTest(kFS);
15924 }
15925
15926 // Test basic do-while loops
TEST_P(GLSLTestLoops,BasicDoWhile)15927 TEST_P(GLSLTestLoops, BasicDoWhile)
15928 {
15929 constexpr char kFS[] = R"(#version 300 es
15930 precision mediump float;
15931 out vec4 color;
15932
15933 void main()
15934 {
15935 int result = 0;
15936 int i = 0;
15937 do
15938 {
15939 int j = 0;
15940 do
15941 {
15942 int k = 0;
15943 do { ++result; ++k; ++j; } while (k < 2);
15944 do { ++result; ++k; } while (k < 5);
15945 do { ++result; } while (k < 3);
15946 ++j;
15947 } while (j < 8);
15948 ++i;
15949 } while (i < 10);
15950
15951 color = result == 180 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
15952 })";
15953
15954 runTest(kFS);
15955 }
15956
15957 // Test do-while loops with continue
TEST_P(GLSLTestLoops,DoWhileContinue)15958 TEST_P(GLSLTestLoops, DoWhileContinue)
15959 {
15960 constexpr char kFS[] = R"(#version 300 es
15961 precision mediump float;
15962 out vec4 color;
15963
15964 void main()
15965 {
15966 int result = 0;
15967 int i = 0;
15968 do
15969 {
15970 int j = 0;
15971 do
15972 {
15973 int k = 0;
15974 do { ++result; ++k; ++j; } while (k < 2);
15975 if (i > 3)
15976 {
15977 ++j;
15978 continue;
15979 }
15980 do { ++result; ++k; } while (k < 5);
15981 do { ++result; } while (k < 3);
15982 ++j;
15983 } while (j < 8);
15984 ++i;
15985 } while (i < 10);
15986
15987 color = result == 108 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
15988 })";
15989
15990 runTest(kFS);
15991 }
15992
15993 // Test do-while loops with continue at the end of block
TEST_P(GLSLTestLoops,DoWhileUnconditionalContinue)15994 TEST_P(GLSLTestLoops, DoWhileUnconditionalContinue)
15995 {
15996 constexpr char kFS[] = R"(#version 300 es
15997 precision mediump float;
15998 out vec4 color;
15999
16000 void main()
16001 {
16002 int result = 0;
16003 int i = 0;
16004 do
16005 {
16006 int j = 0;
16007 do
16008 {
16009 int k = 0;
16010 do { ++result; ++k; ++j; continue; } while (k < 2);
16011 do { ++result; ++k; continue; } while (k < 5);
16012 do { ++result; continue; } while (k < 3);
16013 ++j;
16014 } while (j < 8);
16015 ++i;
16016 } while (i < 10);
16017
16018 color = result == 180 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16019 })";
16020
16021 runTest(kFS);
16022 }
16023
16024 // Test do-while loops with break
TEST_P(GLSLTestLoops,DoWhileBreak)16025 TEST_P(GLSLTestLoops, DoWhileBreak)
16026 {
16027 constexpr char kFS[] = R"(#version 300 es
16028 precision mediump float;
16029 out vec4 color;
16030
16031 void main()
16032 {
16033 int result = 0;
16034 int i = 0;
16035 do
16036 {
16037 int j = 0;
16038 do
16039 {
16040 int k = 0;
16041 do { ++result; ++k; ++j; } while (k < 2);
16042 do { ++result; ++k; } while (k < 5);
16043 do { ++result; } while (k < 3);
16044 ++j;
16045 if (j >= 8)
16046 break;
16047 } while (true);
16048 ++i;
16049 } while (i < 10);
16050
16051 color = result == 180 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16052 })";
16053
16054 runTest(kFS);
16055 }
16056
16057 // Test do-while loops with break at the end of block
TEST_P(GLSLTestLoops,DoWhileUnconditionalBreak)16058 TEST_P(GLSLTestLoops, DoWhileUnconditionalBreak)
16059 {
16060 constexpr char kFS[] = R"(#version 300 es
16061 precision mediump float;
16062 out vec4 color;
16063
16064 void main()
16065 {
16066 int result = 0;
16067 int i = 0;
16068 do
16069 {
16070 int j = 0;
16071 do
16072 {
16073 int k = 0;
16074 do { ++result; ++k; ++j; break; } while (k < 2);
16075 do { ++result; ++k; break; } while (k < 5);
16076 do { ++result; break; } while (k < 3);
16077 ++j;
16078 } while (j < 8);
16079 ++i;
16080 } while (i < 10);
16081
16082 color = result == 120 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16083 })";
16084
16085 runTest(kFS);
16086 }
16087
16088 // Test for loop with continue inside switch.
TEST_P(GLSLTestLoops,ForContinueInSwitch)16089 TEST_P(GLSLTestLoops, ForContinueInSwitch)
16090 {
16091 constexpr char kFS[] = R"(#version 300 es
16092 precision mediump float;
16093 out vec4 color;
16094
16095 void main()
16096 {
16097 int result = 0;
16098 for (int i = 0; i < 10; ++i)
16099 for (int j = 0; j < 8; ++j)
16100 {
16101 switch (j)
16102 {
16103 case 2:
16104 case 3:
16105 case 4:
16106 ++result;
16107 // fallthrough
16108 case 5:
16109 case 6:
16110 ++result;
16111 break;
16112 default:
16113 continue;
16114 }
16115 }
16116
16117 color = result == 80 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16118 })";
16119
16120 runTest(kFS);
16121 }
16122
16123 // Test while loop with continue inside switch
TEST_P(GLSLTestLoops,WhileContinueInSwitch)16124 TEST_P(GLSLTestLoops, WhileContinueInSwitch)
16125 {
16126 constexpr char kFS[] = R"(#version 300 es
16127 precision mediump float;
16128 out vec4 color;
16129
16130 void main()
16131 {
16132 int result = 0;
16133 int i = 0;
16134 while (i < 10)
16135 {
16136 int j = 0;
16137 while (j < 8)
16138 {
16139 switch (j)
16140 {
16141 case 2:
16142 default:
16143 case 3:
16144 case 4:
16145 ++j;
16146 ++result;
16147 continue;
16148 case 0:
16149 case 1:
16150 case 7:
16151 break;
16152 }
16153 ++j;
16154 }
16155 ++i;
16156 }
16157
16158 color = result == 50 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16159 })";
16160
16161 runTest(kFS);
16162 }
16163
16164 // Test do-while loops with continue in switch
TEST_P(GLSLTestLoops,DoWhileContinueInSwitch)16165 TEST_P(GLSLTestLoops, DoWhileContinueInSwitch)
16166 {
16167 constexpr char kFS[] = R"(#version 300 es
16168 precision mediump float;
16169 out vec4 color;
16170
16171 void main()
16172 {
16173 int result = 0;
16174 int i = 0;
16175 do
16176 {
16177 int j = 0;
16178 do
16179 {
16180 switch (j)
16181 {
16182 case 0:
16183 ++j;
16184 continue;
16185 default:
16186 case 2:
16187 case 3:
16188 case 4:
16189 ++j;
16190 ++result;
16191 if (j >= 2 && j <= 6)
16192 break;
16193 else
16194 continue;
16195 }
16196 ++result;
16197 } while (j < 8);
16198 ++i;
16199 } while (i < 10);
16200
16201 color = result == 120 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16202 })";
16203
16204 runTest(kFS);
16205 }
16206
16207 // Test prune-able loop with side effect in statements.
TEST_P(GLSLTestLoops,SideEffectsInPrunableFor)16208 TEST_P(GLSLTestLoops, SideEffectsInPrunableFor)
16209 {
16210 constexpr char kFS[] = R"(#version 300 es
16211 precision mediump float;
16212 out vec4 color;
16213
16214 void main()
16215 {
16216 int a = 4;
16217 float b = 0.;
16218 for (int c = a++; (b += float(c) / 8.) < 0.; b += 0.3)
16219 {
16220 if (2 == 0);
16221 }
16222 int c = a - 4;
16223
16224 // Expect c to be 1 and b to be 0.5
16225 color = c == 1 && abs(b - 0.5) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16226 })";
16227
16228 runTest(kFS);
16229 }
16230
16231 // Test that precision is retained for constants (which are constant folded). Adapted from a WebGL
16232 // test.
TEST_P(GLSLTest,ConstantFoldedConstantsRetainPrecision)16233 TEST_P(GLSLTest, ConstantFoldedConstantsRetainPrecision)
16234 {
16235 constexpr char kFS[] = R"(
16236 // It is assumed that uTest is set to 0. It's here to make the expression not constant.
16237 uniform mediump float uTest;
16238 void main() {
16239 // exact representation of 4096.5 requires 13 bits of relative precision.
16240 const highp float c = 4096.5;
16241 mediump float a = 0.0;
16242 // Below, addition should be evaluated at highp, since one of the operands has the highp qualifier.
16243 // Thus fract should also be evaluated at highp.
16244 // See OpenGL ES Shading Language spec section 4.5.2.
16245 // This should make the result 0.5, since highp provides at least 16 bits of relative precision.
16246 // (exceptions for operation precision are allowed for a small number of computationally
16247 // intensive built-in functions, but it is reasonable to think that fract is not one of those).
16248 // However, if fract() is incorrectly evaluated at minimum precision fulfilling mediump criteria,
16249 // or at IEEE half float precision, the result is 0.0.
16250 a = fract(c + uTest);
16251 // Multiply by 2.0 to make the color green.
16252 gl_FragColor = vec4(0.0, 2.0 * a, 0.0, 1.0);
16253 })";
16254
16255 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
16256
16257 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
16258 EXPECT_GL_NO_ERROR();
16259
16260 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
16261 }
16262
16263 // Test that vector and matrix scalarization does not affect rendering.
TEST_P(GLSLTest,VectorAndMatrixScalarizationDoesNotAffectRendering)16264 TEST_P(GLSLTest, VectorAndMatrixScalarizationDoesNotAffectRendering)
16265 {
16266 constexpr char kFS[] = R"(
16267 precision mediump float;
16268
16269 varying vec2 v_texCoord;
16270
16271 float a = 0.;
16272 #define A 0.
16273
16274 #define r(a) mat2( cos( a + vec4(0,-1.5708,1.5708,0) ) )
16275 vec2 c;
16276 #define f(U,a) ( c = (U) * r(a) , sin(10.*c.x) )
16277
16278 void main() {
16279 vec2 U = v_texCoord;
16280
16281 gl_FragColor = U.y > .5
16282 ? vec4( f(U,a) , f(U*4.,a) , 0,1.0) // top
16283 : vec4( f(U,A) , f(U*4.,A) , 0,1.0); // bottom
16284 }
16285
16286 )";
16287
16288 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), kFS);
16289 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
16290
16291 // Make sure we rendered something.
16292 EXPECT_PIXEL_NE(0, 0, 0, 0, 0, 0);
16293
16294 // Comapare one line in top half to one line in bottom half.
16295 int compareWidth = getWindowWidth();
16296 int compareHeight = getWindowHeight() / 4;
16297
16298 ASSERT_GE(compareWidth, 2);
16299 ASSERT_GE(compareHeight, 2);
16300
16301 GLubyte pixelValue[4];
16302 constexpr int tolerance = 12;
16303
16304 for (int x = 0; x < compareWidth; ++x)
16305 {
16306 glReadPixels(x, compareHeight, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixelValue);
16307 EXPECT_PIXEL_NEAR(x, getWindowHeight() - compareHeight, pixelValue[0], pixelValue[1],
16308 pixelValue[2], pixelValue[3], tolerance);
16309 }
16310 EXPECT_GL_NO_ERROR();
16311 }
16312
16313 // Tests initializing a shader IO block using the shader translator option.
TEST_P(GLSLTest_ES31_InitShaderVariables,InitIOBlock)16314 TEST_P(GLSLTest_ES31_InitShaderVariables, InitIOBlock)
16315 {
16316 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
16317
16318 const char kVS[] = R"(#version 310 es
16319 #extension GL_EXT_shader_io_blocks : require
16320 in vec4 position;
16321 out BlockType {
16322 vec4 blockMember;
16323 } BlockTypeOut;
16324
16325 void main()
16326 {
16327 gl_Position = position;
16328 })";
16329
16330 const char kFS[] = R"(#version 310 es
16331 #extension GL_EXT_shader_io_blocks : require
16332 precision mediump float;
16333 out vec4 colorOut;
16334 in BlockType {
16335 vec4 blockMember;
16336 } BlockTypeOut;
16337
16338 void main()
16339 {
16340 if (BlockTypeOut.blockMember == vec4(0)) {
16341 colorOut = vec4(0, 1, 0, 1);
16342 } else {
16343 colorOut = vec4(1, 0, 0, 1);
16344 }
16345 })";
16346
16347 ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
16348 drawQuad(testProgram, "position", 0.5f, 1.0f, true);
16349 ASSERT_GL_NO_ERROR();
16350 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
16351 }
16352
16353 // Tests initializing a nameless shader IO block using the shader translator option.
TEST_P(GLSLTest_ES31_InitShaderVariables,InitIOBlockNameless)16354 TEST_P(GLSLTest_ES31_InitShaderVariables, InitIOBlockNameless)
16355 {
16356 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
16357
16358 const char kVS[] = R"(#version 310 es
16359 #extension GL_EXT_shader_io_blocks : require
16360 in vec4 position;
16361 out BlockType {
16362 vec4 blockMember;
16363 };
16364
16365 void main()
16366 {
16367 gl_Position = position;
16368 })";
16369
16370 const char kFS[] = R"(#version 310 es
16371 #extension GL_EXT_shader_io_blocks : require
16372 precision mediump float;
16373 out vec4 colorOut;
16374 in BlockType {
16375 vec4 blockMember;
16376 };
16377
16378 void main()
16379 {
16380 if (blockMember == vec4(0)) {
16381 colorOut = vec4(0, 1, 0, 1);
16382 } else {
16383 colorOut = vec4(1, 0, 0, 1);
16384 }
16385 })";
16386
16387 ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
16388 drawQuad(testProgram, "position", 0.5f, 1.0f, true);
16389 ASSERT_GL_NO_ERROR();
16390 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
16391 }
16392
16393 // Tests initializing a shader IO block with an array using the shader translator option.
TEST_P(GLSLTest_ES31_InitShaderVariables,InitIOBlockWithArray)16394 TEST_P(GLSLTest_ES31_InitShaderVariables, InitIOBlockWithArray)
16395 {
16396 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
16397
16398 const char kVS[] = R"(#version 310 es
16399 #extension GL_EXT_shader_io_blocks : require
16400 in vec4 position;
16401 out BlockType {
16402 vec4 blockMember[2];
16403 } BlockTypeOut;
16404
16405 void main()
16406 {
16407 gl_Position = position;
16408 })";
16409
16410 const char kFS[] = R"(#version 310 es
16411 #extension GL_EXT_shader_io_blocks : require
16412 precision mediump float;
16413 out vec4 colorOut;
16414 in BlockType {
16415 vec4 blockMember[2];
16416 } BlockTypeOut;
16417
16418 void main()
16419 {
16420 if (BlockTypeOut.blockMember[0] == vec4(0) &&
16421 BlockTypeOut.blockMember[1] == vec4(0)) {
16422 colorOut = vec4(0, 1, 0, 1);
16423 } else {
16424 colorOut = vec4(1, 0, 0, 1);
16425 }
16426 })";
16427
16428 ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
16429 drawQuad(testProgram, "position", 0.5f, 1.0f, true);
16430 ASSERT_GL_NO_ERROR();
16431 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
16432 }
16433
16434 // Tests initializing a shader IO block array using the shader translator option.
TEST_P(GLSLTest_ES31_InitShaderVariables,InitIOBlockArray)16435 TEST_P(GLSLTest_ES31_InitShaderVariables, InitIOBlockArray)
16436 {
16437 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
16438
16439 const char kVS[] = R"(#version 310 es
16440 #extension GL_EXT_shader_io_blocks : require
16441 in vec4 position;
16442 out BlockType {
16443 vec4 blockMember;
16444 } BlockTypeOut[2];
16445
16446 void main()
16447 {
16448 gl_Position = position;
16449 })";
16450
16451 const char kFS[] = R"(#version 310 es
16452 #extension GL_EXT_shader_io_blocks : require
16453 precision mediump float;
16454 out vec4 colorOut;
16455 in BlockType {
16456 vec4 blockMember;
16457 } BlockTypeOut[2];
16458
16459 void main()
16460 {
16461 if (BlockTypeOut[0].blockMember == vec4(0) &&
16462 BlockTypeOut[1].blockMember == vec4(0)) {
16463 colorOut = vec4(0, 1, 0, 1);
16464 } else {
16465 colorOut = vec4(1, 0, 0, 1);
16466 }
16467 })";
16468
16469 ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
16470 drawQuad(testProgram, "position", 0.5f, 1.0f, true);
16471 ASSERT_GL_NO_ERROR();
16472 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
16473 }
16474
16475 // Tests initializing a shader IO block with a struct using the shader translator option.
TEST_P(GLSLTest_ES31_InitShaderVariables,InitIOBlockWithStruct)16476 TEST_P(GLSLTest_ES31_InitShaderVariables, InitIOBlockWithStruct)
16477 {
16478 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
16479
16480 const char kVS[] = R"(#version 310 es
16481 #extension GL_EXT_shader_io_blocks : require
16482 in vec4 position;
16483 struct s {
16484 float f;
16485 vec2 v;
16486 };
16487 out BlockType {
16488 s blockMember;
16489 } BlockTypeOut;
16490
16491 void main()
16492 {
16493 gl_Position = position;
16494 })";
16495
16496 const char kFS[] = R"(#version 310 es
16497 #extension GL_EXT_shader_io_blocks : require
16498 precision mediump float;
16499 out vec4 colorOut;
16500 struct s {
16501 float f;
16502 vec2 v;
16503 };
16504 in BlockType {
16505 s blockMember;
16506 } BlockTypeOut;
16507
16508 void main()
16509 {
16510 if (BlockTypeOut.blockMember.f == 0.0 &&
16511 BlockTypeOut.blockMember.v == vec2(0)) {
16512 colorOut = vec4(0, 1, 0, 1);
16513 } else {
16514 colorOut = vec4(1, 0, 0, 1);
16515 }
16516 })";
16517
16518 ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
16519 drawQuad(testProgram, "position", 0.5f, 1.0f, true);
16520 ASSERT_GL_NO_ERROR();
16521 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
16522 }
16523
16524 // Tests initializing an IO block with a complicated set of types, using the shader translator.
TEST_P(GLSLTest_ES31_InitShaderVariables,InitIOBlockWithComplexTypes)16525 TEST_P(GLSLTest_ES31_InitShaderVariables, InitIOBlockWithComplexTypes)
16526 {
16527 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
16528
16529 const char kVS[] = R"(#version 310 es
16530 #extension GL_EXT_shader_io_blocks : require
16531 in vec4 position;
16532 struct s {
16533 float f;
16534 vec2 v;
16535 };
16536 out BlockType {
16537 vec4 v;
16538 s s1;
16539 s s2[2];
16540 } BlockTypeOut;
16541
16542 void main()
16543 {
16544 gl_Position = position;
16545 })";
16546
16547 const char kFS[] = R"(#version 310 es
16548 #extension GL_EXT_shader_io_blocks : require
16549 precision mediump float;
16550 out vec4 colorOut;
16551 struct s {
16552 float f;
16553 vec2 v;
16554 };
16555 in BlockType {
16556 vec4 v;
16557 s s1;
16558 s s2[2];
16559 } BlockTypeOut;
16560
16561 void main()
16562 {
16563 s sz = s(0.0, vec2(0));
16564 if (BlockTypeOut.v == vec4(0) &&
16565 BlockTypeOut.s1 == sz &&
16566 BlockTypeOut.s2[0] == sz &&
16567 BlockTypeOut.s2[1] == sz) {
16568 colorOut = vec4(0, 1, 0, 1);
16569 } else {
16570 colorOut = vec4(1, 0, 0, 1);
16571 }
16572 })";
16573
16574 ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
16575 drawQuad(testProgram, "position", 0.5f, 1.0f, true);
16576 ASSERT_GL_NO_ERROR();
16577 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
16578 }
16579
16580 // Tests an unsuccessful re-link using glBindAttribLocation.
TEST_P(GLSLTest_ES3,UnsuccessfulRelinkWithBindAttribLocation)16581 TEST_P(GLSLTest_ES3, UnsuccessfulRelinkWithBindAttribLocation)
16582 {
16583 // Make a simple program.
16584 ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
16585
16586 // Install the executable.
16587 glUseProgram(testProgram);
16588
16589 // Re-link with a bad XFB varying and a bound attrib location.
16590 const char *tfVaryings = "gl_FragColor";
16591 glTransformFeedbackVaryings(testProgram, 1, &tfVaryings, GL_SEPARATE_ATTRIBS);
16592 glBindAttribLocation(testProgram, 8, essl1_shaders::PositionAttrib());
16593 glLinkProgram(testProgram);
16594 GLint linkStatus = 999;
16595 glGetProgramiv(testProgram, GL_LINK_STATUS, &linkStatus);
16596 ASSERT_GL_NO_ERROR();
16597 ASSERT_EQ(linkStatus, GL_FALSE);
16598
16599 // Under normal GL this is not an error.
16600 glDrawArrays(GL_TRIANGLES, 79, 16);
16601 EXPECT_GL_NO_ERROR();
16602 }
16603
16604 // Tests an unsuccessful re-link using glBindAttribLocation under WebGL.
TEST_P(WebGL2GLSLTest,UnsuccessfulRelinkWithBindAttribLocation)16605 TEST_P(WebGL2GLSLTest, UnsuccessfulRelinkWithBindAttribLocation)
16606 {
16607 // Make a simple program.
16608 ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
16609
16610 // Install the executable.
16611 glUseProgram(testProgram);
16612
16613 // Re-link with a bad XFB varying and a bound attrib location.
16614 const char *tfVaryings = "gl_FragColor";
16615 glTransformFeedbackVaryings(testProgram, 1, &tfVaryings, GL_SEPARATE_ATTRIBS);
16616 glBindAttribLocation(testProgram, 8, essl1_shaders::PositionAttrib());
16617 glLinkProgram(testProgram);
16618 GLint linkStatus = 999;
16619 glGetProgramiv(testProgram, GL_LINK_STATUS, &linkStatus);
16620 ASSERT_GL_NO_ERROR();
16621 ASSERT_EQ(linkStatus, GL_FALSE);
16622
16623 // Under WebGL this is an error.
16624 glDrawArrays(GL_TRIANGLES, 79, 16);
16625 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
16626 }
16627
16628 // Covers a HLSL compiler bug.
TEST_P(GLSLTest_ES3,ComplexCrossExpression)16629 TEST_P(GLSLTest_ES3, ComplexCrossExpression)
16630 {
16631 constexpr char kFS[] = R"(#version 300 es
16632 precision mediump float;
16633 vec3 a = vec3(0.0);
16634 out vec4 color;
16635 void main()
16636 {
16637 cross(max(vec3(0.0), reflect(dot(a, vec3(0.0)), 0.0)), vec3(0.0));
16638 })";
16639
16640 ANGLE_GL_PROGRAM(testProgram, essl3_shaders::vs::Simple(), kFS);
16641 drawQuad(testProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
16642 ASSERT_GL_NO_ERROR();
16643 }
16644
16645 // Regression test for a crash in SPIR-V output when faced with an array of struct constant.
TEST_P(GLSLTest_ES3,ArrayOfStructConstantBug)16646 TEST_P(GLSLTest_ES3, ArrayOfStructConstantBug)
16647 {
16648 constexpr char kFS[] = R"(#version 300 es
16649 struct S {
16650 int foo;
16651 };
16652 void main() {
16653 S a[3];
16654 a = S[3](S(0), S(1), S(2));
16655 })";
16656
16657 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
16658
16659 const char *sourceArray[1] = {kFS};
16660 GLint lengths[1] = {static_cast<GLint>(sizeof(kFS) - 1)};
16661 glShaderSource(shader, 1, sourceArray, lengths);
16662 glCompileShader(shader);
16663
16664 GLint compileResult;
16665 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
16666 EXPECT_NE(compileResult, 0);
16667 }
16668
16669 // Regression test for a bug in SPIR-V output where float+matrix was mishandled.
TEST_P(GLSLTest_ES3,FloatPlusMatrix)16670 TEST_P(GLSLTest_ES3, FloatPlusMatrix)
16671 {
16672 constexpr char kFS[] = R"(#version 300 es
16673
16674 precision mediump float;
16675
16676 layout(location=0) out vec4 color;
16677
16678 uniform float f;
16679
16680 void main()
16681 {
16682 mat3x2 m = f + mat3x2(0);
16683 color = vec4(m[0][0]);
16684 })";
16685
16686 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
16687
16688 const char *sourceArray[1] = {kFS};
16689 GLint lengths[1] = {static_cast<GLint>(sizeof(kFS) - 1)};
16690 glShaderSource(shader, 1, sourceArray, lengths);
16691 glCompileShader(shader);
16692
16693 GLint compileResult;
16694 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
16695 EXPECT_NE(compileResult, 0);
16696 }
16697
16698 // Regression test for a bug in SPIR-V output where a transformation creates float(constant) without
16699 // folding it into a TIntermConstantUnion. This transformation is clamping non-constant indices in
16700 // WebGL. The |false ? i : 5| as index caused the transformation to consider this a non-constant
16701 // index.
TEST_P(WebGL2GLSLTest,IndexClampConstantIndexBug)16702 TEST_P(WebGL2GLSLTest, IndexClampConstantIndexBug)
16703 {
16704 constexpr char kFS[] = R"(#version 300 es
16705 precision highp float;
16706
16707 layout(location=0) out float f;
16708
16709 uniform int i;
16710
16711 void main()
16712 {
16713 float data[10];
16714 f = data[false ? i : 5];
16715 })";
16716
16717 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
16718
16719 const char *sourceArray[1] = {kFS};
16720 GLint lengths[1] = {static_cast<GLint>(sizeof(kFS) - 1)};
16721 glShaderSource(shader, 1, sourceArray, lengths);
16722 glCompileShader(shader);
16723
16724 GLint compileResult;
16725 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
16726 EXPECT_NE(compileResult, 0);
16727 }
16728
16729 // Test robustness of out-of-bounds lod in texelFetch
TEST_P(WebGL2GLSLTest,TexelFetchLodOutOfBounds)16730 TEST_P(WebGL2GLSLTest, TexelFetchLodOutOfBounds)
16731 {
16732 constexpr char kVS[] = R"(#version 300 es
16733 in vec4 vertexPosition;
16734 void main() {
16735 gl_Position = vertexPosition;
16736 })";
16737
16738 constexpr char kFS[] = R"(#version 300 es
16739 precision highp float;
16740 uniform highp sampler2DArray textureArray;
16741 uniform int textureLod;
16742 out vec4 fragColor;
16743 void main() {
16744 fragColor = texelFetch(textureArray, ivec3(gl_FragCoord.xy, 0), textureLod);
16745 })";
16746
16747 ANGLE_GL_PROGRAM(program, kVS, kFS);
16748 glUseProgram(program);
16749 const GLint lodLoc = glGetUniformLocation(program, "textureLod");
16750 EXPECT_NE(lodLoc, -1);
16751 const GLint textureLoc = glGetUniformLocation(program, "textureArray");
16752 EXPECT_NE(textureLoc, -1);
16753
16754 const GLint attribLocation = glGetAttribLocation(program, "vertexPosition");
16755 GLBuffer buffer;
16756 glBindBuffer(GL_ARRAY_BUFFER, buffer);
16757 constexpr float vertices[12] = {
16758 -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1,
16759 };
16760 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
16761 glEnableVertexAttribArray(attribLocation);
16762 glVertexAttribPointer(attribLocation, 2, GL_FLOAT, false, 0, 0);
16763
16764 GLTexture texture;
16765 glBindTexture(GL_TEXTURE_2D_ARRAY, texture);
16766 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 5, GL_RGBA8, 16, 16, 3);
16767 glUniform1i(textureLoc, 0);
16768
16769 // Test LOD too large
16770 glUniform1i(lodLoc, 0x7FFF);
16771 glDrawArrays(GL_TRIANGLES, 0, 6);
16772
16773 // Test LOD negative
16774 glUniform1i(lodLoc, -1);
16775 glDrawArrays(GL_TRIANGLES, 0, 6);
16776 }
16777
16778 // Test that framebuffer fetch transforms gl_LastFragData in the presence of gl_FragCoord without
16779 // failing validation (adapted from a Chromium test, see anglebug.com/6951)
TEST_P(GLSLTest,FramebufferFetchWithLastFragData)16780 TEST_P(GLSLTest, FramebufferFetchWithLastFragData)
16781 {
16782 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch"));
16783
16784 constexpr char kFS[] = R"(#version 100
16785
16786 #extension GL_EXT_shader_framebuffer_fetch : require
16787 varying mediump vec4 color;
16788 void main() {
16789 gl_FragColor = length(gl_FragCoord.xy) * gl_LastFragData[0];
16790 })";
16791
16792 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
16793
16794 const char *sourceArray[1] = {kFS};
16795 GLint lengths[1] = {static_cast<GLint>(sizeof(kFS) - 1)};
16796 glShaderSource(shader, 1, sourceArray, lengths);
16797 glCompileShader(shader);
16798
16799 GLint compileResult;
16800 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
16801 EXPECT_NE(compileResult, 0);
16802 }
16803
16804 // Test that loop body ending in a branch doesn't fail compilation
TEST_P(GLSLTest,LoopBodyEndingInBranch1)16805 TEST_P(GLSLTest, LoopBodyEndingInBranch1)
16806 {
16807 constexpr char kFS[] = R"(void main(){for(int a,i;;gl_FragCoord)continue;})";
16808
16809 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
16810
16811 const char *sourceArray[1] = {kFS};
16812 GLint lengths[1] = {static_cast<GLint>(sizeof(kFS) - 1)};
16813 glShaderSource(shader, 1, sourceArray, lengths);
16814 glCompileShader(shader);
16815
16816 GLint compileResult;
16817 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
16818 EXPECT_NE(compileResult, 0);
16819 }
16820
16821 // Test that loop body ending in a branch doesn't fail compilation
TEST_P(GLSLTest,LoopBodyEndingInBranch2)16822 TEST_P(GLSLTest, LoopBodyEndingInBranch2)
16823 {
16824 constexpr char kFS[] =
16825 R"(void main(){for(int a,i;bool(gl_FragCoord.x);gl_FragCoord){continue;}})";
16826
16827 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
16828
16829 const char *sourceArray[1] = {kFS};
16830 GLint lengths[1] = {static_cast<GLint>(sizeof(kFS) - 1)};
16831 glShaderSource(shader, 1, sourceArray, lengths);
16832 glCompileShader(shader);
16833
16834 GLint compileResult;
16835 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
16836 EXPECT_NE(compileResult, 0);
16837 }
16838
16839 // Test that loop body ending in a branch doesn't fail compilation
TEST_P(GLSLTest,LoopBodyEndingInBranch3)16840 TEST_P(GLSLTest, LoopBodyEndingInBranch3)
16841 {
16842 constexpr char kFS[] = R"(void main(){for(int a,i;;gl_FragCoord){{continue;}}})";
16843
16844 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
16845
16846 const char *sourceArray[1] = {kFS};
16847 GLint lengths[1] = {static_cast<GLint>(sizeof(kFS) - 1)};
16848 glShaderSource(shader, 1, sourceArray, lengths);
16849 glCompileShader(shader);
16850
16851 GLint compileResult;
16852 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
16853 EXPECT_NE(compileResult, 0);
16854 }
16855
16856 // Test that loop body ending in a branch doesn't fail compilation
TEST_P(GLSLTest,LoopBodyEndingInBranch4)16857 TEST_P(GLSLTest, LoopBodyEndingInBranch4)
16858 {
16859 constexpr char kFS[] = R"(void main(){for(int a,i;;gl_FragCoord){{continue;}{}{}{{}{}}}})";
16860
16861 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
16862
16863 const char *sourceArray[1] = {kFS};
16864 GLint lengths[1] = {static_cast<GLint>(sizeof(kFS) - 1)};
16865 glShaderSource(shader, 1, sourceArray, lengths);
16866 glCompileShader(shader);
16867
16868 GLint compileResult;
16869 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
16870 EXPECT_NE(compileResult, 0);
16871 }
16872
16873 // Test that loop body ending in a branch doesn't fail compilation
TEST_P(GLSLTest,LoopBodyEndingInBranch5)16874 TEST_P(GLSLTest, LoopBodyEndingInBranch5)
16875 {
16876 constexpr char kFS[] = R"(void main(){while(bool(gl_FragCoord.x)){{continue;{}}{}}})";
16877
16878 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
16879
16880 const char *sourceArray[1] = {kFS};
16881 GLint lengths[1] = {static_cast<GLint>(sizeof(kFS) - 1)};
16882 glShaderSource(shader, 1, sourceArray, lengths);
16883 glCompileShader(shader);
16884
16885 GLint compileResult;
16886 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
16887 EXPECT_NE(compileResult, 0);
16888 }
16889
16890 // Test that loop body ending in a branch doesn't fail compilation
TEST_P(GLSLTest,LoopBodyEndingInBranch6)16891 TEST_P(GLSLTest, LoopBodyEndingInBranch6)
16892 {
16893 constexpr char kFS[] = R"(void main(){do{{continue;{}}{}}while(bool(gl_FragCoord.x));})";
16894
16895 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
16896
16897 const char *sourceArray[1] = {kFS};
16898 GLint lengths[1] = {static_cast<GLint>(sizeof(kFS) - 1)};
16899 glShaderSource(shader, 1, sourceArray, lengths);
16900 glCompileShader(shader);
16901
16902 GLint compileResult;
16903 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
16904 EXPECT_NE(compileResult, 0);
16905 }
16906
16907 // Test that aliasing function out parameters work. The GLSL spec says:
16908 //
16909 // > Because the function works with local copies of parameters, there are no issues regarding
16910 // > aliasing of variables within a function.
16911 //
16912 // In the test below, while the value of x is unknown after the function call, the result of the
16913 // function must deterministically be true.
TEST_P(GLSLTest,AliasingFunctionOutParams)16914 TEST_P(GLSLTest, AliasingFunctionOutParams)
16915 {
16916 constexpr char kFS[] = R"(precision highp float;
16917
16918 const vec4 colorGreen = vec4(0.,1.,0.,1.);
16919 const vec4 colorRed = vec4(1.,0.,0.,1.);
16920
16921 bool outParametersAreDistinct(out float x, out float y) {
16922 x = 1.0;
16923 y = 2.0;
16924 return x == 1.0 && y == 2.0;
16925 }
16926 void main() {
16927 float x = 0.0;
16928 gl_FragColor = outParametersAreDistinct(x, x) ? colorGreen : colorRed;
16929 }
16930 )";
16931
16932 ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), kFS);
16933 drawQuad(testProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
16934 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
16935 ASSERT_GL_NO_ERROR();
16936 }
16937
16938 // Test that aliasing function out parameters work even when multiple params are aliased.
TEST_P(GLSLTest,AliasingFunctionOutParamsMultiple)16939 TEST_P(GLSLTest, AliasingFunctionOutParamsMultiple)
16940 {
16941 constexpr char kFS[] = R"(precision highp float;
16942
16943 const vec4 colorGreen = vec4(0.,1.,0.,1.);
16944 const vec4 colorRed = vec4(1.,0.,0.,1.);
16945
16946 bool outParametersAreDistinct(out float x, out float y, out float z, out float a) {
16947 x = 1.0;
16948 y = 2.0;
16949 z = 3.0;
16950 a = 4.0;
16951 return x == 1.0 && y == 2.0 && z == 3.0 && a == 4.0;
16952 }
16953 void main() {
16954 float x = 0.0;
16955 float y = 0.0;
16956 gl_FragColor = outParametersAreDistinct(x, x, y, y) ? colorGreen : colorRed;
16957 }
16958 )";
16959
16960 ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), kFS);
16961 drawQuad(testProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
16962 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
16963 ASSERT_GL_NO_ERROR();
16964 }
16965
16966 // Test that aliasing function inout parameters work.
TEST_P(GLSLTest,AliasingFunctionInOutParams)16967 TEST_P(GLSLTest, AliasingFunctionInOutParams)
16968 {
16969 constexpr char kFS[] = R"(precision highp float;
16970
16971 const vec4 colorGreen = vec4(0.,1.,0.,1.);
16972 const vec4 colorRed = vec4(1.,0.,0.,1.);
16973
16974 bool inoutParametersAreDistinct(inout float x, inout float y) {
16975 x = 1.0;
16976 y = 2.0;
16977 return x == 1.0 && y == 2.0;
16978 }
16979 void main() {
16980 float x = 0.0;
16981 gl_FragColor = inoutParametersAreDistinct(x, x) ? colorGreen : colorRed;
16982 }
16983 )";
16984
16985 ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), kFS);
16986 drawQuad(testProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
16987 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
16988 ASSERT_GL_NO_ERROR();
16989 }
16990
16991 // Test coverage of some matrix/scalar ops which Metal translation was missing.
TEST_P(GLSLTest,MatrixScalarOps)16992 TEST_P(GLSLTest, MatrixScalarOps)
16993 {
16994 constexpr char kFS[] = R"(precision highp float;
16995 void main() {
16996 float scalar = 0.5;
16997 mat3 matrix = mat3(vec3(0.1), vec3(0.1), vec3(0.1));
16998
16999 mat3 m0 = scalar / matrix;
17000 mat3 m1 = scalar * matrix;
17001 mat3 m2 = scalar + matrix;
17002 mat3 m3 = scalar - matrix;
17003
17004 gl_FragColor = vec4(m0[0][0], m1[0][0], m2[0][0], m3[0][0]);
17005 }
17006 )";
17007
17008 ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), kFS);
17009 ASSERT_GL_NO_ERROR();
17010
17011 drawQuad(testProgram, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
17012 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 13, 153, 102), 1.0);
17013 ASSERT_GL_NO_ERROR();
17014 }
17015
17016 // Test coverage of some matrix ops which Metal translation was missing.
TEST_P(GLSLTest,MatrixNegate)17017 TEST_P(GLSLTest, MatrixNegate)
17018 {
17019 constexpr char kFS[] = R"(precision highp float;
17020 void main() {
17021 mat3 matrix = mat3(vec3(-0.1), vec3(-0.1), vec3(-0.1));
17022
17023 mat3 m0 = -matrix;
17024
17025 gl_FragColor = vec4(m0[0][0], 0, 0, 1);
17026 }
17027 )";
17028
17029 ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), kFS);
17030 ASSERT_GL_NO_ERROR();
17031
17032 drawQuad(testProgram, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
17033 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(26, 0, 0, 255), 1.0);
17034 ASSERT_GL_NO_ERROR();
17035 }
17036
17037 // Test coverage of the mix(float, float, bool) overload which was missing in Metal translation
TEST_P(GLSLTest_ES3,MixFloatFloatBool)17038 TEST_P(GLSLTest_ES3, MixFloatFloatBool)
17039 {
17040 constexpr char kFS[] = R"(#version 300 es
17041 precision highp float;
17042 out vec4 fragColor;
17043 void main() {
17044 vec4 testData = vec4(0.0, 1.0, 0.5, 0.25);
17045 float scalar = mix(testData.x, testData.y, testData.x < 0.5);
17046 vec2 vector = mix(testData.xy, testData.xw, bvec2(testData.x < 0.5, testData.y < 0.5));
17047 fragColor = vec4(scalar, vector.x, vector.y, 1);
17048 }
17049 )";
17050
17051 ANGLE_GL_PROGRAM(testProgram, essl3_shaders::vs::Simple(), kFS);
17052 ASSERT_GL_NO_ERROR();
17053
17054 drawQuad(testProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
17055 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(255, 0, 255, 255));
17056 ASSERT_GL_NO_ERROR();
17057 }
17058
17059 // Test that aliasing function inout parameters work when more than one param is aliased.
TEST_P(GLSLTest,AliasingFunctionInOutParamsMultiple)17060 TEST_P(GLSLTest, AliasingFunctionInOutParamsMultiple)
17061 {
17062 constexpr char kFS[] = R"(precision highp float;
17063
17064 const vec4 colorGreen = vec4(0.,1.,0.,1.);
17065 const vec4 colorRed = vec4(1.,0.,0.,1.);
17066
17067 bool inoutParametersAreDistinct(inout float x, inout float y, inout float z, inout float a) {
17068 x = 1.0;
17069 y = 2.0;
17070 z = 3.0;
17071 a = 4.0;
17072 return x == 1.0 && y == 2.0 && z == 3.0 && a == 4.0;
17073 }
17074 void main() {
17075 float x = 0.0;
17076 float y = 0.0;
17077 gl_FragColor = inoutParametersAreDistinct(x, x, y, y) ? colorGreen : colorRed;
17078 }
17079 )";
17080
17081 ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), kFS);
17082 drawQuad(testProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
17083 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
17084 ASSERT_GL_NO_ERROR();
17085 }
17086
17087 // Test that aliasing function out parameter with a global works.
TEST_P(GLSLTest,AliasingFunctionOutParamAndGlobal)17088 TEST_P(GLSLTest, AliasingFunctionOutParamAndGlobal)
17089 {
17090 constexpr char kFS[] = R"(precision highp float;
17091
17092 const vec4 colorGreen = vec4(0.,1.,0.,1.);
17093 const vec4 colorRed = vec4(1.,0.,0.,1.);
17094
17095 float x = 1.0;
17096 bool outParametersAreDistinctFromGlobal(out float y) {
17097 y = 2.0;
17098 return x == 1.0 && y == 2.0;
17099 }
17100 void main() {
17101 gl_FragColor = outParametersAreDistinctFromGlobal(x) ? colorGreen : colorRed;
17102 }
17103 )";
17104
17105 ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), kFS);
17106 drawQuad(testProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
17107 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
17108 ASSERT_GL_NO_ERROR();
17109 }
17110
17111 // Make sure const sampler parameters work.
TEST_P(GLSLTest,ConstSamplerParameter)17112 TEST_P(GLSLTest, ConstSamplerParameter)
17113 {
17114 constexpr char kFS[] = R"(precision mediump float;
17115 uniform sampler2D samp;
17116
17117 vec4 sampleConstSampler(const sampler2D s) {
17118 return texture2D(s, vec2(0));
17119 }
17120
17121 void main() {
17122 gl_FragColor = sampleConstSampler(samp);
17123 }
17124 )";
17125 CompileShader(GL_FRAGMENT_SHADER, kFS);
17126 ASSERT_GL_NO_ERROR();
17127 }
17128
17129 // Make sure passing const sampler parameters to another function work.
TEST_P(GLSLTest,ConstSamplerParameterAsArgument)17130 TEST_P(GLSLTest, ConstSamplerParameterAsArgument)
17131 {
17132 constexpr char kFS[] = R"(precision mediump float;
17133
17134 uniform sampler2D samp;
17135
17136 vec4 sampleSampler(sampler2D s) {
17137 return texture2D(s, vec2(0));
17138 }
17139
17140 vec4 sampleConstSampler(const sampler2D s) {
17141 return sampleSampler(s);
17142 }
17143
17144 void main() {
17145 gl_FragColor = sampleConstSampler(samp);
17146 }
17147 )";
17148 CompileShader(GL_FRAGMENT_SHADER, kFS);
17149 ASSERT_GL_NO_ERROR();
17150 }
17151
17152 // Test for a driver bug with matrix multiplication in the tessellation control shader.
TEST_P(GLSLTest_ES31,TessellationControlShaderMatrixMultiplicationBug)17153 TEST_P(GLSLTest_ES31, TessellationControlShaderMatrixMultiplicationBug)
17154 {
17155 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
17156
17157 constexpr char kTCS[] = R"(#version 310 es
17158 #extension GL_EXT_tessellation_shader : enable
17159 layout(vertices = 1) out;
17160 precision highp float;
17161
17162 patch out mat4 x;
17163
17164 void main()
17165 {
17166 x = mat4(
17167 0.53455, 0.47307, 0.34935, 0.28717,
17168 0.67195, 0.59992, 0.48213, 0.43678,
17169 0.76376, 0.6772, 0.55361, 0.5165,
17170 0.77996, 0.68862, 0.56187, 0.52611
17171 );
17172
17173 const mat4 m = mat4(
17174 vec4( -1.0, 3.0,-3.0, 1.0),
17175 vec4( 3.0,-6.0, 3.0, 0.0),
17176 vec4( -3.0, 3.0, 0.0, 0.0),
17177 vec4( 1.0, 0.0, 0.0, 0.0)
17178 );
17179
17180 x = m * x;
17181
17182 gl_TessLevelInner[0u] = 1.;
17183 gl_TessLevelInner[1u] = 1.;
17184 gl_TessLevelOuter[0u] = 1.;
17185 gl_TessLevelOuter[1u] = 1.;
17186 gl_TessLevelOuter[2u] = 1.;
17187 gl_TessLevelOuter[3u] = 1.;
17188 })";
17189
17190 constexpr char kTES[] = R"(#version 310 es
17191 #extension GL_EXT_tessellation_shader : enable
17192 layout(quads, cw, fractional_odd_spacing) in;
17193 precision highp float;
17194
17195 patch in mat4 x;
17196
17197 out mat4 x_fs;
17198
17199 void main()
17200 {
17201 x_fs = x;
17202 gl_Position = vec4(gl_TessCoord.xy * 2. - 1., 0, 1);
17203 })";
17204
17205 constexpr char kFS[] = R"(#version 310 es
17206 precision highp float;
17207
17208 in mat4 x_fs;
17209 out vec4 color;
17210
17211 void main()
17212 {
17213 // Note: on the failing driver, .w of every column has the same value as .x of the same column.
17214
17215 const mat4 expect = mat4(
17216 0.12378, -0.18672, -0.18444, 0.53455,
17217 0.1182, -0.13728, -0.21609, 0.67195,
17218 0.12351, -0.11109, -0.25968, 0.76376,
17219 0.1264, -0.10623, -0.27402, 0.77996
17220 );
17221
17222 color = vec4(all(lessThan(abs(x_fs[0] - expect[0]), vec4(0.01))),
17223 all(lessThan(abs(x_fs[1] - expect[1]), vec4(0.01))),
17224 all(lessThan(abs(x_fs[2] - expect[2]), vec4(0.01))),
17225 all(lessThan(abs(x_fs[3] - expect[3]), vec4(0.01))));
17226 })";
17227
17228 ANGLE_GL_PROGRAM_WITH_TESS(program, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
17229 drawPatches(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, GL_FALSE);
17230 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
17231 ASSERT_GL_NO_ERROR();
17232 }
17233
17234 // Test for a driver bug with matrix copy in the tessellation control shader.
TEST_P(GLSLTest_ES31,TessellationControlShaderMatrixCopyBug)17235 TEST_P(GLSLTest_ES31, TessellationControlShaderMatrixCopyBug)
17236 {
17237 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
17238
17239 constexpr char kTCS[] = R"(#version 310 es
17240 #extension GL_EXT_tessellation_shader : enable
17241 layout(vertices = 1) out;
17242 precision highp float;
17243
17244 patch out mat4 x;
17245 patch out vec4 col0;
17246
17247 void main()
17248 {
17249 // Note: if |x| is not an |out| varying, the test passes.
17250 x = mat4(
17251 0.53455, 0.47307, 0.34935, 0.28717,
17252 0.67195, 0.59992, 0.48213, 0.43678,
17253 0.76376, 0.6772, 0.55361, 0.5165,
17254 0.77996, 0.68862, 0.56187, 0.52611
17255 );
17256
17257 const mat4 m = mat4(
17258 vec4( -1.0, 3.0,-3.0, 1.0),
17259 vec4( 3.0,-6.0, 3.0, 0.0),
17260 vec4( -3.0, 3.0, 0.0, 0.0),
17261 vec4( 1.0, 0.0, 0.0, 0.0)
17262 );
17263
17264 mat4 temp = x;
17265
17266 // Note: On the failing driver, commenting this line makes the test pass.
17267 // However, the output being tested is |temp|, assigned above, not |x|.
17268 x = m * x;
17269
17270 col0 = temp[0];
17271
17272 gl_TessLevelInner[0u] = 1.;
17273 gl_TessLevelInner[1u] = 1.;
17274 gl_TessLevelOuter[0u] = 1.;
17275 gl_TessLevelOuter[1u] = 1.;
17276 gl_TessLevelOuter[2u] = 1.;
17277 gl_TessLevelOuter[3u] = 1.;
17278 })";
17279
17280 constexpr char kTES[] = R"(#version 310 es
17281 #extension GL_EXT_tessellation_shader : enable
17282 layout(quads, cw, fractional_odd_spacing) in;
17283 precision highp float;
17284
17285 patch in vec4 col0;
17286
17287 out vec4 col0_fs;
17288
17289 void main()
17290 {
17291 col0_fs = col0;
17292 gl_Position = vec4(gl_TessCoord.xy * 2. - 1., 0, 1);
17293 })";
17294
17295 constexpr char kFS[] = R"(#version 310 es
17296 precision highp float;
17297
17298 in vec4 col0_fs;
17299 out vec4 color;
17300
17301 void main()
17302 {
17303 // Note: on the failing driver, |col0| has the value of |m * x|, not |temp|.
17304 color = vec4(abs(col0_fs.x - 0.53455) < 0.01,
17305 abs(col0_fs.y - 0.47307) < 0.01,
17306 abs(col0_fs.z - 0.34935) < 0.01,
17307 abs(col0_fs.w - 0.28717) < 0.01);
17308 })";
17309
17310 ANGLE_GL_PROGRAM_WITH_TESS(program, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
17311 drawPatches(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, GL_FALSE);
17312 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
17313 ASSERT_GL_NO_ERROR();
17314 }
17315
17316 // Tests the generation of HLSL functions with uint/int parameters that may be ambiguous.
TEST_P(GLSLTest_ES3,AmbiguousHLSLIntegerFunctionParameters)17317 TEST_P(GLSLTest_ES3, AmbiguousHLSLIntegerFunctionParameters)
17318 {
17319 const char kVS[] = R"(#version 300 es
17320 precision highp float;
17321 void main()
17322 {
17323 gl_Position = vec4(0, 0, 0, 0);
17324 })";
17325
17326 const char kFS[] = R"(#version 300 es
17327 precision highp float;
17328 out vec4 color;
17329 void main()
17330 {
17331 // Ensure that both uint and int to float constructors are generated before the ambiguous usage.
17332 int i = int(gl_FragCoord.x);
17333 float f1 = float(i);
17334 color.r = f1;
17335
17336 uint ui = uint(gl_FragCoord.x);
17337 float f2 = float(i);
17338 color.g = f2;
17339
17340 // Ambiguous call
17341 float f3 = float(1u << (2u * ui));
17342 color.b = f3;
17343 })";
17344
17345 ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
17346 }
17347
17348 // Tests adding a struct definition inline in a shader.
17349 // Metal backend contains a pass that separates struct definition and declaration.
TEST_P(GLSLTest_ES3,StructInShader)17350 TEST_P(GLSLTest_ES3, StructInShader)
17351 {
17352 const char kVS[] = R"(#version 300 es
17353 precision highp float;
17354 void main(void)
17355 {
17356 struct structMain {
17357 float i;
17358 } testStruct;
17359
17360 testStruct.i = 5.0 ;
17361 gl_Position = vec4(testStruct.i - 4.0, 0, 0, 1);
17362 })";
17363
17364 const char kFS[] = R"(#version 300 es
17365 precision highp float;
17366 out vec4 color;
17367 void main()
17368 {
17369 color = vec4(0,1,0,0);
17370 })";
17371
17372 ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
17373 }
17374
17375 // Issue: A while loop's expression, and a branch
17376 // condition with EOpContinue were being deep
17377 // copied as part of monomorphize functions,
17378 // causing a crash, as they were not null-checked.
17379 // Tests transforming a function that will be monomorphized.
TEST_P(GLSLTest_ES3,MonomorphizeForAndContinue)17380 TEST_P(GLSLTest_ES3, MonomorphizeForAndContinue)
17381 {
17382
17383 constexpr char kFS[] =
17384 R"(#version 300 es
17385
17386 precision mediump float;
17387 out vec4 fragOut;
17388 struct aParam
17389 {
17390 sampler2D sampler;
17391 };
17392 uniform aParam theParam;
17393
17394 float monomorphizedFunction(aParam a)
17395 {
17396 int i = 0;
17397 vec4 j = vec4(0);
17398 for(;;)
17399 {
17400 if(i++ < 10)
17401 {
17402 j += texture(a.sampler, vec2(0.0f,0.0f));
17403 continue;
17404 }
17405 break;
17406 }
17407 return j.a;
17408 }
17409 void main()
17410 {
17411 fragOut.a = monomorphizedFunction(theParam);
17412 }
17413 )";
17414 CompileShader(GL_FRAGMENT_SHADER, kFS);
17415 ASSERT_GL_NO_ERROR();
17416 }
17417
17418 // Tests inout parameters with array references.
TEST_P(GLSLTest_ES3,InoutWithArrayRefs)17419 TEST_P(GLSLTest_ES3, InoutWithArrayRefs)
17420 {
17421 const char kVS[] = R"(#version 300 es
17422 precision highp float;
17423 void swap(inout float a, inout float b)
17424 {
17425 float tmp = a;
17426 a = b;
17427 b = tmp;
17428 }
17429
17430 void main(void)
17431 {
17432 vec3 testVec = vec3(0.0, 1.0, 1.0);
17433 swap(testVec[0], testVec[1]);
17434 gl_Position = vec4(testVec[0], testVec[1], testVec[2], 1.0);
17435 })";
17436
17437 const char kFS[] = R"(#version 300 es
17438 precision highp float;
17439 out vec4 color;
17440 void main()
17441 {
17442 color = vec4(0,1,0,0);
17443 })";
17444
17445 ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
17446 }
17447
17448 // Test that sample variables compile.
TEST_P(GLSLTest_ES3,SampleVariables)17449 TEST_P(GLSLTest_ES3, SampleVariables)
17450 {
17451 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_sample_variables"));
17452
17453 const char kFS[] = R"(#version 300 es
17454 #extension GL_OES_sample_variables : require
17455 precision highp float;
17456 out vec4 color;
17457 void main()
17458 {
17459 gl_SampleMask[0] = gl_SampleMaskIn[0] & 0x55555555;
17460 color = vec4(gl_SamplePosition.yx, float(gl_SampleID), float(gl_MaxSamples + gl_NumSamples));
17461 })";
17462
17463 ANGLE_GL_PROGRAM(testProgram, essl3_shaders::vs::Simple(), kFS);
17464 }
17465
17466 // Test that shader caching maintains uniforms across compute shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheComputeWithUniform)17467 TEST_P(GLSLTest_ES31, ShaderCacheComputeWithUniform)
17468 {
17469 ANGLE_SKIP_TEST_IF(!IsVulkan());
17470 constexpr char kCS[] = R"(#version 310 es
17471 layout (local_size_x = 2, local_size_y = 3, local_size_z = 1) in;
17472
17473 uniform uint inputs[6];
17474
17475 layout (binding = 0, std430) buffer OutputBuffer {
17476 uint outputs[6];
17477 };
17478
17479 void main() {
17480 outputs[gl_LocalInvocationIndex] = inputs[gl_LocalInvocationIndex];
17481 }
17482 )";
17483
17484 ANGLE_GL_COMPUTE_PROGRAM(unusedProgram, kCS);
17485 ASSERT_GL_NO_ERROR();
17486 // Delete the shader and recompile to fetch from cache.
17487 glDeleteProgram(unusedProgram);
17488 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
17489 ASSERT_GL_NO_ERROR();
17490 glUseProgram(program);
17491
17492 constexpr std::array<GLuint, 6> kInputUniform = {1, 2, 3, 4, 5, 6};
17493 for (int i = 0; i < static_cast<int>(kInputUniform.size()); ++i)
17494 {
17495 const std::string uniformName =
17496 std::string("inputs[") + std::to_string(i) + std::string("]");
17497 int inputLocation =
17498 glGetUniformLocation(program, static_cast<const GLchar *>(uniformName.c_str()));
17499 glUniform1ui(inputLocation, kInputUniform[i]);
17500 ASSERT_GL_NO_ERROR();
17501 }
17502
17503 constexpr std::array<GLuint, 6> kOutputInitData = {0, 0, 0, 0, 0, 0};
17504 GLBuffer outputBuffer;
17505 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
17506 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLuint) * kOutputInitData.size(),
17507 kOutputInitData.data(), GL_STATIC_READ);
17508 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, outputBuffer);
17509
17510 glDispatchCompute(1, 1, 1);
17511 glDeleteProgram(program);
17512 ASSERT_GL_NO_ERROR();
17513 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
17514
17515 auto outputData = static_cast<const GLuint *>(glMapBufferRange(
17516 GL_SHADER_STORAGE_BUFFER, 0, sizeof(GLuint) * kOutputInitData.size(), GL_MAP_READ_BIT));
17517 for (int i = 0; i < static_cast<int>(kInputUniform.size()); ++i)
17518 {
17519 EXPECT_EQ(kInputUniform[i], outputData[i]);
17520 }
17521 }
17522
17523 // Test that shader caching maintains uniform blocks across shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheComputeWithUniformBlocks)17524 TEST_P(GLSLTest_ES31, ShaderCacheComputeWithUniformBlocks)
17525 {
17526 ANGLE_SKIP_TEST_IF(!IsVulkan());
17527 constexpr char kCS[] = R"(#version 310 es
17528 layout (local_size_x = 2, local_size_y = 3, local_size_z = 1) in;
17529
17530 layout (std140) uniform Input1 {
17531 uint input1;
17532 };
17533
17534 layout (std140) uniform Input2 {
17535 uint input2;
17536 };
17537
17538 layout (binding = 0, std430) buffer OutputBuffer {
17539 uint outputs[6];
17540 };
17541
17542 void main() {
17543 if (gl_LocalInvocationIndex < uint(3))
17544 {
17545 outputs[gl_LocalInvocationIndex] = input1;
17546 }
17547 else
17548 {
17549 outputs[gl_LocalInvocationIndex] = input2;
17550 }
17551 }
17552 )";
17553
17554 ANGLE_GL_COMPUTE_PROGRAM(unusedProgram, kCS);
17555 ASSERT_GL_NO_ERROR();
17556 // Delete the shader and recompile to fetch from cache.
17557 glDeleteProgram(unusedProgram);
17558 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
17559 ASSERT_GL_NO_ERROR();
17560 glUseProgram(program);
17561
17562 constexpr GLuint kInput1Data = 1;
17563 GLBuffer input1;
17564 glBindBuffer(GL_UNIFORM_BUFFER, input1);
17565 glBufferData(GL_UNIFORM_BUFFER, sizeof(GLuint), &kInput1Data, GL_STATIC_COPY);
17566 const GLuint kInput1Index = glGetUniformBlockIndex(program, "Input1");
17567 glUniformBlockBinding(program, kInput1Index, 1);
17568 glBindBufferBase(GL_UNIFORM_BUFFER, 1, input1);
17569 glBindBuffer(GL_UNIFORM_BUFFER, 0);
17570 ASSERT_GL_NO_ERROR();
17571
17572 constexpr GLuint kInput2Data = 2;
17573 GLBuffer input2;
17574 glBindBuffer(GL_UNIFORM_BUFFER, input2);
17575 glBufferData(GL_UNIFORM_BUFFER, sizeof(GLuint), &kInput2Data, GL_STATIC_COPY);
17576 const GLuint kInput2Index = glGetUniformBlockIndex(program, "Input2");
17577 glUniformBlockBinding(program, kInput2Index, 2);
17578 glBindBufferBase(GL_UNIFORM_BUFFER, 2, input2);
17579 glBindBuffer(GL_UNIFORM_BUFFER, 0);
17580 ASSERT_GL_NO_ERROR();
17581
17582 constexpr std::array<GLuint, 6> kOutputInitData = {0, 0, 0, 0, 0, 0};
17583 GLBuffer outputBuffer;
17584 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
17585 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLuint) * kOutputInitData.size(),
17586 kOutputInitData.data(), GL_STATIC_READ);
17587 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, outputBuffer);
17588 ASSERT_GL_NO_ERROR();
17589
17590 glDispatchCompute(1, 1, 1);
17591 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
17592 glDeleteProgram(program);
17593 ASSERT_GL_NO_ERROR();
17594
17595 auto outputData = static_cast<const GLuint *>(glMapBufferRange(
17596 GL_SHADER_STORAGE_BUFFER, 0, sizeof(GLuint) * kOutputInitData.size(), GL_MAP_READ_BIT));
17597 constexpr std::array<GLuint, 6> kWant = {kInput1Data, kInput1Data, kInput1Data,
17598 kInput2Data, kInput2Data, kInput2Data};
17599 for (int i = 0; i < static_cast<int>(kWant.size()); ++i)
17600 {
17601 EXPECT_EQ(kWant[i], outputData[i]);
17602 }
17603 }
17604
17605 // Test that shader caching maintains uniforms across vertex shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheVertexWithUniform)17606 TEST_P(GLSLTest_ES31, ShaderCacheVertexWithUniform)
17607 {
17608 ANGLE_SKIP_TEST_IF(!IsVulkan());
17609 constexpr char kVS[] = R"(#version 310 es
17610
17611 precision mediump float;
17612
17613 layout (location = 0) in vec4 a_position;
17614
17615 uniform float redInput;
17616
17617 out float redValue;
17618
17619 void main() {
17620 gl_Position = a_position;
17621 redValue = redInput;
17622 })";
17623
17624 constexpr char kFS[] = R"(#version 310 es
17625
17626 precision mediump float;
17627
17628 in float redValue;
17629
17630 out vec4 fragColor;
17631
17632 void main()
17633 {
17634 fragColor = vec4(redValue, 0., 0., 1.);
17635 })";
17636
17637 ANGLE_GL_PROGRAM(unusedProgram, kVS, kFS);
17638 ASSERT_GL_NO_ERROR();
17639 // Delete the shader and recompile to fetch from cache.
17640 glDeleteProgram(unusedProgram);
17641 ANGLE_GL_PROGRAM(program, kVS, kFS);
17642 ASSERT_GL_NO_ERROR();
17643 glUseProgram(program);
17644
17645 constexpr GLfloat kRedValue = 1.0f;
17646 int redInputLocation = glGetUniformLocation(program, "redInput");
17647 glUniform1f(redInputLocation, kRedValue);
17648 ASSERT_GL_NO_ERROR();
17649
17650 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
17651 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
17652 }
17653
17654 // Test that shader caching maintains uniform blocks across vertex shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheVertexWithUniformBlock)17655 TEST_P(GLSLTest_ES31, ShaderCacheVertexWithUniformBlock)
17656 {
17657 ANGLE_SKIP_TEST_IF(!IsVulkan());
17658 constexpr char kVS[] = R"(#version 310 es
17659
17660 precision mediump float;
17661
17662 layout (location = 0) in vec4 a_position;
17663
17664 layout (std140) uniform Input {
17665 float redInput;
17666 };
17667
17668 out float redValue;
17669
17670 void main() {
17671 gl_Position = a_position;
17672 redValue = redInput;
17673 })";
17674
17675 constexpr char kFS[] = R"(#version 310 es
17676
17677 precision mediump float;
17678
17679 in float redValue;
17680
17681 out vec4 fragColor;
17682
17683 void main()
17684 {
17685 fragColor = vec4(redValue, 0., 0., 1.);
17686 })";
17687
17688 ANGLE_GL_PROGRAM(unusedProgram, kVS, kFS);
17689 ASSERT_GL_NO_ERROR();
17690 // Delete the shader and recompile to fetch from cache.
17691 glDeleteProgram(unusedProgram);
17692 ANGLE_GL_PROGRAM(program, kVS, kFS);
17693 ASSERT_GL_NO_ERROR();
17694 glUseProgram(program);
17695
17696 constexpr GLfloat kInputData = 1.0f;
17697 GLBuffer input;
17698 glBindBuffer(GL_UNIFORM_BUFFER, input);
17699 glBufferData(GL_UNIFORM_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
17700 const GLuint kInputIndex = glGetUniformBlockIndex(program, "Input");
17701 glUniformBlockBinding(program, kInputIndex, 0);
17702 glBindBufferBase(GL_UNIFORM_BUFFER, 0, input);
17703 glBindBuffer(GL_UNIFORM_BUFFER, 0);
17704 ASSERT_GL_NO_ERROR();
17705
17706 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
17707 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
17708 }
17709
17710 // Test that shader caching maintains SSBOs across vertex shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheVertexWithSSBO)17711 TEST_P(GLSLTest_ES31, ShaderCacheVertexWithSSBO)
17712 {
17713 ANGLE_SKIP_TEST_IF(!IsVulkan());
17714
17715 // Check that GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS is at least 1.
17716 GLint maxVertexShaderStorageBlocks;
17717 glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &maxVertexShaderStorageBlocks);
17718 ANGLE_SKIP_TEST_IF(maxVertexShaderStorageBlocks == 0);
17719 constexpr char kVS[] = R"(#version 310 es
17720
17721 precision mediump float;
17722
17723 layout (location = 0) in vec4 a_position;
17724
17725 layout (binding = 0, std430) buffer Input {
17726 float redInput;
17727 };
17728
17729 out float redValue;
17730
17731 void main() {
17732 gl_Position = a_position;
17733 redValue = redInput;
17734 })";
17735
17736 constexpr char kFS[] = R"(#version 310 es
17737
17738 precision mediump float;
17739
17740 in float redValue;
17741
17742 out vec4 fragColor;
17743
17744 void main()
17745 {
17746 fragColor = vec4(redValue, 0., 0., 1.);
17747 })";
17748
17749 ANGLE_GL_PROGRAM(unusedProgram, kVS, kFS);
17750 ASSERT_GL_NO_ERROR();
17751 // Delete the shader and recompile to fetch from cache.
17752 glDeleteProgram(unusedProgram);
17753 ANGLE_GL_PROGRAM(program, kVS, kFS);
17754 ASSERT_GL_NO_ERROR();
17755 glUseProgram(program);
17756
17757 constexpr GLfloat kInputData = 1.0f;
17758 GLBuffer input;
17759 glBindBuffer(GL_SHADER_STORAGE_BUFFER, input);
17760 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
17761 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, input);
17762 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
17763 ASSERT_GL_NO_ERROR();
17764
17765 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
17766 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
17767 }
17768
17769 // Test that shader caching maintains uniforms across vertex shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheFragmentWithUniform)17770 TEST_P(GLSLTest_ES31, ShaderCacheFragmentWithUniform)
17771 {
17772 ANGLE_SKIP_TEST_IF(!IsVulkan());
17773 constexpr char kFS[] = R"(#version 310 es
17774
17775 precision mediump float;
17776
17777 uniform float redValue;
17778
17779 out vec4 fragColor;
17780
17781 void main()
17782 {
17783 fragColor = vec4(redValue, 0., 0., 1.);
17784 })";
17785
17786 ANGLE_GL_PROGRAM(unusedProgram, essl31_shaders::vs::Simple(), kFS);
17787 ASSERT_GL_NO_ERROR();
17788 // Delete the shader and recompile to fetch from cache.
17789 glDeleteProgram(unusedProgram);
17790 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
17791 ASSERT_GL_NO_ERROR();
17792 glUseProgram(program);
17793
17794 GLfloat redValue = 1.0f;
17795 int redInputLocation = glGetUniformLocation(program, "redValue");
17796 glUniform1f(redInputLocation, redValue);
17797 ASSERT_GL_NO_ERROR();
17798
17799 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
17800 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
17801 }
17802
17803 // Test that shader caching maintains uniform blocks across vertex shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheFragmentWithUniformBlock)17804 TEST_P(GLSLTest_ES31, ShaderCacheFragmentWithUniformBlock)
17805 {
17806 ANGLE_SKIP_TEST_IF(!IsVulkan());
17807 constexpr char kFS[] = R"(#version 310 es
17808
17809 precision mediump float;
17810
17811 layout (std140) uniform Input {
17812 float redValue;
17813 };
17814
17815 out vec4 fragColor;
17816
17817 void main()
17818 {
17819 fragColor = vec4(redValue, 0., 0., 1.);
17820 })";
17821
17822 ANGLE_GL_PROGRAM(unusedProgram, essl31_shaders::vs::Simple(), kFS);
17823 ASSERT_GL_NO_ERROR();
17824 // Delete the shader and recompile to fetch from cache.
17825 glDeleteProgram(unusedProgram);
17826 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
17827 ASSERT_GL_NO_ERROR();
17828 glUseProgram(program);
17829
17830 constexpr GLfloat kInputData = 1.0f;
17831 GLBuffer input;
17832 glBindBuffer(GL_UNIFORM_BUFFER, input);
17833 glBufferData(GL_UNIFORM_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
17834 const GLuint kInputIndex = glGetUniformBlockIndex(program, "Input");
17835 glUniformBlockBinding(program, kInputIndex, 0);
17836 glBindBufferBase(GL_UNIFORM_BUFFER, 0, input);
17837 glBindBuffer(GL_UNIFORM_BUFFER, 0);
17838 ASSERT_GL_NO_ERROR();
17839
17840 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
17841 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
17842 }
17843
17844 // Test that shader caching maintains SSBOs across vertex shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheFragmentWithSSBO)17845 TEST_P(GLSLTest_ES31, ShaderCacheFragmentWithSSBO)
17846 {
17847 ANGLE_SKIP_TEST_IF(!IsVulkan());
17848 constexpr char kFS[] = R"(#version 310 es
17849
17850 precision mediump float;
17851
17852 layout (binding = 0, std430) buffer Input {
17853 float redValue;
17854 };
17855
17856 out vec4 fragColor;
17857
17858 void main()
17859 {
17860 fragColor = vec4(redValue, 0., 0., 1.);
17861 })";
17862
17863 ANGLE_GL_PROGRAM(unusedProgram, essl31_shaders::vs::Simple(), kFS);
17864 ASSERT_GL_NO_ERROR();
17865 // Delete the shader and recompile to fetch from cache.
17866 glDeleteProgram(unusedProgram);
17867 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
17868 ASSERT_GL_NO_ERROR();
17869 glUseProgram(program);
17870
17871 constexpr GLfloat kInputData = 1.0f;
17872 GLBuffer input;
17873 glBindBuffer(GL_SHADER_STORAGE_BUFFER, input);
17874 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
17875 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, input);
17876 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
17877 ASSERT_GL_NO_ERROR();
17878
17879 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
17880 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
17881 }
17882
17883 // Test that shader caching maintains whether GL_ARB_sample_shading is enabled across shader
17884 // compilations.
TEST_P(GLSLTest_ES31,ShaderCacheFragmentWithARBSampleShading)17885 TEST_P(GLSLTest_ES31, ShaderCacheFragmentWithARBSampleShading)
17886 {
17887 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ARB_sample_shading"));
17888 ANGLE_SKIP_TEST_IF(!IsVulkan());
17889
17890 constexpr char kFS[] = R"(#version 310 es
17891 #extension GL_ARB_sample_shading : enable
17892
17893 precision mediump float;
17894
17895 out vec4 fragColor;
17896
17897 void main()
17898 {
17899 #ifdef GL_ARB_sample_shading
17900 fragColor = vec4(1., 0., 0., 1.);
17901 #else
17902 fragColor = vec4(0.);
17903 #endif
17904 })";
17905
17906 ANGLE_GL_PROGRAM(unusedProgram, essl31_shaders::vs::Simple(), kFS);
17907 ASSERT_GL_NO_ERROR();
17908 // Delete the shader and recompile to fetch from cache.
17909 glDeleteProgram(unusedProgram);
17910 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
17911 ASSERT_GL_NO_ERROR();
17912 glUseProgram(program);
17913
17914 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
17915 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
17916 }
17917
17918 // Test that shader caching maintains which advanced blending equations (provided by
17919 // GL_KHR_blend_equation_advanced) are used across shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheFragmentWithKHRAdvancedBlendEquations)17920 TEST_P(GLSLTest_ES31, ShaderCacheFragmentWithKHRAdvancedBlendEquations)
17921 {
17922 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_KHR_blend_equation_advanced"));
17923 ANGLE_SKIP_TEST_IF(!IsVulkan());
17924
17925 constexpr char kFS[] = R"(#version 310 es
17926 #extension GL_KHR_blend_equation_advanced : require
17927
17928 layout (blend_support_multiply) out;
17929
17930 precision mediump float;
17931
17932 out vec4 fragColor;
17933
17934 void main()
17935 {
17936 fragColor = vec4(1., 0., 0., 1.);
17937 })";
17938
17939 ANGLE_GL_PROGRAM(unusedProgram, essl31_shaders::vs::Simple(), kFS);
17940 ASSERT_GL_NO_ERROR();
17941 // Delete the shader and recompile to fetch from cache.
17942 glDeleteProgram(unusedProgram);
17943 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
17944 ASSERT_GL_NO_ERROR();
17945 glUseProgram(program);
17946
17947 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
17948 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
17949 }
17950
17951 // Test that shader caching maintains uniforms in geometry shaders across shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheGeometryWithUniform)17952 TEST_P(GLSLTest_ES31, ShaderCacheGeometryWithUniform)
17953 {
17954 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
17955 ANGLE_SKIP_TEST_IF(!IsVulkan());
17956
17957 constexpr char kGS[] = R"(#version 310 es
17958 #extension GL_EXT_geometry_shader : require
17959 precision mediump float;
17960
17961 layout (triangles) in;
17962 layout (triangle_strip, max_vertices = 3) out;
17963
17964 uniform float redInput;
17965
17966 out float redValue;
17967
17968 void main() {
17969 gl_Position = gl_in[0].gl_Position;
17970 redValue = redInput;
17971 EmitVertex();
17972
17973 gl_Position = gl_in[1].gl_Position;
17974 redValue = redInput;
17975 EmitVertex();
17976
17977 gl_Position = gl_in[2].gl_Position;
17978 redValue = redInput;
17979 EmitVertex();
17980
17981 EndPrimitive();
17982 }
17983 )";
17984
17985 constexpr char kFS[] = R"(#version 310 es
17986 precision mediump float;
17987
17988 out vec4 fragColor;
17989
17990 in float redValue;
17991
17992 void main()
17993 {
17994 fragColor = vec4(redValue, 0., 0., 1.);
17995 })";
17996
17997 ANGLE_GL_PROGRAM_WITH_GS(unusedProgram, essl31_shaders::vs::Simple(), kGS, kFS);
17998 ASSERT_GL_NO_ERROR();
17999 // Delete the shader and recompile to fetch from cache.
18000 glDeleteProgram(unusedProgram);
18001 ANGLE_GL_PROGRAM_WITH_GS(program, essl31_shaders::vs::Simple(), kGS, kFS);
18002 ASSERT_GL_NO_ERROR();
18003 glUseProgram(program);
18004
18005 constexpr GLfloat kRedValue = 1.0f;
18006 int redInputLocation = glGetUniformLocation(program, "redInput");
18007 glUniform1f(redInputLocation, kRedValue);
18008 ASSERT_GL_NO_ERROR();
18009
18010 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18011 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18012 }
18013
18014 // Test that shader caching maintains uniform blocks in geometry shaders across shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheGeometryWithUniformBlock)18015 TEST_P(GLSLTest_ES31, ShaderCacheGeometryWithUniformBlock)
18016 {
18017 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
18018 ANGLE_SKIP_TEST_IF(!IsVulkan());
18019
18020 constexpr char kGS[] = R"(#version 310 es
18021 #extension GL_EXT_geometry_shader : require
18022 precision mediump float;
18023
18024 layout (triangles) in;
18025 layout (triangle_strip, max_vertices = 3) out;
18026
18027 layout (std140) uniform Input {
18028 float redInput;
18029 };
18030
18031 out float redValue;
18032
18033 void main() {
18034 gl_Position = gl_in[0].gl_Position;
18035 redValue = redInput;
18036 EmitVertex();
18037
18038 gl_Position = gl_in[1].gl_Position;
18039 redValue = redInput;
18040 EmitVertex();
18041
18042 gl_Position = gl_in[2].gl_Position;
18043 redValue = redInput;
18044 EmitVertex();
18045
18046 EndPrimitive();
18047 }
18048 )";
18049
18050 constexpr char kFS[] = R"(#version 310 es
18051 precision mediump float;
18052
18053 out vec4 fragColor;
18054
18055 in float redValue;
18056
18057 void main()
18058 {
18059 fragColor = vec4(redValue, 0., 0., 1.);
18060 })";
18061
18062 ANGLE_GL_PROGRAM_WITH_GS(unusedProgram, essl31_shaders::vs::Simple(), kGS, kFS);
18063 ASSERT_GL_NO_ERROR();
18064 // Delete the shader and recompile to fetch from cache.
18065 glDeleteProgram(unusedProgram);
18066 ANGLE_GL_PROGRAM_WITH_GS(program, essl31_shaders::vs::Simple(), kGS, kFS);
18067 ASSERT_GL_NO_ERROR();
18068 glUseProgram(program);
18069
18070 constexpr GLfloat kInputData = 1.0f;
18071 GLBuffer input;
18072 glBindBuffer(GL_UNIFORM_BUFFER, input);
18073 glBufferData(GL_UNIFORM_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
18074 const GLuint kInputIndex = glGetUniformBlockIndex(program, "Input");
18075 glUniformBlockBinding(program, kInputIndex, 0);
18076 glBindBufferBase(GL_UNIFORM_BUFFER, 0, input);
18077 glBindBuffer(GL_UNIFORM_BUFFER, 0);
18078 ASSERT_GL_NO_ERROR();
18079
18080 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18081 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18082 }
18083
18084 // Test that shader caching maintains SSBO in geometry shaders across shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheGeometryWithSSBO)18085 TEST_P(GLSLTest_ES31, ShaderCacheGeometryWithSSBO)
18086 {
18087 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
18088 ANGLE_SKIP_TEST_IF(!IsVulkan());
18089 GLint maxGeometryShaderStorageBlocks = 0;
18090 glGetIntegerv(GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT, &maxGeometryShaderStorageBlocks);
18091 ANGLE_SKIP_TEST_IF(maxGeometryShaderStorageBlocks == 0);
18092
18093 constexpr char kGS[] = R"(#version 310 es
18094 #extension GL_EXT_geometry_shader : require
18095 precision mediump float;
18096
18097 layout (triangles) in;
18098 layout (triangle_strip, max_vertices = 3) out;
18099
18100 layout (binding = 0, std430) buffer Input {
18101 float redInput;
18102 };
18103
18104 out float redValue;
18105
18106 void main() {
18107 gl_Position = gl_in[0].gl_Position;
18108 redValue = redInput;
18109 EmitVertex();
18110
18111 gl_Position = gl_in[1].gl_Position;
18112 redValue = redInput;
18113 EmitVertex();
18114
18115 gl_Position = gl_in[2].gl_Position;
18116 redValue = redInput;
18117 EmitVertex();
18118
18119 EndPrimitive();
18120 }
18121 )";
18122
18123 constexpr char kFS[] = R"(#version 310 es
18124 precision mediump float;
18125
18126 out vec4 fragColor;
18127
18128 in float redValue;
18129
18130 void main()
18131 {
18132 fragColor = vec4(redValue, 0., 0., 1.);
18133 })";
18134
18135 ANGLE_GL_PROGRAM_WITH_GS(unusedProgram, essl31_shaders::vs::Simple(), kGS, kFS);
18136 ASSERT_GL_NO_ERROR();
18137 // Delete the shader and recompile to fetch from cache.
18138 glDeleteProgram(unusedProgram);
18139 ANGLE_GL_PROGRAM_WITH_GS(program, essl31_shaders::vs::Simple(), kGS, kFS);
18140 ASSERT_GL_NO_ERROR();
18141 glUseProgram(program);
18142
18143 constexpr GLfloat kInputData = 1.0f;
18144 GLBuffer input;
18145 glBindBuffer(GL_SHADER_STORAGE_BUFFER, input);
18146 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
18147 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, input);
18148 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
18149 ASSERT_GL_NO_ERROR();
18150
18151 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18152 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18153 }
18154
18155 // Test that shader caching maintains the number of invocations in geometry shaders across shader
18156 // compilations.
TEST_P(GLSLTest_ES31,ShaderCacheGeometryWithInvocations)18157 TEST_P(GLSLTest_ES31, ShaderCacheGeometryWithInvocations)
18158 {
18159 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
18160 ANGLE_SKIP_TEST_IF(!IsVulkan());
18161
18162 constexpr char kGS[] = R"(#version 310 es
18163 #extension GL_EXT_geometry_shader : require
18164 precision mediump float;
18165
18166 layout (triangles, invocations = 2) in;
18167 layout (triangle_strip, max_vertices = 3) out;
18168
18169 out float redValue;
18170
18171 void main() {
18172 float redOut = 0.;
18173 if (gl_InvocationID == 1) {
18174 redOut = 1.;
18175 }
18176
18177 gl_Position = gl_in[0].gl_Position;
18178 redValue = redOut;
18179 EmitVertex();
18180
18181 gl_Position = gl_in[1].gl_Position;
18182 redValue = redOut;
18183 EmitVertex();
18184
18185 gl_Position = gl_in[2].gl_Position;
18186 redValue = redOut;
18187 EmitVertex();
18188
18189 EndPrimitive();
18190 }
18191 )";
18192
18193 constexpr char kFS[] = R"(#version 310 es
18194 precision mediump float;
18195
18196 out vec4 fragColor;
18197
18198 in float redValue;
18199
18200 void main()
18201 {
18202 fragColor = vec4(redValue, 0., 0., 1.);
18203 })";
18204
18205 ANGLE_GL_PROGRAM_WITH_GS(unusedProgram, essl31_shaders::vs::Simple(), kGS, kFS);
18206 ASSERT_GL_NO_ERROR();
18207 // Delete the shader and recompile to fetch from cache.
18208 glDeleteProgram(unusedProgram);
18209 ANGLE_GL_PROGRAM_WITH_GS(program, essl31_shaders::vs::Simple(), kGS, kFS);
18210 ASSERT_GL_NO_ERROR();
18211 glUseProgram(program);
18212
18213 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18214 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18215 }
18216
18217 // Test that shader caching maintains uniforms in tessellation control shaders across shader
18218 // compilations.
TEST_P(GLSLTest_ES31,ShaderCacheTessellationControlWithUniform)18219 TEST_P(GLSLTest_ES31, ShaderCacheTessellationControlWithUniform)
18220 {
18221 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
18222 ANGLE_SKIP_TEST_IF(!IsVulkan());
18223
18224 constexpr char kTCS[] = R"(#version 310 es
18225 #extension GL_EXT_tessellation_shader : require
18226 precision mediump float;
18227
18228 layout (vertices = 1) out;
18229
18230 uniform float redInput;
18231
18232 patch out float redValueCS;
18233
18234 void main()
18235 {
18236 gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
18237 gl_TessLevelInner[0] = 1.0;
18238 gl_TessLevelInner[1] = 1.0;
18239 gl_TessLevelOuter[0] = 1.0;
18240 gl_TessLevelOuter[1] = 1.0;
18241 gl_TessLevelOuter[2] = 1.0;
18242 gl_TessLevelOuter[3] = 1.0;
18243
18244 redValueCS = redInput;
18245 }
18246
18247 )";
18248
18249 constexpr char kTES[] = R"(#version 310 es
18250 #extension GL_EXT_tessellation_shader : require
18251 precision mediump float;
18252
18253 layout (quads, cw, fractional_odd_spacing) in;
18254
18255 patch in float redValueCS;
18256
18257 out float redValue;
18258
18259 void main()
18260 {
18261 gl_Position = vec4(gl_TessCoord.xy * 2. - 1., 0, 1);
18262
18263 redValue = redValueCS;
18264 }
18265 )";
18266
18267 constexpr char kFS[] = R"(#version 310 es
18268 precision mediump float;
18269
18270 out vec4 fragColor;
18271
18272 in float redValue;
18273
18274 void main()
18275 {
18276 fragColor = vec4(redValue, 0., 0., 1.);
18277 })";
18278
18279 ANGLE_GL_PROGRAM_WITH_TESS(unusedProgram, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
18280 ASSERT_GL_NO_ERROR();
18281 // Delete the shader and recompile to fetch from cache.
18282 glDeleteProgram(unusedProgram);
18283 ANGLE_GL_PROGRAM_WITH_TESS(program, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
18284 ASSERT_GL_NO_ERROR();
18285 glUseProgram(program);
18286
18287 constexpr GLfloat kRedValue = 1.0f;
18288 int redInputLocation = glGetUniformLocation(program, "redInput");
18289 glUniform1f(redInputLocation, kRedValue);
18290 ASSERT_GL_NO_ERROR();
18291
18292 drawPatches(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, GL_FALSE);
18293 ASSERT_GL_NO_ERROR();
18294
18295 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18296 }
18297
18298 // Test that shader caching maintains uniform blocks in tessellation control shaders across shader
18299 // compilations.
TEST_P(GLSLTest_ES31,ShaderCacheTessellationControlWithUniformBlock)18300 TEST_P(GLSLTest_ES31, ShaderCacheTessellationControlWithUniformBlock)
18301 {
18302 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
18303 ANGLE_SKIP_TEST_IF(!IsVulkan());
18304
18305 constexpr char kTCS[] = R"(#version 310 es
18306 #extension GL_EXT_tessellation_shader : require
18307 precision mediump float;
18308
18309 layout (vertices = 1) out;
18310
18311 layout (std140) uniform Input {
18312 float redInput;
18313 };
18314
18315 patch out float redValueCS;
18316
18317 void main()
18318 {
18319 gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
18320 gl_TessLevelInner[0] = 1.0;
18321 gl_TessLevelInner[1] = 1.0;
18322 gl_TessLevelOuter[0] = 1.0;
18323 gl_TessLevelOuter[1] = 1.0;
18324 gl_TessLevelOuter[2] = 1.0;
18325 gl_TessLevelOuter[3] = 1.0;
18326
18327 redValueCS = redInput;
18328 }
18329
18330 )";
18331
18332 constexpr char kTES[] = R"(#version 310 es
18333 #extension GL_EXT_tessellation_shader : require
18334 precision mediump float;
18335
18336 layout (quads, cw, fractional_odd_spacing) in;
18337
18338 patch in float redValueCS;
18339
18340 out float redValue;
18341
18342 void main()
18343 {
18344 gl_Position = vec4(gl_TessCoord.xy * 2. - 1., 0, 1);
18345
18346 redValue = redValueCS;
18347 }
18348 )";
18349
18350 constexpr char kFS[] = R"(#version 310 es
18351 precision mediump float;
18352
18353 out vec4 fragColor;
18354
18355 in float redValue;
18356
18357 void main()
18358 {
18359 fragColor = vec4(redValue, 0., 0., 1.);
18360 })";
18361
18362 ANGLE_GL_PROGRAM_WITH_TESS(unusedProgram, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
18363 ASSERT_GL_NO_ERROR();
18364 // Delete the shader and recompile to fetch from cache.
18365 glDeleteProgram(unusedProgram);
18366 ANGLE_GL_PROGRAM_WITH_TESS(program, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
18367 ASSERT_GL_NO_ERROR();
18368 glUseProgram(program);
18369
18370 constexpr GLfloat kInputData = 1.0f;
18371 GLBuffer input;
18372 glBindBuffer(GL_UNIFORM_BUFFER, input);
18373 glBufferData(GL_UNIFORM_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
18374 const GLuint kInputIndex = glGetUniformBlockIndex(program, "Input");
18375 glUniformBlockBinding(program, kInputIndex, 0);
18376 glBindBufferBase(GL_UNIFORM_BUFFER, 0, input);
18377 glBindBuffer(GL_UNIFORM_BUFFER, 0);
18378 ASSERT_GL_NO_ERROR();
18379
18380 drawPatches(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, GL_FALSE);
18381 ASSERT_GL_NO_ERROR();
18382
18383 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18384 }
18385
18386 // Test that shader caching maintains SSBOs in tessellation control shaders across shader
18387 // compilations.
TEST_P(GLSLTest_ES31,ShaderCacheTessellationControlWithSSBO)18388 TEST_P(GLSLTest_ES31, ShaderCacheTessellationControlWithSSBO)
18389 {
18390 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
18391 ANGLE_SKIP_TEST_IF(!IsVulkan());
18392 GLint maxTessControlShaderStorageBlocks;
18393 glGetIntegerv(GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS_EXT,
18394 &maxTessControlShaderStorageBlocks);
18395 ANGLE_SKIP_TEST_IF(maxTessControlShaderStorageBlocks == 0);
18396
18397 constexpr char kTCS[] = R"(#version 310 es
18398 #extension GL_EXT_tessellation_shader : require
18399 precision mediump float;
18400
18401 layout (vertices = 1) out;
18402
18403 layout (binding = 0, std430) buffer Input {
18404 float redInput;
18405 };
18406
18407 patch out float redValueCS;
18408
18409 void main()
18410 {
18411 gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
18412 gl_TessLevelInner[0] = 1.0;
18413 gl_TessLevelInner[1] = 1.0;
18414 gl_TessLevelOuter[0] = 1.0;
18415 gl_TessLevelOuter[1] = 1.0;
18416 gl_TessLevelOuter[2] = 1.0;
18417 gl_TessLevelOuter[3] = 1.0;
18418
18419 redValueCS = redInput;
18420 }
18421
18422 )";
18423
18424 constexpr char kTES[] = R"(#version 310 es
18425 #extension GL_EXT_tessellation_shader : require
18426 precision mediump float;
18427
18428 layout (quads, cw, fractional_odd_spacing) in;
18429
18430 patch in float redValueCS;
18431
18432 out float redValue;
18433
18434 void main()
18435 {
18436 gl_Position = vec4(gl_TessCoord.xy * 2. - 1., 0, 1);
18437
18438 redValue = redValueCS;
18439 }
18440 )";
18441
18442 constexpr char kFS[] = R"(#version 310 es
18443 precision mediump float;
18444
18445 out vec4 fragColor;
18446
18447 in float redValue;
18448
18449 void main()
18450 {
18451 fragColor = vec4(redValue, 0., 0., 1.);
18452 })";
18453
18454 ANGLE_GL_PROGRAM_WITH_TESS(unusedProgram, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
18455 ASSERT_GL_NO_ERROR();
18456 // Delete the shader and recompile to fetch from cache.
18457 glDeleteProgram(unusedProgram);
18458 ANGLE_GL_PROGRAM_WITH_TESS(program, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
18459 ASSERT_GL_NO_ERROR();
18460 glUseProgram(program);
18461
18462 constexpr GLfloat kInputData = 1.0f;
18463 GLBuffer input;
18464 glBindBuffer(GL_SHADER_STORAGE_BUFFER, input);
18465 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
18466 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, input);
18467 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
18468 ASSERT_GL_NO_ERROR();
18469
18470 drawPatches(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, GL_FALSE);
18471 ASSERT_GL_NO_ERROR();
18472
18473 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18474 }
18475
18476 // Test that shader caching maintains uniforms in tessellation evaluation shaders across shader
18477 // compilations.
TEST_P(GLSLTest_ES31,ShaderCacheTessellationEvalWithUniform)18478 TEST_P(GLSLTest_ES31, ShaderCacheTessellationEvalWithUniform)
18479 {
18480 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
18481 ANGLE_SKIP_TEST_IF(!IsVulkan());
18482
18483 constexpr char kTCS[] = R"(#version 310 es
18484 #extension GL_EXT_tessellation_shader : require
18485 precision mediump float;
18486
18487 layout (vertices = 1) out;
18488
18489 void main()
18490 {
18491 gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
18492 gl_TessLevelInner[0] = 1.0;
18493 gl_TessLevelInner[1] = 1.0;
18494 gl_TessLevelOuter[0] = 1.0;
18495 gl_TessLevelOuter[1] = 1.0;
18496 gl_TessLevelOuter[2] = 1.0;
18497 gl_TessLevelOuter[3] = 1.0;
18498 }
18499
18500 )";
18501
18502 constexpr char kTES[] = R"(#version 310 es
18503 #extension GL_EXT_tessellation_shader : require
18504 precision mediump float;
18505
18506 layout (quads, cw, fractional_odd_spacing) in;
18507
18508 uniform float redInput;
18509
18510 out float redValue;
18511
18512 void main()
18513 {
18514 gl_Position = vec4(gl_TessCoord.xy * 2. - 1., 0, 1);
18515
18516 redValue = redInput;
18517 }
18518 )";
18519
18520 constexpr char kFS[] = R"(#version 310 es
18521 precision mediump float;
18522
18523 out vec4 fragColor;
18524
18525 in float redValue;
18526
18527 void main()
18528 {
18529 fragColor = vec4(redValue, 0., 0., 1.);
18530 })";
18531
18532 ANGLE_GL_PROGRAM_WITH_TESS(unusedProgram, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
18533 ASSERT_GL_NO_ERROR();
18534 // Delete the shader and recompile to fetch from cache.
18535 glDeleteProgram(unusedProgram);
18536 ANGLE_GL_PROGRAM_WITH_TESS(program, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
18537 ASSERT_GL_NO_ERROR();
18538 glUseProgram(program);
18539
18540 constexpr GLfloat kRedValue = 1.0f;
18541 int redInputLocation = glGetUniformLocation(program, "redInput");
18542 glUniform1f(redInputLocation, kRedValue);
18543 ASSERT_GL_NO_ERROR();
18544
18545 drawPatches(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, GL_FALSE);
18546 ASSERT_GL_NO_ERROR();
18547
18548 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18549 }
18550
18551 // Test that shader caching maintains uniform blocks in tessellation evaluation shaders across
18552 // shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheTessellationEvalWithUniformBlock)18553 TEST_P(GLSLTest_ES31, ShaderCacheTessellationEvalWithUniformBlock)
18554 {
18555 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
18556 ANGLE_SKIP_TEST_IF(!IsVulkan());
18557
18558 constexpr char kTCS[] = R"(#version 310 es
18559 #extension GL_EXT_tessellation_shader : require
18560 precision mediump float;
18561
18562 layout (vertices = 1) out;
18563
18564 void main()
18565 {
18566 gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
18567 gl_TessLevelInner[0] = 1.0;
18568 gl_TessLevelInner[1] = 1.0;
18569 gl_TessLevelOuter[0] = 1.0;
18570 gl_TessLevelOuter[1] = 1.0;
18571 gl_TessLevelOuter[2] = 1.0;
18572 gl_TessLevelOuter[3] = 1.0;
18573 }
18574
18575 )";
18576
18577 constexpr char kTES[] = R"(#version 310 es
18578 #extension GL_EXT_tessellation_shader : require
18579 precision mediump float;
18580
18581 layout (quads, cw, fractional_odd_spacing) in;
18582
18583 layout (std140) uniform Input {
18584 float redInput;
18585 };
18586
18587 out float redValue;
18588
18589 void main()
18590 {
18591 gl_Position = vec4(gl_TessCoord.xy * 2. - 1., 0, 1);
18592
18593 redValue = redInput;
18594 }
18595 )";
18596
18597 constexpr char kFS[] = R"(#version 310 es
18598 precision mediump float;
18599
18600 out vec4 fragColor;
18601
18602 in float redValue;
18603
18604 void main()
18605 {
18606 fragColor = vec4(redValue, 0., 0., 1.);
18607 })";
18608
18609 ANGLE_GL_PROGRAM_WITH_TESS(unusedProgram, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
18610 ASSERT_GL_NO_ERROR();
18611 // Delete the shader and recompile to fetch from cache.
18612 glDeleteProgram(unusedProgram);
18613 ANGLE_GL_PROGRAM_WITH_TESS(program, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
18614 ASSERT_GL_NO_ERROR();
18615 glUseProgram(program);
18616
18617 constexpr GLfloat kInputData = 1.0f;
18618 GLBuffer input;
18619 glBindBuffer(GL_UNIFORM_BUFFER, input);
18620 glBufferData(GL_UNIFORM_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
18621 const GLuint kInputIndex = glGetUniformBlockIndex(program, "Input");
18622 glUniformBlockBinding(program, kInputIndex, 0);
18623 glBindBufferBase(GL_UNIFORM_BUFFER, 0, input);
18624 glBindBuffer(GL_UNIFORM_BUFFER, 0);
18625 ASSERT_GL_NO_ERROR();
18626
18627 drawPatches(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, GL_FALSE);
18628 ASSERT_GL_NO_ERROR();
18629
18630 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18631 }
18632
18633 // Test that shader caching maintains SSBOs in tessellation evaluation shaders across shader
18634 // compilations.
TEST_P(GLSLTest_ES31,ShaderCacheTessellationEvalWithSSBO)18635 TEST_P(GLSLTest_ES31, ShaderCacheTessellationEvalWithSSBO)
18636 {
18637 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
18638 ANGLE_SKIP_TEST_IF(!IsVulkan());
18639 GLint maxTessEvalShaderStorageBlocks;
18640 glGetIntegerv(GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS_EXT,
18641 &maxTessEvalShaderStorageBlocks);
18642 ANGLE_SKIP_TEST_IF(maxTessEvalShaderStorageBlocks == 0);
18643
18644 constexpr char kTCS[] = R"(#version 310 es
18645 #extension GL_EXT_tessellation_shader : require
18646 precision mediump float;
18647
18648 layout (vertices = 1) out;
18649
18650 void main()
18651 {
18652 gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
18653 gl_TessLevelInner[0] = 1.0;
18654 gl_TessLevelInner[1] = 1.0;
18655 gl_TessLevelOuter[0] = 1.0;
18656 gl_TessLevelOuter[1] = 1.0;
18657 gl_TessLevelOuter[2] = 1.0;
18658 gl_TessLevelOuter[3] = 1.0;
18659 }
18660
18661 )";
18662
18663 constexpr char kTES[] = R"(#version 310 es
18664 #extension GL_EXT_tessellation_shader : require
18665 precision mediump float;
18666
18667 layout (quads, cw, fractional_odd_spacing) in;
18668
18669 layout (binding = 0, std430) buffer Input {
18670 float redInput;
18671 };
18672
18673 out float redValue;
18674
18675 void main()
18676 {
18677 gl_Position = vec4(gl_TessCoord.xy * 2. - 1., 0, 1);
18678
18679 redValue = redInput;
18680 }
18681 )";
18682
18683 constexpr char kFS[] = R"(#version 310 es
18684 precision mediump float;
18685
18686 out vec4 fragColor;
18687
18688 in float redValue;
18689
18690 void main()
18691 {
18692 fragColor = vec4(redValue, 0., 0., 1.);
18693 })";
18694
18695 ANGLE_GL_PROGRAM_WITH_TESS(unusedProgram, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
18696 ASSERT_GL_NO_ERROR();
18697 // Delete the shader and recompile to fetch from cache.
18698 glDeleteProgram(unusedProgram);
18699 ANGLE_GL_PROGRAM_WITH_TESS(program, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
18700 ASSERT_GL_NO_ERROR();
18701 glUseProgram(program);
18702
18703 constexpr GLfloat kInputData = 1.0f;
18704 GLBuffer input;
18705 glBindBuffer(GL_SHADER_STORAGE_BUFFER, input);
18706 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
18707 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, input);
18708 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
18709 ASSERT_GL_NO_ERROR();
18710
18711 drawPatches(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, GL_FALSE);
18712 ASSERT_GL_NO_ERROR();
18713
18714 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18715 }
18716
18717 // Test that only macros for ESSL 1.0 compatible extensions are defined
TEST_P(GLSLTest,ESSL1ExtensionMacros)18718 TEST_P(GLSLTest, ESSL1ExtensionMacros)
18719 {
18720 std::string fs = essl1_shaders::fs::Red();
18721 fs += ExpectedExtensionMacros({
18722 "GL_ANGLE_multi_draw",
18723 "GL_APPLE_clip_distance",
18724 "GL_ARB_texture_rectangle",
18725 "GL_ARM_shader_framebuffer_fetch",
18726 "GL_EXT_blend_func_extended",
18727 "GL_EXT_draw_buffers",
18728 "GL_EXT_frag_depth",
18729 "GL_EXT_separate_shader_objects",
18730 "GL_EXT_shader_framebuffer_fetch_non_coherent",
18731 "GL_EXT_shader_framebuffer_fetch",
18732 "GL_EXT_shader_non_constant_global_initializers",
18733 "GL_EXT_shader_texture_lod",
18734 "GL_EXT_shadow_samplers",
18735 "GL_KHR_blend_equation_advanced",
18736 "GL_NV_EGL_stream_consumer_external",
18737 "GL_NV_shader_framebuffer_fetch",
18738 "GL_OES_EGL_image_external",
18739 "GL_OES_standard_derivatives",
18740 "GL_OES_texture_3D",
18741 "GL_WEBGL_video_texture",
18742 });
18743 fs += UnexpectedExtensionMacros({
18744 "GL_ANDROID_extension_pack_es31a",
18745 "GL_ANGLE_base_vertex_base_instance_shader_builtin",
18746 "GL_ANGLE_clip_cull_distance",
18747 "GL_ANGLE_shader_pixel_local_storage",
18748 "GL_ANGLE_texture_multisample",
18749 "GL_EXT_clip_cull_distance",
18750 "GL_EXT_geometry_shader",
18751 "GL_EXT_gpu_shader5",
18752 "GL_EXT_primitive_bounding_box",
18753 "GL_EXT_shader_io_blocks",
18754 "GL_EXT_tessellation_shader",
18755 "GL_EXT_texture_buffer",
18756 "GL_EXT_texture_cube_map_array",
18757 "GL_EXT_YUV_target",
18758 "GL_NV_shader_noperspective_interpolation",
18759 "GL_OES_EGL_image_external_essl3",
18760 "GL_OES_geometry_shader",
18761 "GL_OES_primitive_bounding_box",
18762 "GL_OES_sample_variables",
18763 "GL_OES_shader_image_atomic",
18764 "GL_OES_shader_io_blocks",
18765 "GL_OES_shader_multisample_interpolation",
18766 "GL_OES_texture_buffer",
18767 "GL_OES_texture_cube_map_array",
18768 "GL_OES_texture_storage_multisample_2d_array",
18769 "GL_OVR_multiview",
18770 "GL_OVR_multiview2",
18771 });
18772 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), fs.c_str());
18773 ASSERT_GL_NO_ERROR();
18774 }
18775
18776 // Test that only macros for ESSL 3.0 compatible extensions are defined
TEST_P(GLSLTest_ES3,ESSL3ExtensionMacros)18777 TEST_P(GLSLTest_ES3, ESSL3ExtensionMacros)
18778 {
18779 std::string fs = essl3_shaders::fs::Red();
18780 fs += ExpectedExtensionMacros({
18781 "GL_ANGLE_base_vertex_base_instance_shader_builtin",
18782 "GL_ANGLE_clip_cull_distance",
18783 "GL_ANGLE_multi_draw",
18784 "GL_ANGLE_shader_pixel_local_storage",
18785 "GL_ANGLE_texture_multisample",
18786 "GL_APPLE_clip_distance",
18787 "GL_ARB_texture_rectangle",
18788 "GL_ARM_shader_framebuffer_fetch",
18789 "GL_EXT_blend_func_extended",
18790 "GL_EXT_clip_cull_distance",
18791 "GL_EXT_separate_shader_objects",
18792 "GL_EXT_shader_framebuffer_fetch_non_coherent",
18793 "GL_EXT_shader_framebuffer_fetch",
18794 "GL_EXT_shader_non_constant_global_initializers",
18795 "GL_EXT_YUV_target",
18796 "GL_KHR_blend_equation_advanced",
18797 "GL_NV_EGL_stream_consumer_external",
18798 "GL_NV_shader_noperspective_interpolation",
18799 // Enabled on ESSL 3+ to workaround app bug. http://issuetracker.google.com/285871779
18800 "GL_OES_EGL_image_external",
18801 "GL_OES_EGL_image_external_essl3",
18802 // Enabled on ESSL 3+ to workaround app bug. http://issuetracker.google.com/285871779
18803 "GL_OES_texture_3D",
18804 "GL_OES_sample_variables",
18805 "GL_OES_shader_multisample_interpolation",
18806 "GL_OVR_multiview",
18807 "GL_OVR_multiview2",
18808 "GL_WEBGL_video_texture",
18809 });
18810 fs += UnexpectedExtensionMacros({
18811 "GL_ANDROID_extension_pack_es31a",
18812 "GL_EXT_draw_buffers",
18813 "GL_EXT_frag_depth",
18814 "GL_EXT_geometry_shader",
18815 "GL_EXT_gpu_shader5",
18816 "GL_EXT_primitive_bounding_box",
18817 "GL_EXT_shader_io_blocks",
18818 "GL_EXT_shader_texture_lod",
18819 "GL_EXT_shadow_samplers",
18820 "GL_EXT_tessellation_shader",
18821 "GL_EXT_texture_buffer",
18822 "GL_EXT_texture_cube_map_array",
18823 "GL_NV_shader_framebuffer_fetch",
18824 "GL_OES_geometry_shader",
18825 "GL_OES_primitive_bounding_box",
18826 "GL_OES_shader_image_atomic",
18827 "GL_OES_shader_io_blocks",
18828 "GL_OES_standard_derivatives",
18829 "GL_OES_texture_buffer",
18830 "GL_OES_texture_cube_map_array",
18831 "GL_OES_texture_storage_multisample_2d_array",
18832 });
18833 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fs.c_str());
18834 ASSERT_GL_NO_ERROR();
18835 }
18836
18837 // Test that only macros for ESSL 3.1 compatible extensions are defined
TEST_P(GLSLTest_ES31,ESSL31ExtensionMacros)18838 TEST_P(GLSLTest_ES31, ESSL31ExtensionMacros)
18839 {
18840 std::string fs = essl31_shaders::fs::Red();
18841 fs += ExpectedExtensionMacros({
18842 "GL_ANDROID_extension_pack_es31a",
18843 "GL_ANGLE_base_vertex_base_instance_shader_builtin",
18844 "GL_ANGLE_clip_cull_distance",
18845 "GL_ANGLE_multi_draw",
18846 "GL_ANGLE_shader_pixel_local_storage",
18847 "GL_ANGLE_texture_multisample",
18848 "GL_APPLE_clip_distance",
18849 "GL_ARB_texture_rectangle",
18850 "GL_ARM_shader_framebuffer_fetch",
18851 "GL_EXT_blend_func_extended",
18852 "GL_EXT_clip_cull_distance",
18853 "GL_EXT_geometry_shader",
18854 "GL_EXT_gpu_shader5",
18855 "GL_EXT_primitive_bounding_box",
18856 "GL_EXT_separate_shader_objects",
18857 "GL_EXT_shader_framebuffer_fetch_non_coherent",
18858 "GL_EXT_shader_framebuffer_fetch",
18859 "GL_EXT_shader_io_blocks",
18860 "GL_EXT_shader_non_constant_global_initializers",
18861 "GL_EXT_tessellation_shader",
18862 "GL_EXT_texture_buffer",
18863 "GL_EXT_texture_cube_map_array",
18864 "GL_EXT_YUV_target",
18865 "GL_KHR_blend_equation_advanced",
18866 "GL_NV_EGL_stream_consumer_external",
18867 "GL_NV_shader_noperspective_interpolation",
18868 // Enabled on ESSL 3+ to workaround app bug. http://issuetracker.google.com/285871779
18869 "GL_OES_EGL_image_external",
18870 "GL_OES_EGL_image_external_essl3",
18871 // Enabled on ESSL 3+ to workaround app bug. http://issuetracker.google.com/285871779
18872 "GL_OES_texture_3D",
18873 "GL_OES_geometry_shader",
18874 "GL_OES_primitive_bounding_box",
18875 "GL_OES_sample_variables",
18876 "GL_OES_shader_image_atomic",
18877 "GL_OES_shader_io_blocks",
18878 "GL_OES_shader_multisample_interpolation",
18879 "GL_OES_texture_buffer",
18880 "GL_OES_texture_cube_map_array",
18881 "GL_OES_texture_storage_multisample_2d_array",
18882 "GL_OVR_multiview",
18883 "GL_OVR_multiview2",
18884 "GL_WEBGL_video_texture",
18885 });
18886 fs += UnexpectedExtensionMacros({
18887 "GL_EXT_draw_buffers",
18888 "GL_EXT_frag_depth",
18889 "GL_EXT_shader_texture_lod",
18890 "GL_EXT_shadow_samplers",
18891 "GL_NV_shader_framebuffer_fetch",
18892 "GL_OES_standard_derivatives",
18893 });
18894 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), fs.c_str());
18895 ASSERT_GL_NO_ERROR();
18896 }
18897
18898 // Make sure names starting with webgl_ work.
TEST_P(GLSLTest_ES3,NameWithWebgl)18899 TEST_P(GLSLTest_ES3, NameWithWebgl)
18900 {
18901 constexpr char kFS[] = R"(#version 300 es
18902 out highp vec4 webgl_color;
18903 void main()
18904 {
18905 webgl_color = vec4(0, 1, 0, 1);
18906 })";
18907
18908 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
18909 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18910 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
18911 }
18912
18913 // Make sure webgl_FragColor works.
TEST_P(GLSLTest_ES3,NameWithWebglFragColor)18914 TEST_P(GLSLTest_ES3, NameWithWebglFragColor)
18915 {
18916 constexpr char kFS[] = R"(#version 300 es
18917 out highp vec4 webgl_FragColor;
18918 void main()
18919 {
18920 webgl_FragColor = vec4(0, 1, 0, 1);
18921 })";
18922
18923 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
18924 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18925 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
18926 }
18927
18928 // Test that the ScalarizeVecAndMatConstructorArgs workaround works correctly with constructors that
18929 // have no precision. Regression test for a bug where the generated helper has no precision
18930 // specified on the parameters and return value.
TEST_P(GLSLTest,ScalarizeVectorWorkaroundVsPrecisionlessConstructor)18931 TEST_P(GLSLTest, ScalarizeVectorWorkaroundVsPrecisionlessConstructor)
18932 {
18933 constexpr char kFS[] = R"(precision highp float;
18934 void main() {
18935 bool b1 = true;
18936 float f1 = dot(vec4(b1 ? 1.0 : 0.0, 0.0, 0.0, 0.0), vec4(1.0));
18937 gl_FragColor = vec4(f1,0.0,0.0, 1.0);
18938 })";
18939
18940 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
18941 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18942 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18943 }
18944
18945 // Test that Metal compiler doesn't inline non-const globals
TEST_P(WebGLGLSLTest,InvalidGlobalsNotInlined)18946 TEST_P(WebGLGLSLTest, InvalidGlobalsNotInlined)
18947 {
18948 constexpr char kFS[] = R"(#version 100
18949 precision highp float;
18950 float v1 = 0.5;
18951 float v2 = v1;
18952
18953 float f1() {
18954 return v2;
18955 }
18956
18957 void main() {
18958 gl_FragColor = vec4(v1 + f1(),0.0,0.0, 1.0);
18959 })";
18960 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
18961 ASSERT_GL_NO_ERROR();
18962 }
18963
18964 // Test that a struct can have lots of fields. Regression test for an inefficient O(n^2) check for
18965 // fields having unique names.
TEST_P(GLSLTest_ES3,LotsOfFieldsInStruct)18966 TEST_P(GLSLTest_ES3, LotsOfFieldsInStruct)
18967 {
18968 std::ostringstream fs;
18969 fs << R"(#version 300 es
18970 precision highp float;
18971 struct LotsOfFields
18972 {
18973 )";
18974 // Note: 16383 is the SPIR-V limit for struct member count.
18975 for (uint32_t i = 0; i < 16383; ++i)
18976 {
18977 fs << " float field" << i << ";\n";
18978 }
18979 fs << R"(};
18980 uniform B { LotsOfFields s; };
18981 out vec4 color;
18982 void main() {
18983 color = vec4(s.field0, 0.0, 0.0, 1.0);
18984 })";
18985
18986 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fs.str().c_str());
18987 }
18988
18989 // Test that structs with too many fields are rejected. In SPIR-V, the instruction that defines the
18990 // struct lists the fields which means the length of the instruction is a function of the field
18991 // count. Since SPIR-V instruction sizes are limited to 16 bits, structs with more fields cannot be
18992 // represented.
TEST_P(GLSLTest_ES3,TooManyFieldsInStruct)18993 TEST_P(GLSLTest_ES3, TooManyFieldsInStruct)
18994 {
18995 std::ostringstream fs;
18996 fs << R"(#version 300 es
18997 precision highp float;
18998 struct TooManyFields
18999 {
19000 )";
19001 for (uint32_t i = 0; i < (1 << 16); ++i)
19002 {
19003 fs << " float field" << i << ";\n";
19004 }
19005 fs << R"(};
19006 uniform B { TooManyFields s; };
19007 out vec4 color;
19008 void main() {
19009 color = vec4(s.field0, 0.0, 0.0, 1.0);
19010 })";
19011
19012 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, fs.str().c_str());
19013 EXPECT_EQ(0u, shader);
19014 }
19015
19016 // Same as TooManyFieldsInStruct, but with samplers in the struct.
TEST_P(GLSLTest_ES3,TooManySamplerFieldsInStruct)19017 TEST_P(GLSLTest_ES3, TooManySamplerFieldsInStruct)
19018 {
19019 std::ostringstream fs;
19020 fs << R"(#version 300 es
19021 precision highp float;
19022 struct TooManyFields
19023 {
19024 )";
19025 for (uint32_t i = 0; i < (1 << 16); ++i)
19026 {
19027 fs << " sampler2D field" << i << ";\n";
19028 }
19029 fs << R"(};
19030 uniform TooManyFields s;
19031 out vec4 color;
19032 void main() {
19033 color = texture(s.field0, vec2(0));
19034 })";
19035
19036 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, fs.str().c_str());
19037 EXPECT_EQ(0u, shader);
19038 }
19039
19040 // More complex variation of ManySamplerFieldsInStruct. This one compiles fine.
TEST_P(GLSLTest_ES3,ManySamplerFieldsInStructComplex)19041 TEST_P(GLSLTest_ES3, ManySamplerFieldsInStructComplex)
19042 {
19043 // D3D and OpenGL may be more restrictive about this many samplers.
19044 ANGLE_SKIP_TEST_IF(IsD3D() || IsOpenGL());
19045
19046 std::ostringstream fs;
19047 fs << R"(#version 300 es
19048 precision highp float;
19049
19050 struct X {
19051 mediump sampler2D a[0xf00];
19052 mediump sampler2D b[0xf00];
19053 mediump sampler2D c[0xf000];
19054 mediump sampler2D d[0xf00];
19055 };
19056
19057 struct Y {
19058 X s1;
19059 mediump sampler2D a[0xf00];
19060 mediump sampler2D b[0xf000];
19061 mediump sampler2D c[0x14000];
19062 };
19063
19064 struct S {
19065 Y s1;
19066 };
19067
19068 struct structBuffer { S s; };
19069
19070 uniform structBuffer b;
19071
19072 out vec4 color;
19073 void main()
19074 {
19075 color = texture(b.s.s1.s1.c[0], vec2(0));
19076 })";
19077
19078 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, fs.str().c_str());
19079 EXPECT_NE(0u, shader);
19080 }
19081
19082 // Make sure a large array of samplers works.
TEST_P(GLSLTest,ManySamplers)19083 TEST_P(GLSLTest, ManySamplers)
19084 {
19085 // D3D and OpenGL may be more restrictive about this many samplers.
19086 ANGLE_SKIP_TEST_IF(IsD3D() || IsOpenGL());
19087
19088 std::ostringstream fs;
19089 fs << R"(precision highp float;
19090
19091 uniform mediump sampler2D c[0x12000];
19092
19093 void main()
19094 {
19095 gl_FragColor = texture2D(c[0], vec2(0));
19096 })";
19097
19098 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, fs.str().c_str());
19099 EXPECT_NE(0u, shader);
19100 }
19101
19102 // Make sure a large array of samplers works when declared in a struct.
TEST_P(GLSLTest,ManySamplersInStruct)19103 TEST_P(GLSLTest, ManySamplersInStruct)
19104 {
19105 // D3D and OpenGL may be more restrictive about this many samplers.
19106 ANGLE_SKIP_TEST_IF(IsD3D() || IsOpenGL());
19107
19108 std::ostringstream fs;
19109 fs << R"(precision highp float;
19110
19111 struct X {
19112 mediump sampler2D c[0x12000];
19113 };
19114
19115 uniform X x;
19116
19117 void main()
19118 {
19119 gl_FragColor = texture2D(x.c[0], vec2(0));
19120 })";
19121
19122 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, fs.str().c_str());
19123 EXPECT_NE(0u, shader);
19124 }
19125
19126 // Test that passing large arrays to functions are compiled correctly. Regression test for the
19127 // SPIR-V generator that made a copy of the array to pass to the function, by decomposing and
19128 // reconstructing it (in the absence of OpCopyLogical), but the reconstruction instruction has a
19129 // length higher than can fit in SPIR-V.
TEST_P(GLSLTest_ES3,LargeInterfaceBlockArrayPassedToFunction)19130 TEST_P(GLSLTest_ES3, LargeInterfaceBlockArrayPassedToFunction)
19131 {
19132 constexpr char kFS[] = R"(#version 300 es
19133 precision highp float;
19134 uniform Large { float a[65536]; };
19135 float f(float b[65536])
19136 {
19137 b[0] = 1.0;
19138 return b[0] + b[1];
19139 }
19140 out vec4 color;
19141 void main() {
19142 color = vec4(f(a), 0.0, 0.0, 1.0);
19143 })";
19144
19145 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
19146 EXPECT_EQ(0u, shader);
19147 }
19148
19149 // Make sure the shader in LargeInterfaceBlockArrayPassedToFunction works if the large local is
19150 // avoided.
TEST_P(GLSLTest_ES3,LargeInterfaceBlockArray)19151 TEST_P(GLSLTest_ES3, LargeInterfaceBlockArray)
19152 {
19153 int maxUniformBlockSize = 0;
19154 glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &maxUniformBlockSize);
19155 ANGLE_SKIP_TEST_IF(maxUniformBlockSize < 16384 * 4);
19156
19157 constexpr char kFS[] = R"(#version 300 es
19158 precision highp float;
19159 uniform Large { float a[16384]; };
19160 out vec4 color;
19161 void main() {
19162 color = vec4(a[0], 0.0, 0.0, 1.0);
19163 })";
19164
19165 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
19166 }
19167
19168 // Similar to LargeInterfaceBlockArrayPassedToFunction, but the array is nested in a struct.
TEST_P(GLSLTest_ES3,LargeInterfaceBlockNestedArrayPassedToFunction)19169 TEST_P(GLSLTest_ES3, LargeInterfaceBlockNestedArrayPassedToFunction)
19170 {
19171 constexpr char kFS[] = R"(#version 300 es
19172 precision highp float;
19173 struct S { float a[65536]; };
19174 uniform Large { S s; };
19175 float f(float b[65536])
19176 {
19177 b[0] = 1.0;
19178 return b[0] + b[1];
19179 }
19180 out vec4 color;
19181 void main() {
19182 color = vec4(f(s.a), 0.0, 0.0, 1.0);
19183 })";
19184
19185 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
19186 EXPECT_EQ(0u, shader);
19187 }
19188
19189 // Make sure the shader in LargeInterfaceBlockNestedArrayPassedToFunction works if the large local
19190 // is avoided.
TEST_P(GLSLTest_ES3,LargeInterfaceBlockNestedArray)19191 TEST_P(GLSLTest_ES3, LargeInterfaceBlockNestedArray)
19192 {
19193 int maxUniformBlockSize = 0;
19194 glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &maxUniformBlockSize);
19195 ANGLE_SKIP_TEST_IF(maxUniformBlockSize < 16384 * 4);
19196
19197 constexpr char kFS[] = R"(#version 300 es
19198 precision highp float;
19199 struct S { float a[16384]; };
19200 uniform Large { S s; };
19201 out vec4 color;
19202 void main() {
19203 color = vec4(s.a[0], 0.0, 0.0, 1.0);
19204 })";
19205
19206 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
19207 }
19208
19209 // Similar to LargeInterfaceBlockArrayPassedToFunction, but the large array is copied to a local
19210 // variable instead.
TEST_P(GLSLTest_ES3,LargeInterfaceBlockArrayCopiedToLocal)19211 TEST_P(GLSLTest_ES3, LargeInterfaceBlockArrayCopiedToLocal)
19212 {
19213 constexpr char kFS[] = R"(#version 300 es
19214 precision highp float;
19215 uniform Large { float a[65536]; };
19216 out vec4 color;
19217 void main() {
19218 float b[65536] = a;
19219 color = vec4(b[0], 0.0, 0.0, 1.0);
19220 })";
19221
19222 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
19223 EXPECT_EQ(0u, shader);
19224 }
19225
19226 // Similar to LargeInterfaceBlockArrayCopiedToLocal, but the array is nested in a struct
TEST_P(GLSLTest_ES3,LargeInterfaceBlockNestedArrayCopiedToLocal)19227 TEST_P(GLSLTest_ES3, LargeInterfaceBlockNestedArrayCopiedToLocal)
19228 {
19229 constexpr char kFS[] = R"(#version 300 es
19230 precision highp float;
19231 struct S { float a[65536]; };
19232 uniform Large { S s; };
19233 out vec4 color;
19234 void main() {
19235 S s2 = s;
19236 color = vec4(s2.a[0], 0.0, 0.0, 1.0);
19237 })";
19238
19239 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
19240 EXPECT_EQ(0u, shader);
19241 }
19242
19243 // Test that too large varyings are rejected.
TEST_P(GLSLTest_ES3,LargeArrayVarying)19244 TEST_P(GLSLTest_ES3, LargeArrayVarying)
19245 {
19246 constexpr char kFS[] = R"(#version 300 es
19247 precision highp float;
19248 in float a[65536];
19249 out vec4 color;
19250 void main() {
19251 color = vec4(a[0], 0.0, 0.0, 1.0);
19252 })";
19253
19254 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
19255 EXPECT_EQ(0u, shader);
19256 }
19257
19258 // Regression test for const globals losing const qualifiers during MSL
19259 // translation and exceeding available temporary registers on Apple GPUs.
TEST_P(GLSLTest_ES3,LargeConstGlobalArraysOfStructs)19260 TEST_P(GLSLTest_ES3, LargeConstGlobalArraysOfStructs)
19261 {
19262 const int n = 128;
19263 std::stringstream fragmentShader;
19264 fragmentShader << "#version 300 es\n"
19265 << "precision mediump float;\n"
19266 << "uniform mediump int zero;\n"
19267 << "out vec4 color;\n"
19268 << "struct S { vec3 A; vec3 B; float C; };\n";
19269 for (int i = 0; i < 3; ++i)
19270 {
19271 fragmentShader << "const S s" << i << "[" << n << "] = S[" << n << "](\n";
19272 for (int j = 0; j < n; ++j)
19273 {
19274 fragmentShader << " S(vec3(0., 1., 0.), vec3(" << j << "), 0.)"
19275 << (j != n - 1 ? ",\n" : "\n");
19276 }
19277 fragmentShader << ");\n";
19278 }
19279 // To ensure that the array is not rescoped, it must be accessed from two functions.
19280 // To ensure that the array is not optimized out, it must be accessed with a dynamic index.
19281 fragmentShader << "vec4 foo() {\n"
19282 << " return vec4(s0[zero].A * s1[zero].A * s2[zero].A, 1.0);\n"
19283 << "}\n"
19284 << "void main() {\n"
19285 << " color = foo() * vec4(s0[zero].A * s1[zero].A * s2[zero].A, 1.0);\n"
19286 << "}\n";
19287 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fragmentShader.str().c_str());
19288
19289 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
19290 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
19291 ASSERT_GL_NO_ERROR();
19292 }
19293
19294 // Test that framebuffer fetch emulation does not add a user-visible uniform.
TEST_P(GLSLTest,FramebufferFetchDoesNotAddUniforms)19295 TEST_P(GLSLTest, FramebufferFetchDoesNotAddUniforms)
19296 {
19297 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch"));
19298 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_draw_buffers"));
19299
19300 static constexpr char kFS[] = R"(#version 100
19301 #extension GL_EXT_shader_framebuffer_fetch : require
19302 #extension GL_EXT_draw_buffers : require
19303 uniform highp vec4 u_color;
19304
19305 void main (void)
19306 {
19307 gl_FragData[0] = gl_LastFragData[0] + u_color;
19308 gl_FragData[1] = gl_LastFragData[1] + u_color;
19309 gl_FragData[2] = gl_LastFragData[2] + u_color;
19310 gl_FragData[3] = gl_LastFragData[3] + u_color;
19311 })";
19312
19313 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
19314 glUseProgram(program);
19315
19316 GLint activeUniforms = 0, uniformsMaxLength = 0;
19317 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &activeUniforms);
19318 glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &uniformsMaxLength);
19319
19320 // There should be only one active uniform
19321 EXPECT_EQ(activeUniforms, 1);
19322
19323 // And that is u_color
19324 GLsizei nameLen = uniformsMaxLength;
19325 std::vector<char> name(uniformsMaxLength);
19326
19327 GLint size;
19328 GLenum type;
19329
19330 glGetActiveUniform(program, 0, uniformsMaxLength, &nameLen, &size, &type, name.data());
19331 EXPECT_EQ(std::string(name.data()), "u_color");
19332 EXPECT_EQ(size, 1);
19333 EXPECT_EQ(type, static_cast<GLenum>(GL_FLOAT_VEC4));
19334 }
19335
19336 // Test that framebuffer fetch emulation does not add a user-visible uniform.
TEST_P(GLSLTest_ES31,FramebufferFetchDoesNotAddUniforms)19337 TEST_P(GLSLTest_ES31, FramebufferFetchDoesNotAddUniforms)
19338 {
19339 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch"));
19340
19341 static constexpr char kFS[] = R"(#version 310 es
19342 #extension GL_EXT_shader_framebuffer_fetch : require
19343 layout(location = 0) inout highp vec4 o_color;
19344
19345 layout(std140, binding = 0) buffer outBlock {
19346 highp vec4 data[256];
19347 };
19348
19349 uniform highp vec4 u_color;
19350 void main (void)
19351 {
19352 uint index = uint(gl_FragCoord.y) * 16u + uint(gl_FragCoord.x);
19353 data[index] = o_color;
19354 o_color += u_color;
19355 })";
19356
19357 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
19358 glUseProgram(program);
19359
19360 GLint activeUniforms = 0, uniformsMaxLength = 0;
19361 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &activeUniforms);
19362 glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &uniformsMaxLength);
19363
19364 // There should be only one active uniform
19365 EXPECT_EQ(activeUniforms, 1);
19366
19367 // And that is u_color
19368 GLsizei nameLen = uniformsMaxLength;
19369 std::vector<char> name(uniformsMaxLength);
19370
19371 GLint size;
19372 GLenum type;
19373
19374 glGetActiveUniform(program, 0, uniformsMaxLength, &nameLen, &size, &type, name.data());
19375 EXPECT_EQ(std::string(name.data()), "u_color");
19376 EXPECT_EQ(size, 1);
19377 EXPECT_EQ(type, static_cast<GLenum>(GL_FLOAT_VEC4));
19378 }
19379
19380 // Test that advanced blend emulation does not add a user-visible uniform.
TEST_P(GLSLTest_ES31,AdvancedBlendEquationsDoesNotAddUniforms)19381 TEST_P(GLSLTest_ES31, AdvancedBlendEquationsDoesNotAddUniforms)
19382 {
19383 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_KHR_blend_equation_advanced"));
19384
19385 static constexpr char kFS[] = R"(#version 310 es
19386 #extension GL_KHR_blend_equation_advanced : require
19387
19388 layout (blend_support_multiply) out;
19389
19390 out highp vec4 o_color;
19391
19392 layout(std140, binding = 0) buffer outBlock {
19393 highp vec4 data[256];
19394 };
19395
19396 uniform highp vec4 u_color;
19397 void main (void)
19398 {
19399 o_color = u_color;
19400 })";
19401
19402 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
19403 glUseProgram(program);
19404
19405 GLint activeUniforms = 0, uniformsMaxLength = 0;
19406 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &activeUniforms);
19407 glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &uniformsMaxLength);
19408
19409 // There should be only one active uniform
19410 EXPECT_EQ(activeUniforms, 1);
19411
19412 // And that is u_color
19413 GLsizei nameLen = uniformsMaxLength;
19414 std::vector<char> name(uniformsMaxLength);
19415
19416 GLint size;
19417 GLenum type;
19418
19419 glGetActiveUniform(program, 0, uniformsMaxLength, &nameLen, &size, &type, name.data());
19420 EXPECT_EQ(std::string(name.data()), "u_color");
19421 EXPECT_EQ(size, 1);
19422 EXPECT_EQ(type, static_cast<GLenum>(GL_FLOAT_VEC4));
19423 }
19424
19425 // Tests struct in function return type.
TEST_P(GLSLTest,StructInFunctionDefinition)19426 TEST_P(GLSLTest, StructInFunctionDefinition)
19427 {
19428 const char kFragmentShader[] = R"(precision mediump float;
19429 struct Foo
19430 {
19431 float v;
19432 };
19433
19434 Foo foo()
19435 {
19436 Foo f;
19437 f.v = 0.5;
19438 return f;
19439 }
19440
19441 void main()
19442 {
19443 gl_FragColor = vec4(1, 0, 0, 1);
19444 Foo f = foo();
19445 if (f.v == 0.5)
19446 {
19447 gl_FragColor = vec4(0, 1, 0, 1);
19448 }
19449 })";
19450
19451 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
19452 glUseProgram(program);
19453
19454 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
19455 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
19456 }
19457
19458 // Tests struct definition in function return type.
TEST_P(GLSLTest,StructDefinitionInFunctionDefinition)19459 TEST_P(GLSLTest, StructDefinitionInFunctionDefinition)
19460 {
19461 const char kFragmentShader[] = R"(precision mediump float;
19462 struct Foo { float v; } foo()
19463 {
19464 Foo f;
19465 f.v = 0.5;
19466 return f;
19467 }
19468
19469 void main()
19470 {
19471 gl_FragColor = vec4(1, 0, 0, 1);
19472 Foo f = foo();
19473 if (f.v == 0.5)
19474 {
19475 gl_FragColor = vec4(0, 1, 0, 1);
19476 }
19477 })";
19478
19479 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
19480 glUseProgram(program);
19481
19482 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
19483 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
19484 }
19485
19486 // Test struct definition in forward declaration of function return type.
TEST_P(GLSLTest,StructDefinitionInFunctionPrototype)19487 TEST_P(GLSLTest, StructDefinitionInFunctionPrototype)
19488 {
19489 const char kFragmentShader[] = R"(precision mediump float;
19490 struct Foo { float v; } foo();
19491
19492 void main()
19493 {
19494 gl_FragColor = vec4(1, 0, 0, 1);
19495 Foo f = foo();
19496 if (f.v == 0.5)
19497 {
19498 gl_FragColor = vec4(0, 1, 0, 1);
19499 }
19500 }
19501
19502 Foo foo()
19503 {
19504 Foo f;
19505 f.v = 0.5;
19506 return f;
19507 })";
19508
19509 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
19510 glUseProgram(program);
19511
19512 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
19513 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
19514 }
19515
19516 // Test that struct declarations are introduced into the correct scope.
TEST_P(GLSLTest,StructDefinitionInFunctionPrototypeScope)19517 TEST_P(GLSLTest, StructDefinitionInFunctionPrototypeScope)
19518 {
19519 const char kFragmentShader[] = R"(precision mediump float;
19520
19521 struct Foo { float v; } foo()
19522 {
19523 Foo f;
19524 f.v = 0.5;
19525 return f;
19526 }
19527
19528 struct Bar { Foo f; } bar()
19529 {
19530 Bar b;
19531 b.f = foo();
19532 return b;
19533 }
19534
19535 void main()
19536 {
19537 gl_FragColor = vec4(1, 0, 0, 1);
19538 Bar b = bar();
19539 if (b.f.v == 0.5)
19540 {
19541 gl_FragColor = vec4(0, 1, 0, 1);
19542 }
19543 })";
19544
19545 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
19546 glUseProgram(program);
19547
19548 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
19549 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
19550 }
19551
19552 // Test that struct declarations are introduced into the correct scope.
TEST_P(GLSLTest,NestedReturnedStructs)19553 TEST_P(GLSLTest, NestedReturnedStructs)
19554 {
19555 const char kFragmentShader[] = R"(precision mediump float;
19556 struct Foo { float v; } foo(float bar);
19557
19558 void main()
19559 {
19560 gl_FragColor = vec4(1, 0, 0, 1);
19561 float v = foo(foo(0.5).v).v;
19562 if (v == 0.5)
19563 {
19564 gl_FragColor = vec4(0, 1, 0, 1);
19565 }
19566 }
19567
19568 Foo foo(float bar)
19569 {
19570 Foo f;
19571 f.v = bar;
19572 return f;
19573 })";
19574
19575 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
19576 glUseProgram(program);
19577
19578 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
19579 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
19580 }
19581
19582 // Test that double underscores user defined name is allowed
TEST_P(GLSLTest_ES3,DoubleUnderscoresName)19583 TEST_P(GLSLTest_ES3, DoubleUnderscoresName)
19584 {
19585 constexpr char kFS[] = R"(#version 300 es
19586 precision mediump float;
19587 out vec4 oColor;
19588 uniform struct __Data {float red;} data;
19589 void main() {oColor=vec4(data.red,0,1,1);})";
19590
19591 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
19592 glUseProgram(program);
19593 // populate uniform
19594 GLint uniformLocation = glGetUniformLocation(program, "data.red");
19595 EXPECT_NE(uniformLocation, -1);
19596 glUniform1f(uniformLocation, 0);
19597
19598 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
19599 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
19600 ASSERT_GL_NO_ERROR();
19601 }
19602
19603 // Test that user defined name starts with "ANGLE" or "ANGLE_"
TEST_P(GLSLTest_ES3,VariableNameStartsWithANGLE)19604 TEST_P(GLSLTest_ES3, VariableNameStartsWithANGLE)
19605 {
19606 constexpr char kFS[] = R"(#version 300 es
19607 precision mediump float;
19608 out vec4 oColor;
19609 uniform struct ANGLEData{float red;} data;
19610 uniform struct ANGLE_Data{float green;} _data;
19611 void main() {oColor=vec4(data.red,_data.green,1,1);})";
19612
19613 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
19614 glUseProgram(program);
19615 // populate uniform
19616 GLint uniformRedLocation = glGetUniformLocation(program, "data.red");
19617 GLint uniformGreenLocation = glGetUniformLocation(program, "_data.green");
19618 EXPECT_NE(uniformRedLocation, -1);
19619 EXPECT_NE(uniformGreenLocation, -1);
19620 glUniform1f(uniformRedLocation, 0);
19621 glUniform1f(uniformGreenLocation, 0);
19622
19623 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
19624 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
19625 ASSERT_GL_NO_ERROR();
19626 }
19627
19628 // Test that underscores in array names work with out arrays.
TEST_P(GLSLTest_ES3,UnderscoresWorkWithOutArrays)19629 TEST_P(GLSLTest_ES3, UnderscoresWorkWithOutArrays)
19630 {
19631 GLuint fbo;
19632 glGenFramebuffers(1, &fbo);
19633 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
19634
19635 GLuint textures[4];
19636 glGenTextures(4, textures);
19637
19638 for (size_t texIndex = 0; texIndex < ArraySize(textures); texIndex++)
19639 {
19640 glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
19641 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
19642 GL_UNSIGNED_BYTE, nullptr);
19643 }
19644
19645 GLint maxDrawBuffers;
19646 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
19647 ASSERT_GE(maxDrawBuffers, 4);
19648
19649 GLuint readFramebuffer;
19650 glGenFramebuffers(1, &readFramebuffer);
19651 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFramebuffer);
19652
19653 constexpr char kFS[] = R"(#version 300 es
19654 precision highp float;
19655 out vec4 _e[4];
19656 void main()
19657 {
19658 _e[0] = vec4(1.0, 0.0, 0.0, 1.0);
19659 _e[1] = vec4(0.0, 1.0, 0.0, 1.0);
19660 _e[2] = vec4(0.0, 0.0, 1.0, 1.0);
19661 _e[3] = vec4(1.0, 1.0, 1.0, 1.0);
19662 }
19663 )";
19664 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
19665 GLenum allBufs[4] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2,
19666 GL_COLOR_ATTACHMENT3};
19667 constexpr GLuint kMaxBuffers = 4;
19668 // Enable all draw buffers.
19669 for (GLuint texIndex = 0; texIndex < kMaxBuffers; texIndex++)
19670 {
19671 glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
19672 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
19673 textures[texIndex], 0);
19674 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
19675 textures[texIndex], 0);
19676 }
19677 glDrawBuffers(kMaxBuffers, allBufs);
19678
19679 // Draw with simple program.
19680 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
19681 ASSERT_GL_NO_ERROR();
19682 verifyAttachment2DColor(0, textures[0], GL_TEXTURE_2D, 0, GLColor::red);
19683 verifyAttachment2DColor(1, textures[1], GL_TEXTURE_2D, 0, GLColor::green);
19684 verifyAttachment2DColor(2, textures[2], GL_TEXTURE_2D, 0, GLColor::blue);
19685 verifyAttachment2DColor(3, textures[3], GL_TEXTURE_2D, 0, GLColor::white);
19686 }
19687
19688 } // anonymous namespace
19689
19690 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(
19691 GLSLTest,
19692 ES3_OPENGL().enable(Feature::ForceInitShaderVariables),
19693 ES3_OPENGL().enable(Feature::ScalarizeVecAndMatConstructorArgs),
19694 ES3_OPENGLES().enable(Feature::ScalarizeVecAndMatConstructorArgs),
19695 ES3_VULKAN().enable(Feature::AvoidOpSelectWithMismatchingRelaxedPrecision),
19696 ES3_VULKAN().enable(Feature::ForceInitShaderVariables),
19697 ES3_VULKAN().disable(Feature::SupportsSPIRV14));
19698
19699 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(GLSLTestNoValidation);
19700
19701 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLTest_ES3);
19702 ANGLE_INSTANTIATE_TEST_ES3_AND(
19703 GLSLTest_ES3,
19704 ES3_OPENGL().enable(Feature::ForceInitShaderVariables),
19705 ES3_OPENGL().enable(Feature::ScalarizeVecAndMatConstructorArgs),
19706 ES3_OPENGLES().enable(Feature::ScalarizeVecAndMatConstructorArgs),
19707 ES3_VULKAN().enable(Feature::AvoidOpSelectWithMismatchingRelaxedPrecision),
19708 ES3_VULKAN().enable(Feature::ForceInitShaderVariables),
19709 ES3_VULKAN().disable(Feature::SupportsSPIRV14));
19710
19711 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLTestLoops);
19712 ANGLE_INSTANTIATE_TEST_ES3(GLSLTestLoops);
19713
19714 ANGLE_INSTANTIATE_TEST_ES2(WebGLGLSLTest);
19715
19716 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WebGL2GLSLTest);
19717 ANGLE_INSTANTIATE_TEST_ES3(WebGL2GLSLTest);
19718
19719 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLTest_ES31);
19720 ANGLE_INSTANTIATE_TEST_ES31_AND(GLSLTest_ES31,
19721 ES31_VULKAN().enable(Feature::ForceInitShaderVariables),
19722 ES31_VULKAN().disable(Feature::SupportsSPIRV14));
19723
19724 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLTest_ES31_InitShaderVariables);
19725 ANGLE_INSTANTIATE_TEST(
19726 GLSLTest_ES31_InitShaderVariables,
19727 ES31_VULKAN().enable(Feature::ForceInitShaderVariables),
19728 ES31_VULKAN().disable(Feature::SupportsSPIRV14).enable(Feature::ForceInitShaderVariables));
19729