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.
TEST_P(GLSLTest,SwizzledChainedAssignIncrement)570 TEST_P(GLSLTest, SwizzledChainedAssignIncrement)
571 {
572 constexpr char kFS[] =
573 R"(
574 precision mediump float;
575 void main() {
576 vec2 v = vec2(1,5);
577 // at the end of next statement, values in
578 // v.x = 12, v.y = 12
579 v.xy += v.yx += v.xy;
580 // v1 and v2, both are initialized with (12,12)
581 vec2 v1 = v, v2 = v;
582 v1.xy += v2.yx += ++(v.xy); // v1 = 37, v2 = 25 each
583 v1.xy += v2.yx += (v.xy)++; // v1 = 75, v2 = 38 each
584 gl_FragColor = vec4(v1,v2)/255.; // 75, 75, 38, 38
585 })";
586
587 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
588 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
589 ASSERT_GL_NO_ERROR();
590 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(75, 75, 38, 38));
591 }
592
TEST_P(GLSLTest,NamelessScopedStructs)593 TEST_P(GLSLTest, NamelessScopedStructs)
594 {
595 constexpr char kFS[] = R"(precision mediump float;
596 void main()
597 {
598 struct
599 {
600 float q;
601 } b;
602
603 gl_FragColor = vec4(1, 0, 0, 1);
604 gl_FragColor.a += b.q;
605 })";
606
607 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
608 }
609
TEST_P(GLSLTest_ES3,CompareEqualityOfArrayOfVectors)610 TEST_P(GLSLTest_ES3, CompareEqualityOfArrayOfVectors)
611 {
612 constexpr char kFS[] = R"(#version 300 es
613 precision mediump float;
614 out vec4 fragColor;
615 uniform vec3 a[3];
616 uniform vec3 b[3];
617 void main() {
618 bool same = a == b;
619 fragColor = vec4(0);
620 if (same) {
621 fragColor = vec4(1);
622 }
623 }
624 )";
625
626 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
627 glUseProgram(program);
628
629 GLint aLocation = glGetUniformLocation(program, "a");
630 GLint bLocation = glGetUniformLocation(program, "b");
631 EXPECT_NE(aLocation, -1);
632 EXPECT_NE(bLocation, -1);
633
634 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
635 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
636
637 static float almostZeros[] = {0, 0, 0, 0, 0, 0, 0, 1, 0};
638 glUniform3fv(bLocation, 9, almostZeros);
639
640 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
641 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
642
643 glUniform3fv(aLocation, 9, almostZeros);
644 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
645 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
646
647 ASSERT_GL_NO_ERROR();
648 }
649
TEST_P(GLSLTest_ES3,CompareEqualityOfArrayOfMatrices)650 TEST_P(GLSLTest_ES3, CompareEqualityOfArrayOfMatrices)
651 {
652 constexpr char kFS[] = R"(#version 300 es
653 precision mediump float;
654 out vec4 fragColor;
655 uniform mat3 a[3];
656 uniform mat3 b[3];
657 void main() {
658 bool same = a == b;
659 fragColor = vec4(0);
660 if (same) {
661 fragColor = vec4(1);
662 }
663 }
664 )";
665
666 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
667 glUseProgram(program);
668
669 GLint aLocation = glGetUniformLocation(program, "a");
670 GLint bLocation = glGetUniformLocation(program, "b");
671 EXPECT_NE(aLocation, -1);
672 EXPECT_NE(bLocation, -1);
673
674 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
675 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
676
677 static float almostZeros[] = {
678 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,
679 };
680 glUniformMatrix3fv(bLocation, 27, false, almostZeros);
681
682 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
683 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
684
685 glUniformMatrix3fv(aLocation, 27, false, almostZeros);
686 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
687 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
688
689 ASSERT_GL_NO_ERROR();
690 }
691
TEST_P(GLSLTest_ES3,CompareEqualityOfArrayOfFloats)692 TEST_P(GLSLTest_ES3, CompareEqualityOfArrayOfFloats)
693 {
694 constexpr char kFS[] = R"(#version 300 es
695 precision mediump float;
696 out vec4 fragColor;
697 uniform float a[3];
698 uniform float b[3];
699 void main() {
700 bool same = a == b;
701 fragColor = vec4(0);
702 if (same) {
703 fragColor = vec4(1);
704 }
705 }
706 )";
707
708 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
709 glUseProgram(program);
710
711 GLint aLocation = glGetUniformLocation(program, "a");
712 GLint bLocation = glGetUniformLocation(program, "b");
713 EXPECT_NE(aLocation, -1);
714 EXPECT_NE(bLocation, -1);
715
716 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
717 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
718
719 static float almostZeros[] = {
720 0,
721 0,
722 1,
723 };
724 glUniform1fv(bLocation, 3, almostZeros);
725
726 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
727 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
728
729 glUniform1fv(aLocation, 3, almostZeros);
730 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
731 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
732
733 ASSERT_GL_NO_ERROR();
734 }
735
TEST_P(GLSLTest_ES3,CompareInequalityOfArrayOfVectors)736 TEST_P(GLSLTest_ES3, CompareInequalityOfArrayOfVectors)
737 {
738 constexpr char kFS[] = R"(#version 300 es
739 precision mediump float;
740 out vec4 fragColor;
741 uniform vec3 a[3];
742 uniform vec3 b[3];
743 void main() {
744 bool notSame = a != b;
745 fragColor = vec4(0);
746 if (notSame) {
747 fragColor = vec4(1);
748 }
749 }
750 )";
751
752 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
753 glUseProgram(program);
754
755 GLint aLocation = glGetUniformLocation(program, "a");
756 GLint bLocation = glGetUniformLocation(program, "b");
757 EXPECT_NE(aLocation, -1);
758 EXPECT_NE(bLocation, -1);
759
760 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
761 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
762
763 static float almostZeros[] = {0, 0, 0, 0, 0, 0, 0, 1, 0};
764 glUniform3fv(bLocation, 9, almostZeros);
765
766 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
767 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
768
769 glUniform3fv(aLocation, 9, almostZeros);
770 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
771 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
772
773 ASSERT_GL_NO_ERROR();
774 }
775
TEST_P(GLSLTest_ES3,CompareInequalityOfArrayOfMatrices)776 TEST_P(GLSLTest_ES3, CompareInequalityOfArrayOfMatrices)
777 {
778 constexpr char kFS[] = R"(#version 300 es
779 precision mediump float;
780 out vec4 fragColor;
781 uniform mat3 a[3];
782 uniform mat3 b[3];
783 void main() {
784 bool notSame = a != b;
785 fragColor = vec4(0);
786 if (notSame) {
787 fragColor = vec4(1);
788 }
789 }
790 )";
791
792 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
793 glUseProgram(program);
794
795 GLint aLocation = glGetUniformLocation(program, "a");
796 GLint bLocation = glGetUniformLocation(program, "b");
797 EXPECT_NE(aLocation, -1);
798 EXPECT_NE(bLocation, -1);
799
800 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
801 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
802
803 static float almostZeros[] = {
804 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,
805 };
806 glUniformMatrix3fv(bLocation, 27, false, almostZeros);
807
808 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
809 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
810
811 glUniformMatrix3fv(aLocation, 27, false, almostZeros);
812 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
813 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
814
815 ASSERT_GL_NO_ERROR();
816 }
817
TEST_P(GLSLTest_ES3,CompareInequalityOfArrayOfFloats)818 TEST_P(GLSLTest_ES3, CompareInequalityOfArrayOfFloats)
819 {
820 constexpr char kFS[] = R"(#version 300 es
821 precision mediump float;
822 out vec4 fragColor;
823 uniform float a[3];
824 uniform float b[3];
825 void main() {
826 bool notSame = a != b;
827 fragColor = vec4(0);
828 if (notSame) {
829 fragColor = vec4(1);
830 }
831 }
832 )";
833
834 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
835 glUseProgram(program);
836
837 GLint aLocation = glGetUniformLocation(program, "a");
838 GLint bLocation = glGetUniformLocation(program, "b");
839 EXPECT_NE(aLocation, -1);
840 EXPECT_NE(bLocation, -1);
841
842 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
843 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
844
845 static float almostZeros[] = {
846 0,
847 0,
848 1,
849 };
850 glUniform1fv(bLocation, 3, almostZeros);
851
852 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
853 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
854
855 glUniform1fv(aLocation, 3, almostZeros);
856 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
857 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
858
859 ASSERT_GL_NO_ERROR();
860 }
861
862 // Test that array of fragment shader outputs is processed properly and draws
863 // E.g. was issue with "out vec4 frag_color[4];"
TEST_P(GLSLTest_ES3,FragmentShaderOutputArray)864 TEST_P(GLSLTest_ES3, FragmentShaderOutputArray)
865 {
866 GLuint fbo;
867 glGenFramebuffers(1, &fbo);
868 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
869
870 GLuint textures[4];
871 glGenTextures(4, textures);
872
873 for (size_t texIndex = 0; texIndex < ArraySize(textures); texIndex++)
874 {
875 glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
876 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
877 GL_UNSIGNED_BYTE, nullptr);
878 }
879
880 GLint maxDrawBuffers;
881 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
882 ASSERT_GE(maxDrawBuffers, 4);
883
884 GLuint readFramebuffer;
885 glGenFramebuffers(1, &readFramebuffer);
886 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFramebuffer);
887
888 constexpr char kFS[] = R"(#version 300 es
889 precision highp float;
890
891 out vec4 frag_color[4];
892
893 void main()
894 {
895 frag_color[0] = vec4(1.0, 0.0, 0.0, 1.0);
896 frag_color[1] = vec4(0.0, 1.0, 0.0, 1.0);
897 frag_color[2] = vec4(0.0, 0.0, 1.0, 1.0);
898 frag_color[3] = vec4(1.0, 1.0, 1.0, 1.0);
899 }
900 )";
901
902 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
903
904 GLenum allBufs[4] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2,
905 GL_COLOR_ATTACHMENT3};
906
907 constexpr GLuint kMaxBuffers = 4;
908
909 // Enable all draw buffers.
910 for (GLuint texIndex = 0; texIndex < kMaxBuffers; texIndex++)
911 {
912 glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
913 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
914 textures[texIndex], 0);
915 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
916 textures[texIndex], 0);
917 }
918 glDrawBuffers(kMaxBuffers, allBufs);
919
920 // Draw with simple program.
921 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
922 ASSERT_GL_NO_ERROR();
923
924 verifyAttachment2DColor(0, textures[0], GL_TEXTURE_2D, 0, GLColor::red);
925 verifyAttachment2DColor(1, textures[1], GL_TEXTURE_2D, 0, GLColor::green);
926 verifyAttachment2DColor(2, textures[2], GL_TEXTURE_2D, 0, GLColor::blue);
927 verifyAttachment2DColor(3, textures[3], GL_TEXTURE_2D, 0, GLColor::white);
928 }
929
930 // Test that inactive fragment shader outputs don't cause a crash.
TEST_P(GLSLTest_ES3,InactiveFragmentShaderOutput)931 TEST_P(GLSLTest_ES3, InactiveFragmentShaderOutput)
932 {
933 constexpr char kFS[] = R"(#version 300 es
934 precision highp float;
935
936 // Make color0 inactive but specify color1 first. The Vulkan backend assigns bogus locations when
937 // compiling and fixes it up in SPIR-V. If color0's location is not fixed, it will return location
938 // 1 (aliasing color1). This will lead to a Vulkan validation warning about attachment 0 not being
939 // written to, which shouldn't be fatal.
940 layout(location = 1) out vec4 color1;
941 layout(location = 0) out vec4 color0;
942
943 void main()
944 {
945 color1 = vec4(0.0, 1.0, 0.0, 1.0);
946 }
947 )";
948
949 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
950
951 constexpr GLint kDrawBufferCount = 2;
952
953 GLint maxDrawBuffers;
954 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
955 ASSERT_GE(maxDrawBuffers, kDrawBufferCount);
956
957 GLTexture textures[kDrawBufferCount];
958
959 for (GLint texIndex = 0; texIndex < kDrawBufferCount; ++texIndex)
960 {
961 glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
962 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
963 GL_UNSIGNED_BYTE, nullptr);
964 }
965
966 GLenum allBufs[kDrawBufferCount] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
967
968 GLFramebuffer fbo;
969 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
970
971 // Enable all draw buffers.
972 for (GLint texIndex = 0; texIndex < kDrawBufferCount; ++texIndex)
973 {
974 glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
975 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
976 textures[texIndex], 0);
977 }
978 glDrawBuffers(kDrawBufferCount, allBufs);
979
980 // Draw with simple program.
981 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
982 ASSERT_GL_NO_ERROR();
983 }
984
TEST_P(GLSLTest,ScopedStructsOrderBug)985 TEST_P(GLSLTest, ScopedStructsOrderBug)
986 {
987 constexpr char kFS[] = R"(precision mediump float;
988
989 struct T
990 {
991 float f;
992 };
993
994 void main()
995 {
996 T a;
997
998 struct T
999 {
1000 float q;
1001 };
1002
1003 T b;
1004
1005 gl_FragColor = vec4(1, 0, 0, 1);
1006 gl_FragColor.a += a.f;
1007 gl_FragColor.a += b.q;
1008 })";
1009
1010 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
1011 }
1012
1013 // Test that defining a struct together with an inactive uniform, then using it in a scope that has
1014 // another struct with the same name declared works.
TEST_P(GLSLTest,ScopedStructsOrderBug2)1015 TEST_P(GLSLTest, ScopedStructsOrderBug2)
1016 {
1017 constexpr char kFS[] = R"(precision mediump float;
1018
1019 uniform struct T
1020 {
1021 float f;
1022 } x;
1023
1024 void main()
1025 {
1026 T a;
1027
1028 struct T
1029 {
1030 float q;
1031 };
1032
1033 T b;
1034
1035 gl_FragColor = vec4(1, 0, 0, 1);
1036 gl_FragColor.a += a.f;
1037 gl_FragColor.a += b.q;
1038 })";
1039
1040 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
1041 }
1042
1043 // Test that inactive uniforms of struct type don't cause any errors.
TEST_P(GLSLTest,InactiveStructUniform)1044 TEST_P(GLSLTest, InactiveStructUniform)
1045 {
1046 constexpr char kVS[] = R"(
1047 uniform struct
1048 {
1049 vec4 c;
1050 } s;
1051 void main()
1052 {
1053 })";
1054
1055 ANGLE_GL_PROGRAM(program, kVS, essl1_shaders::fs::Red());
1056 }
1057
1058 // Test that struct with same name can be declared in inner scope.
TEST_P(GLSLTest,SameNameStructInInnerScope)1059 TEST_P(GLSLTest, SameNameStructInInnerScope)
1060 {
1061 constexpr char kVS[] = R"(
1062 void main() {
1063 gl_Position = vec4(0);
1064 })";
1065
1066 constexpr char kFS[] = R"(
1067 struct S
1068 {
1069 mediump float f;
1070 };
1071 void main()
1072 {
1073 struct S
1074 {
1075 S n;
1076 };
1077 })";
1078
1079 ANGLE_GL_PROGRAM(program, kVS, kFS);
1080 }
1081
1082 // Regression test based on WebGL's conformance/glsl/misc/empty-declaration.html
TEST_P(GLSLTest,StructEmptyDeclaratorBug)1083 TEST_P(GLSLTest, StructEmptyDeclaratorBug)
1084 {
1085 constexpr char kVS[] = R"(
1086 struct S {
1087 float member;
1088 }, a;
1089 void main() {
1090 a.member = 0.0;
1091 gl_Position = vec4(a.member);
1092 })";
1093
1094 constexpr char kFS[] = R"(precision mediump float;
1095 void main()
1096 {
1097 gl_FragColor = vec4(1.0,0.0,0.0,1.0);
1098 })";
1099
1100 ANGLE_GL_PROGRAM(program, kVS, kFS);
1101 }
1102
1103 // Regression test based on WebGL's conformance/ogles/GL/build/build_001_to_008.html
TEST_P(GLSLTest,StructConstantFoldingBug)1104 TEST_P(GLSLTest, StructConstantFoldingBug)
1105 {
1106 constexpr char kVS[] = R"(
1107 void main()
1108 {
1109
1110 const struct s2 {
1111 int i;
1112 vec3 v3;
1113 bvec4 bv4;
1114 } s22 = s2(8, vec3(9, 10, 11), bvec4(true, false, true, false));
1115
1116 struct s4 {
1117 int ii;
1118 vec4 v4;
1119 };
1120
1121 const struct s1 {
1122 s2 ss;
1123 int i;
1124 float f;
1125 mat4 m;
1126 s4 s44;
1127 } s11 = s1(s22, 2, 4.0, mat4(5), s4(6, vec4(7, 8, 9, 10))) ;
1128
1129 const int field3 = s11.i * s11.ss.i; // constant folding (int * int)
1130 const vec4 field4 = s11.s44.v4 * s11.s44.v4; // constant folding (vec4 * vec4)
1131 // 49, 64, 81, 100
1132 const vec4 v4 = vec4(s11.ss.v3.y, s11.m[3][3], field3, field4[2]); // 10.0, 5.0, 16.0, 81.0
1133 gl_Position = v4;
1134 })";
1135
1136 constexpr char kFS[] = R"(precision mediump float;
1137 precision mediump float;
1138 void main()
1139 {
1140 gl_FragColor = vec4(1.0,0.0,0.0,1.0);
1141 })";
1142
1143 ANGLE_GL_PROGRAM(program, kVS, kFS);
1144 }
1145
1146 // Test that constant folding doesn't remove struct declaration.
TEST_P(GLSLTest,StructConstantFoldingBug2)1147 TEST_P(GLSLTest, StructConstantFoldingBug2)
1148 {
1149 constexpr char kVS[] = R"(
1150 uniform vec4 u;
1151
1152 void main()
1153 {
1154
1155 const struct s2 {
1156 int i;
1157 vec3 v3;
1158 bvec4 bv4;
1159 } s22 = s2(8, vec3(9, 10, 11), bvec4(true, false, true, false));
1160
1161 s2 x;
1162 x.v3 = u.xyz;
1163
1164 gl_Position = vec4(x.v3, float(s22.i));
1165 })";
1166
1167 constexpr char kFS[] = R"(precision mediump float;
1168 precision mediump float;
1169 void main()
1170 {
1171 gl_FragColor = vec4(1.0,0.0,0.0,1.0);
1172 })";
1173
1174 ANGLE_GL_PROGRAM(program, kVS, kFS);
1175 }
1176
TEST_P(GLSLTest,ScopedStructsBug)1177 TEST_P(GLSLTest, ScopedStructsBug)
1178 {
1179 constexpr char kFS[] = R"(precision mediump float;
1180
1181 struct T_0
1182 {
1183 float f;
1184 };
1185
1186 void main()
1187 {
1188 gl_FragColor = vec4(1, 0, 0, 1);
1189
1190 struct T
1191 {
1192 vec2 v;
1193 };
1194
1195 T_0 a;
1196 T b;
1197
1198 gl_FragColor.a += a.f;
1199 gl_FragColor.a += b.v.x;
1200 })";
1201
1202 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
1203 }
1204
TEST_P(GLSLTest,DxPositionBug)1205 TEST_P(GLSLTest, DxPositionBug)
1206 {
1207 constexpr char kVS[] = R"(attribute vec4 inputAttribute;
1208 varying float dx_Position;
1209 void main()
1210 {
1211 gl_Position = vec4(inputAttribute);
1212 dx_Position = 0.0;
1213 })";
1214
1215 constexpr char kFS[] = R"(precision mediump float;
1216
1217 varying float dx_Position;
1218
1219 void main()
1220 {
1221 gl_FragColor = vec4(dx_Position, 0, 0, 1);
1222 })";
1223
1224 ANGLE_GL_PROGRAM(program, kVS, kFS);
1225 }
1226
1227 // Draw an array of points with the first vertex offset at 0 using gl_VertexID
TEST_P(GLSLTest_ES3,GLVertexIDOffsetZeroDrawArray)1228 TEST_P(GLSLTest_ES3, GLVertexIDOffsetZeroDrawArray)
1229 {
1230 constexpr int kStartIndex = 0;
1231 constexpr int kArrayLength = 5;
1232 constexpr char kVS[] = R"(#version 300 es
1233 precision highp float;
1234 void main() {
1235 gl_Position = vec4(float(gl_VertexID)/10.0, 0, 0, 1);
1236 gl_PointSize = 3.0;
1237 })";
1238
1239 constexpr char kFS[] = R"(#version 300 es
1240 precision highp float;
1241 out vec4 outColor;
1242 void main() {
1243 outColor = vec4(1.0, 0.0, 0.0, 1.0);
1244 })";
1245
1246 ANGLE_GL_PROGRAM(program, kVS, kFS);
1247
1248 glUseProgram(program);
1249 glDrawArrays(GL_POINTS, kStartIndex, kArrayLength);
1250
1251 double pointCenterX = static_cast<double>(getWindowWidth()) / 2.0;
1252 double pointCenterY = static_cast<double>(getWindowHeight()) / 2.0;
1253 for (int i = kStartIndex; i < kStartIndex + kArrayLength; i++)
1254 {
1255 double pointOffsetX = static_cast<double>(i * getWindowWidth()) / 20.0;
1256 EXPECT_PIXEL_COLOR_EQ(static_cast<int>(pointCenterX + pointOffsetX),
1257 static_cast<int>(pointCenterY), GLColor::red);
1258 }
1259 }
1260
GetFirstIntPixelRedValue()1261 GLint GetFirstIntPixelRedValue()
1262 {
1263 GLint pixel[4];
1264 glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_INT, pixel);
1265 return pixel[0];
1266 }
1267
TEST_P(GLSLTest_ES3,GLVertexIDIntegerTextureDrawElements)1268 TEST_P(GLSLTest_ES3, GLVertexIDIntegerTextureDrawElements)
1269 {
1270 constexpr char kVS[] = R"(#version 300 es
1271 flat out highp int vVertexID;
1272
1273 void main() {
1274 vVertexID = gl_VertexID;
1275 gl_PointSize = 1.0;
1276 gl_Position = vec4(0,0,0,1);
1277 })";
1278
1279 constexpr char kFS[] = R"(#version 300 es
1280 flat in highp int vVertexID;
1281 out highp int oVertexID;
1282 void main() {
1283 oVertexID = vVertexID;
1284 })";
1285
1286 ANGLE_GL_PROGRAM(program, kVS, kFS);
1287 glUseProgram(program);
1288 glViewport(0, 0, 1, 1);
1289
1290 GLTexture tex;
1291 glBindTexture(GL_TEXTURE_2D, tex);
1292 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, 1, 1);
1293 GLFramebuffer fb;
1294 glBindFramebuffer(GL_FRAMEBUFFER, fb);
1295 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
1296
1297 EXPECT_GL_NO_ERROR();
1298
1299 GLint clearData[4] = {42};
1300 glClearBufferiv(GL_COLOR, 0, clearData);
1301 EXPECT_EQ(42, GetFirstIntPixelRedValue());
1302
1303 const int kIndexDataSize = 5;
1304 GLushort indexData[] = {1, 2, 5, 3, 10000};
1305 GLBuffer indexBuffer;
1306 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1307 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_STATIC_DRAW);
1308
1309 for (size_t first = 0; first < kIndexDataSize; ++first)
1310 {
1311 for (size_t count = 1; first + count <= kIndexDataSize; ++count)
1312 {
1313 glDrawElements(GL_POINTS, count, GL_UNSIGNED_SHORT,
1314 reinterpret_cast<const void *>(first * 2u));
1315 GLint expected = indexData[first + count - 1];
1316 GLint actual = GetFirstIntPixelRedValue();
1317 EXPECT_EQ(expected, actual);
1318 }
1319 }
1320 EXPECT_GL_NO_ERROR();
1321 }
1322
TEST_P(GLSLTest_ES3,GLVertexIDIntegerTextureDrawElementsU8)1323 TEST_P(GLSLTest_ES3, GLVertexIDIntegerTextureDrawElementsU8)
1324 {
1325 constexpr char kVS[] = R"(#version 300 es
1326 flat out highp int vVertexID;
1327
1328 void main() {
1329 vVertexID = gl_VertexID;
1330 gl_PointSize = 1.0;
1331 gl_Position = vec4(0,0,0,1);
1332 })";
1333
1334 constexpr char kFS[] = R"(#version 300 es
1335 flat in highp int vVertexID;
1336 out highp int oVertexID;
1337 void main() {
1338 oVertexID = vVertexID;
1339 })";
1340
1341 ANGLE_GL_PROGRAM(program, kVS, kFS);
1342 glUseProgram(program);
1343 glViewport(0, 0, 1, 1);
1344
1345 GLTexture tex;
1346 glBindTexture(GL_TEXTURE_2D, tex);
1347 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, 1, 1);
1348 GLFramebuffer fb;
1349 glBindFramebuffer(GL_FRAMEBUFFER, fb);
1350 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
1351
1352 EXPECT_GL_NO_ERROR();
1353
1354 GLint clearData[4] = {42};
1355 glClearBufferiv(GL_COLOR, 0, clearData);
1356 EXPECT_EQ(42, GetFirstIntPixelRedValue());
1357
1358 const int kIndexDataSize = 5;
1359 GLubyte indexData[] = {1, 2, 5, 3, 100};
1360 GLBuffer indexBuffer;
1361 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1362 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_STATIC_DRAW);
1363
1364 for (size_t first = 0; first < kIndexDataSize; ++first)
1365 {
1366 for (size_t count = 1; first + count <= kIndexDataSize; ++count)
1367 {
1368 glDrawElements(GL_POINTS, count, GL_UNSIGNED_BYTE,
1369 reinterpret_cast<const void *>(first));
1370 GLint expected = indexData[first + count - 1];
1371 GLint actual = GetFirstIntPixelRedValue();
1372 EXPECT_EQ(expected, actual);
1373 }
1374 }
1375 EXPECT_GL_NO_ERROR();
1376 }
1377
GLVertexIDIntegerTextureDrawElementsU8Line_Helper(size_t first,const GLubyte * indices)1378 void GLVertexIDIntegerTextureDrawElementsU8Line_Helper(size_t first, const GLubyte *indices)
1379 {
1380 glDrawElements(GL_LINES, 2, GL_UNSIGNED_BYTE, reinterpret_cast<const void *>(first));
1381
1382 GLint pixels[8];
1383 glReadPixels(0, 0, 2, 1, GL_RGBA_INTEGER, GL_INT, pixels);
1384
1385 GLint expected = indices[first + 1];
1386 EXPECT_EQ(expected, pixels[0]);
1387 EXPECT_EQ(expected, pixels[4]);
1388 }
1389
TEST_P(GLSLTest_ES3,GLVertexIDIntegerTextureDrawElementsU8Line)1390 TEST_P(GLSLTest_ES3, GLVertexIDIntegerTextureDrawElementsU8Line)
1391 {
1392 constexpr char kVS[] = R"(#version 300 es
1393 flat out highp int vVertexID;
1394 layout(location = 0) in vec4 position;
1395
1396 void main() {
1397 vVertexID = gl_VertexID;
1398 gl_Position = position;
1399 })";
1400
1401 constexpr char kFS[] = R"(#version 300 es
1402 flat in highp int vVertexID;
1403 out highp int oVertexID;
1404 void main() {
1405 oVertexID = vVertexID;
1406 })";
1407
1408 ANGLE_GL_PROGRAM(program, kVS, kFS);
1409 glUseProgram(program);
1410 glViewport(0, 0, 2, 1);
1411
1412 GLTexture tex;
1413 glBindTexture(GL_TEXTURE_2D, tex);
1414 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, 2, 1);
1415 GLFramebuffer fb;
1416 glBindFramebuffer(GL_FRAMEBUFFER, fb);
1417 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
1418
1419 EXPECT_GL_NO_ERROR();
1420
1421 struct LR
1422 {
1423 LR() : X0(-1.0f), X1(1.0f) {}
1424 float X0;
1425 float X1;
1426 };
1427 constexpr int kNumVertices = 100;
1428 LR vertData[kNumVertices];
1429 GLBuffer buf;
1430 glBindBuffer(GL_ARRAY_BUFFER, buf);
1431 glBufferData(GL_ARRAY_BUFFER, sizeof(vertData), vertData, GL_STATIC_DRAW);
1432 glEnableVertexAttribArray(0);
1433 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
1434
1435 GLint clearData[4] = {42};
1436 glClearBufferiv(GL_COLOR, 0, clearData);
1437 EXPECT_EQ(42, GetFirstIntPixelRedValue());
1438
1439 GLubyte indexData[] = {1, 4, 5, 2, 50, 61};
1440 GLBuffer indexBuffer;
1441 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1442 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_STATIC_DRAW);
1443
1444 GLVertexIDIntegerTextureDrawElementsU8Line_Helper(0, indexData);
1445 GLVertexIDIntegerTextureDrawElementsU8Line_Helper(1, indexData);
1446 GLVertexIDIntegerTextureDrawElementsU8Line_Helper(2, indexData);
1447 GLVertexIDIntegerTextureDrawElementsU8Line_Helper(4, indexData);
1448
1449 EXPECT_GL_NO_ERROR();
1450 }
1451
1452 // Test gl_VertexID works with lines
TEST_P(GLSLTest_ES3,GLVertexIDIntegerTextureDrawElementsU8LineIds)1453 TEST_P(GLSLTest_ES3, GLVertexIDIntegerTextureDrawElementsU8LineIds)
1454 {
1455 // Draws lines via indices (glDrawElements). Each pair of indices
1456 // draws the next consecutive pixel. For 2 points, because we're
1457 // using int attributes, they must be "flat" and so the spec
1458 // says for a given line the value should come from the second
1459 // of the 2 points. (see: OpenGL ES 3.0.2 spec Table 2.12)
1460 // Each line is only 1 pixel long so every other pixel should
1461 // be the default value.
1462 constexpr char kVS[] = R"(#version 300 es
1463 flat out highp int vVertexID;
1464 layout(location = 0) in float position;
1465 uniform float width;
1466
1467 void main() {
1468 vVertexID = gl_VertexID;
1469 gl_Position = vec4(position / width * 2.0 - 1.0, 0, 0, 1);
1470 })";
1471
1472 constexpr char kFS[] = R"(#version 300 es
1473 flat in highp int vVertexID;
1474 out highp int oVertexID;
1475 void main() {
1476 oVertexID = vVertexID;
1477 })";
1478
1479 GLubyte indexData[] = {1, 4, 5, 2, 50, 61, 32, 33};
1480 constexpr size_t kNumIndices = sizeof(indexData) / sizeof(indexData[0]);
1481 GLBuffer indexBuffer;
1482 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1483 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_STATIC_DRAW);
1484
1485 ANGLE_GL_PROGRAM(program, kVS, kFS);
1486 glUseProgram(program);
1487 glUniform1f(glGetUniformLocation(program, "width"), kNumIndices);
1488 glViewport(0, 0, kNumIndices, 1);
1489
1490 GLTexture tex;
1491 glBindTexture(GL_TEXTURE_2D, tex);
1492 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, kNumIndices, 1);
1493 GLFramebuffer fb;
1494 glBindFramebuffer(GL_FRAMEBUFFER, fb);
1495 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
1496
1497 constexpr int kNumVertices = 100;
1498 std::vector<float> vertData(kNumVertices, -1.0f);
1499 {
1500 int i = 0;
1501 for (GLubyte ndx : indexData)
1502 {
1503 vertData[ndx] = i++;
1504 }
1505 }
1506 GLBuffer buf;
1507 glBindBuffer(GL_ARRAY_BUFFER, buf);
1508 glBufferData(GL_ARRAY_BUFFER, vertData.size() * sizeof(float), vertData.data(), GL_STATIC_DRAW);
1509 glEnableVertexAttribArray(0);
1510 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
1511
1512 GLint kDefaultValue = 42;
1513 GLint clearData[4] = {kDefaultValue};
1514 glClearBufferiv(GL_COLOR, 0, clearData);
1515 EXPECT_EQ(kDefaultValue, GetFirstIntPixelRedValue());
1516
1517 EXPECT_GL_NO_ERROR();
1518
1519 glDrawElements(GL_LINES, kNumIndices, GL_UNSIGNED_BYTE, 0);
1520
1521 GLint pixels[kNumIndices * 4];
1522 glReadPixels(0, 0, kNumIndices, 1, GL_RGBA_INTEGER, GL_INT, pixels);
1523
1524 for (size_t i = 0; i < kNumIndices; ++i)
1525 {
1526 const int expected = i % 2 ? kDefaultValue : indexData[i + 1];
1527 const int actual = pixels[i * 4];
1528 EXPECT_EQ(expected, actual);
1529 }
1530
1531 EXPECT_GL_NO_ERROR();
1532 }
1533
1534 // Helper function for the GLVertexIDIntegerTextureDrawArrays test
GLVertexIDIntegerTextureDrawArrays_helper(int first,int count,GLenum err)1535 void GLVertexIDIntegerTextureDrawArrays_helper(int first, int count, GLenum err)
1536 {
1537 glDrawArrays(GL_POINTS, first, count);
1538
1539 int pixel[4];
1540 glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_INT, pixel);
1541 // If we call this function with err as GL_NO_ERROR, then we expect no error and check the
1542 // pixels.
1543 if (err == static_cast<GLenum>(GL_NO_ERROR))
1544 {
1545 EXPECT_GL_NO_ERROR();
1546 EXPECT_EQ(pixel[0], first + count - 1);
1547 }
1548 else
1549 {
1550 // If we call this function with err set, we will allow the error, but check the pixels if
1551 // the error hasn't occurred.
1552 GLenum glError = glGetError();
1553 if (glError == err || glError == static_cast<GLenum>(GL_NO_ERROR))
1554 {
1555 EXPECT_EQ(pixel[0], first + count - 1);
1556 }
1557 }
1558 }
1559
1560 // Ensure gl_VertexID gets passed to an integer texture properly when drawArrays is called. This
1561 // is based off the WebGL test:
1562 // https://github.com/KhronosGroup/WebGL/blob/master/sdk/tests/conformance2/rendering/vertex-id.html
TEST_P(GLSLTest_ES3,GLVertexIDIntegerTextureDrawArrays)1563 TEST_P(GLSLTest_ES3, GLVertexIDIntegerTextureDrawArrays)
1564 {
1565 constexpr char kVS[] = R"(#version 300 es
1566 flat out highp int vVertexID;
1567 void main() {
1568 vVertexID = gl_VertexID;
1569 gl_Position = vec4(0,0,0,1);
1570 gl_PointSize = 1.0;
1571 })";
1572
1573 constexpr char kFS[] = R"(#version 300 es
1574 flat in highp int vVertexID;
1575 out highp int oVertexID;
1576 void main() {
1577 oVertexID = vVertexID;
1578 })";
1579
1580 ANGLE_GL_PROGRAM(program, kVS, kFS);
1581 glUseProgram(program);
1582 glViewport(0, 0, 1, 1);
1583
1584 GLTexture texture;
1585 glBindTexture(GL_TEXTURE_2D, texture);
1586 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, 1, 1);
1587 GLFramebuffer fbo;
1588 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1589 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1590 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1591 EXPECT_GL_NO_ERROR();
1592
1593 // Clear the texture to 42 to ensure the first test case doesn't accidentally pass
1594 GLint val[4] = {42};
1595 glClearBufferiv(GL_COLOR, 0, val);
1596 int pixel[4];
1597 glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_INT, pixel);
1598 EXPECT_EQ(pixel[0], val[0]);
1599
1600 GLVertexIDIntegerTextureDrawArrays_helper(0, 1, GL_NO_ERROR);
1601 GLVertexIDIntegerTextureDrawArrays_helper(1, 1, GL_NO_ERROR);
1602 GLVertexIDIntegerTextureDrawArrays_helper(10000, 1, GL_NO_ERROR);
1603 GLVertexIDIntegerTextureDrawArrays_helper(100000, 1, GL_NO_ERROR);
1604 GLVertexIDIntegerTextureDrawArrays_helper(1000000, 1, GL_NO_ERROR);
1605 GLVertexIDIntegerTextureDrawArrays_helper(0, 2, GL_NO_ERROR);
1606 GLVertexIDIntegerTextureDrawArrays_helper(1, 2, GL_NO_ERROR);
1607 GLVertexIDIntegerTextureDrawArrays_helper(10000, 2, GL_NO_ERROR);
1608 GLVertexIDIntegerTextureDrawArrays_helper(100000, 2, GL_NO_ERROR);
1609 GLVertexIDIntegerTextureDrawArrays_helper(1000000, 2, GL_NO_ERROR);
1610
1611 int32_t int32Max = 0x7FFFFFFF;
1612 GLVertexIDIntegerTextureDrawArrays_helper(int32Max - 2, 1, GL_OUT_OF_MEMORY);
1613 GLVertexIDIntegerTextureDrawArrays_helper(int32Max - 1, 1, GL_OUT_OF_MEMORY);
1614 }
1615
1616 // Draw an array of points with the first vertex offset at 5 using gl_VertexID
TEST_P(GLSLTest_ES3,GLVertexIDOffsetFiveDrawArray)1617 TEST_P(GLSLTest_ES3, GLVertexIDOffsetFiveDrawArray)
1618 {
1619 // Bug in Nexus drivers, offset does not work. (anglebug.com/42261941)
1620 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsOpenGLES());
1621
1622 constexpr int kStartIndex = 5;
1623 constexpr int kArrayLength = 5;
1624 constexpr char kVS[] = R"(#version 300 es
1625 precision highp float;
1626 void main() {
1627 gl_Position = vec4(float(gl_VertexID)/10.0, 0, 0, 1);
1628 gl_PointSize = 3.0;
1629 })";
1630
1631 constexpr char kFS[] = R"(#version 300 es
1632 precision highp float;
1633 out vec4 outColor;
1634 void main() {
1635 outColor = vec4(1.0, 0.0, 0.0, 1.0);
1636 })";
1637
1638 ANGLE_GL_PROGRAM(program, kVS, kFS);
1639
1640 glUseProgram(program);
1641 glDrawArrays(GL_POINTS, kStartIndex, kArrayLength);
1642
1643 double pointCenterX = static_cast<double>(getWindowWidth()) / 2.0;
1644 double pointCenterY = static_cast<double>(getWindowHeight()) / 2.0;
1645 for (int i = kStartIndex; i < kStartIndex + kArrayLength; i++)
1646 {
1647 double pointOffsetX = static_cast<double>(i * getWindowWidth()) / 20.0;
1648 EXPECT_PIXEL_COLOR_EQ(static_cast<int>(pointCenterX + pointOffsetX),
1649 static_cast<int>(pointCenterY), GLColor::red);
1650 }
1651 }
1652
TEST_P(GLSLTest,ElseIfRewriting)1653 TEST_P(GLSLTest, ElseIfRewriting)
1654 {
1655 constexpr char kVS[] =
1656 "attribute vec4 a_position;\n"
1657 "varying float v;\n"
1658 "void main() {\n"
1659 " gl_Position = a_position;\n"
1660 " v = 1.0;\n"
1661 " if (a_position.x <= 0.5) {\n"
1662 " v = 0.0;\n"
1663 " } else if (a_position.x >= 0.5) {\n"
1664 " v = 2.0;\n"
1665 " }\n"
1666 "}\n";
1667
1668 constexpr char kFS[] =
1669 "precision highp float;\n"
1670 "varying float v;\n"
1671 "void main() {\n"
1672 " vec4 color = vec4(1.0, 0.0, 0.0, 1.0);\n"
1673 " if (v >= 1.0) color = vec4(0.0, 1.0, 0.0, 1.0);\n"
1674 " if (v >= 2.0) color = vec4(0.0, 0.0, 1.0, 1.0);\n"
1675 " gl_FragColor = color;\n"
1676 "}\n";
1677
1678 ANGLE_GL_PROGRAM(program, kVS, kFS);
1679
1680 drawQuad(program, "a_position", 0.5f);
1681
1682 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
1683 EXPECT_PIXEL_EQ(getWindowWidth() - 1, 0, 0, 255, 0, 255);
1684 }
1685
TEST_P(GLSLTest,TwoElseIfRewriting)1686 TEST_P(GLSLTest, TwoElseIfRewriting)
1687 {
1688 constexpr char kVS[] =
1689 "attribute vec4 a_position;\n"
1690 "varying float v;\n"
1691 "void main() {\n"
1692 " gl_Position = a_position;\n"
1693 " if (a_position.x == 0.0) {\n"
1694 " v = 1.0;\n"
1695 " } else if (a_position.x > 0.5) {\n"
1696 " v = 0.0;\n"
1697 " } else if (a_position.x > 0.75) {\n"
1698 " v = 0.5;\n"
1699 " }\n"
1700 "}\n";
1701
1702 constexpr char kFS[] =
1703 "precision highp float;\n"
1704 "varying float v;\n"
1705 "void main() {\n"
1706 " gl_FragColor = vec4(v, 0.0, 0.0, 1.0);\n"
1707 "}\n";
1708
1709 ANGLE_GL_PROGRAM(program, kVS, kFS);
1710 }
1711
TEST_P(GLSLTest,FrontFacingAndVarying)1712 TEST_P(GLSLTest, FrontFacingAndVarying)
1713 {
1714 EGLPlatformParameters platform = GetParam().eglParameters;
1715
1716 constexpr char kVS[] = R"(attribute vec4 a_position;
1717 varying float v_varying;
1718 void main()
1719 {
1720 v_varying = a_position.x;
1721 gl_Position = a_position;
1722 })";
1723
1724 constexpr char kFS[] = R"(precision mediump float;
1725 varying float v_varying;
1726 void main()
1727 {
1728 vec4 c;
1729
1730 if (gl_FrontFacing)
1731 {
1732 c = vec4(v_varying, 0, 0, 1.0);
1733 }
1734 else
1735 {
1736 c = vec4(0, v_varying, 0, 1.0);
1737 }
1738 gl_FragColor = c;
1739 })";
1740
1741 GLuint program = CompileProgram(kVS, kFS);
1742
1743 // Compilation should fail on D3D11 feature level 9_3, since gl_FrontFacing isn't supported.
1744 if (platform.renderer == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
1745 {
1746 if (platform.majorVersion == 9 && platform.minorVersion == 3)
1747 {
1748 EXPECT_EQ(0u, program);
1749 return;
1750 }
1751 }
1752
1753 // Otherwise, compilation should succeed
1754 EXPECT_NE(0u, program);
1755 }
1756
1757 // Test that we can release the shader compiler and still compile things properly.
TEST_P(GLSLTest,ReleaseCompilerThenCompile)1758 TEST_P(GLSLTest, ReleaseCompilerThenCompile)
1759 {
1760 // Draw with the first program.
1761 ANGLE_GL_PROGRAM(program1, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
1762 drawQuad(program1, essl1_shaders::PositionAttrib(), 0.5f);
1763 ASSERT_GL_NO_ERROR();
1764 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1765
1766 // Clear and release shader compiler.
1767 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
1768 glClear(GL_COLOR_BUFFER_BIT);
1769 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1770 glReleaseShaderCompiler();
1771 ASSERT_GL_NO_ERROR();
1772
1773 // Draw with a second program.
1774 ANGLE_GL_PROGRAM(program2, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
1775 drawQuad(program2, essl1_shaders::PositionAttrib(), 0.5f);
1776 ASSERT_GL_NO_ERROR();
1777 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1778 }
1779
1780 // Verify that linking shaders declaring different shading language versions fails.
TEST_P(GLSLTest_ES3,VersionMismatch)1781 TEST_P(GLSLTest_ES3, VersionMismatch)
1782 {
1783 GLuint program = CompileProgram(essl3_shaders::vs::Simple(), essl1_shaders::fs::Red());
1784 EXPECT_EQ(0u, program);
1785
1786 program = CompileProgram(essl1_shaders::vs::Simple(), essl3_shaders::fs::Red());
1787 EXPECT_EQ(0u, program);
1788 }
1789
1790 // Verify that declaring varying as invariant only in vertex shader fails in ESSL 1.00.
TEST_P(GLSLTest,InvariantVaryingOut)1791 TEST_P(GLSLTest, InvariantVaryingOut)
1792 {
1793 constexpr char kFS[] =
1794 "precision mediump float;\n"
1795 "varying float v_varying;\n"
1796 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1797
1798 constexpr char kVS[] =
1799 "attribute vec4 a_position;\n"
1800 "invariant varying float v_varying;\n"
1801 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1802
1803 GLuint program = CompileProgram(kVS, kFS);
1804 EXPECT_EQ(0u, program);
1805 }
1806
1807 // Verify that declaring varying as invariant only in vertex shader succeeds in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantVaryingOut)1808 TEST_P(GLSLTest_ES3, InvariantVaryingOut)
1809 {
1810 // TODO: ESSL 3.00 -> GLSL 1.20 translation should add "invariant" in fragment shader
1811 // for varyings which are invariant in vertex shader (http://anglebug.com/40096344)
1812 ANGLE_SKIP_TEST_IF(IsDesktopOpenGL());
1813
1814 constexpr char kFS[] =
1815 "#version 300 es\n"
1816 "precision mediump float;\n"
1817 "in float v_varying;\n"
1818 "out vec4 my_FragColor;\n"
1819 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1820
1821 constexpr char kVS[] =
1822 "#version 300 es\n"
1823 "in vec4 a_position;\n"
1824 "invariant out float v_varying;\n"
1825 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1826
1827 GLuint program = CompileProgram(kVS, kFS);
1828 EXPECT_NE(0u, program);
1829 }
1830
1831 // Verify that declaring varying as invariant only in fragment shader fails in ESSL 1.00.
TEST_P(GLSLTest,InvariantVaryingIn)1832 TEST_P(GLSLTest, InvariantVaryingIn)
1833 {
1834 constexpr char kFS[] =
1835 "precision mediump float;\n"
1836 "invariant varying float v_varying;\n"
1837 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1838
1839 constexpr char kVS[] =
1840 "attribute vec4 a_position;\n"
1841 "varying float v_varying;\n"
1842 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1843
1844 GLuint program = CompileProgram(kVS, kFS);
1845 EXPECT_EQ(0u, program);
1846 }
1847
1848 // Verify that declaring varying as invariant only in fragment shader fails in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantVaryingIn)1849 TEST_P(GLSLTest_ES3, InvariantVaryingIn)
1850 {
1851 constexpr char kFS[] =
1852 "#version 300 es\n"
1853 "precision mediump float;\n"
1854 "invariant in float v_varying;\n"
1855 "out vec4 my_FragColor;\n"
1856 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1857
1858 constexpr char kVS[] =
1859 "#version 300 es\n"
1860 "in vec4 a_position;\n"
1861 "out float v_varying;\n"
1862 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1863
1864 GLuint program = CompileProgram(kVS, kFS);
1865 EXPECT_EQ(0u, program);
1866 }
1867
1868 // Verify that declaring varying as invariant in both shaders succeeds in ESSL 1.00.
TEST_P(GLSLTest,InvariantVaryingBoth)1869 TEST_P(GLSLTest, InvariantVaryingBoth)
1870 {
1871 constexpr char kFS[] =
1872 "precision mediump float;\n"
1873 "invariant varying float v_varying;\n"
1874 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1875
1876 constexpr char kVS[] =
1877 "attribute vec4 a_position;\n"
1878 "invariant varying float v_varying;\n"
1879 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1880
1881 GLuint program = CompileProgram(kVS, kFS);
1882 EXPECT_NE(0u, program);
1883 }
1884
1885 // Verify that declaring varying as invariant in both shaders fails in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantVaryingBoth)1886 TEST_P(GLSLTest_ES3, InvariantVaryingBoth)
1887 {
1888 constexpr char kFS[] =
1889 "#version 300 es\n"
1890 "precision mediump float;\n"
1891 "invariant in float v_varying;\n"
1892 "out vec4 my_FragColor;\n"
1893 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1894
1895 constexpr char kVS[] =
1896 "#version 300 es\n"
1897 "in vec4 a_position;\n"
1898 "invariant out float v_varying;\n"
1899 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1900
1901 GLuint program = CompileProgram(kVS, kFS);
1902 EXPECT_EQ(0u, program);
1903 }
1904
1905 // Verify that declaring gl_Position as invariant succeeds in ESSL 1.00.
TEST_P(GLSLTest,InvariantGLPosition)1906 TEST_P(GLSLTest, InvariantGLPosition)
1907 {
1908 constexpr char kFS[] =
1909 "precision mediump float;\n"
1910 "varying float v_varying;\n"
1911 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1912
1913 constexpr char kVS[] =
1914 "attribute vec4 a_position;\n"
1915 "invariant gl_Position;\n"
1916 "varying float v_varying;\n"
1917 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1918
1919 GLuint program = CompileProgram(kVS, kFS);
1920 EXPECT_NE(0u, program);
1921 }
1922
1923 // Verify that declaring gl_Position as invariant succeeds in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantGLPosition)1924 TEST_P(GLSLTest_ES3, InvariantGLPosition)
1925 {
1926 constexpr char kFS[] =
1927 "#version 300 es\n"
1928 "precision mediump float;\n"
1929 "in float v_varying;\n"
1930 "out vec4 my_FragColor;\n"
1931 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1932
1933 constexpr char kVS[] =
1934 "#version 300 es\n"
1935 "in vec4 a_position;\n"
1936 "invariant gl_Position;\n"
1937 "out float v_varying;\n"
1938 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1939
1940 GLuint program = CompileProgram(kVS, kFS);
1941 EXPECT_NE(0u, program);
1942 }
1943
1944 // Verify that using invariant(all) in both shaders fails in ESSL 1.00.
TEST_P(GLSLTest,InvariantAllBoth)1945 TEST_P(GLSLTest, InvariantAllBoth)
1946 {
1947 constexpr char kFS[] =
1948 "#pragma STDGL invariant(all)\n"
1949 "precision mediump float;\n"
1950 "varying float v_varying;\n"
1951 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1952
1953 constexpr char kVS[] =
1954 "#pragma STDGL invariant(all)\n"
1955 "attribute vec4 a_position;\n"
1956 "varying float v_varying;\n"
1957 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1958
1959 GLuint program = CompileProgram(kVS, kFS);
1960 EXPECT_EQ(0u, program);
1961 }
1962
1963 // Verify that using a struct as both invariant and non-invariant output works.
TEST_P(GLSLTest_ES31,StructBothInvariantAndNot)1964 TEST_P(GLSLTest_ES31, StructBothInvariantAndNot)
1965 {
1966 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
1967
1968 constexpr char kVS[] = R"(#version 310 es
1969 #extension GL_EXT_shader_io_blocks : require
1970
1971 struct S
1972 {
1973 vec4 s;
1974 };
1975
1976 out Output
1977 {
1978 vec4 x;
1979 invariant S s;
1980 };
1981
1982 out S s2;
1983
1984 void main(){
1985 x = vec4(0);
1986 s.s = vec4(1);
1987 s2.s = vec4(2);
1988 S s3 = s;
1989 s.s = s3.s;
1990 })";
1991
1992 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
1993 EXPECT_NE(0u, shader);
1994 glDeleteShader(shader);
1995 }
1996
1997 // Verify that using maximum size as atomic counter offset results in compilation failure.
TEST_P(GLSLTest_ES31,CompileWithMaxAtomicCounterOffsetFails)1998 TEST_P(GLSLTest_ES31, CompileWithMaxAtomicCounterOffsetFails)
1999 {
2000 GLint maxSize;
2001 glGetIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE, &maxSize);
2002
2003 std::ostringstream srcStream;
2004 srcStream << "#version 310 es\n"
2005 << "layout(location = 0) out uvec4 color;\n"
2006 << "layout(binding = 0, offset = " << maxSize << ") uniform atomic_uint a_counter;\n"
2007 << "void main() {\n"
2008 << "color = uvec4(atomicCounterIncrement(a_counter)); \n"
2009 << "}";
2010 std::string fsStream = srcStream.str();
2011 const char *strFS = fsStream.c_str();
2012
2013 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, strFS);
2014 EXPECT_EQ(0u, shader);
2015 }
2016
2017 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnFloat)2018 TEST_P(GLSLTest, MissingReturnFloat)
2019 {
2020 constexpr char kVS[] =
2021 "varying float v_varying;\n"
2022 "float f() { if (v_varying > 0.0) return 1.0; }\n"
2023 "void main() { gl_Position = vec4(f(), 0, 0, 1); }\n";
2024
2025 GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
2026 EXPECT_NE(0u, program);
2027 }
2028
2029 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnVec2)2030 TEST_P(GLSLTest, MissingReturnVec2)
2031 {
2032 constexpr char kVS[] =
2033 "varying float v_varying;\n"
2034 "vec2 f() { if (v_varying > 0.0) return vec2(1.0, 1.0); }\n"
2035 "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
2036
2037 GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
2038 EXPECT_NE(0u, program);
2039 }
2040
2041 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnVec3)2042 TEST_P(GLSLTest, MissingReturnVec3)
2043 {
2044 constexpr char kVS[] =
2045 "varying float v_varying;\n"
2046 "vec3 f() { if (v_varying > 0.0) return vec3(1.0, 1.0, 1.0); }\n"
2047 "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
2048
2049 GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
2050 EXPECT_NE(0u, program);
2051 }
2052
2053 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnVec4)2054 TEST_P(GLSLTest, MissingReturnVec4)
2055 {
2056 constexpr char kVS[] =
2057 "varying float v_varying;\n"
2058 "vec4 f() { if (v_varying > 0.0) return vec4(1.0, 1.0, 1.0, 1.0); }\n"
2059 "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
2060
2061 GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
2062 EXPECT_NE(0u, program);
2063 }
2064
2065 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnIVec4)2066 TEST_P(GLSLTest, MissingReturnIVec4)
2067 {
2068 constexpr char kVS[] =
2069 "varying float v_varying;\n"
2070 "ivec4 f() { if (v_varying > 0.0) return ivec4(1, 1, 1, 1); }\n"
2071 "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
2072
2073 GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
2074 EXPECT_NE(0u, program);
2075 }
2076
2077 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnMat4)2078 TEST_P(GLSLTest, MissingReturnMat4)
2079 {
2080 constexpr char kVS[] =
2081 "varying float v_varying;\n"
2082 "mat4 f() { if (v_varying > 0.0) return mat4(1.0); }\n"
2083 "void main() { gl_Position = vec4(f()[0][0], 0, 0, 1); }\n";
2084
2085 GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
2086 EXPECT_NE(0u, program);
2087 }
2088
2089 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnStruct)2090 TEST_P(GLSLTest, MissingReturnStruct)
2091 {
2092 constexpr char kVS[] =
2093 "varying float v_varying;\n"
2094 "struct s { float a; int b; vec2 c; };\n"
2095 "s f() { if (v_varying > 0.0) return s(1.0, 1, vec2(1.0, 1.0)); }\n"
2096 "void main() { gl_Position = vec4(f().a, 0, 0, 1); }\n";
2097
2098 GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
2099 EXPECT_NE(0u, program);
2100 }
2101
2102 // Verify that functions without return statements still compile
TEST_P(GLSLTest_ES3,MissingReturnArray)2103 TEST_P(GLSLTest_ES3, MissingReturnArray)
2104 {
2105 constexpr char kVS[] =
2106 "#version 300 es\n"
2107 "in float v_varying;\n"
2108 "vec2[2] f() { if (v_varying > 0.0) { return vec2[2](vec2(1.0, 1.0), vec2(1.0, 1.0)); } }\n"
2109 "void main() { gl_Position = vec4(f()[0].x, 0, 0, 1); }\n";
2110
2111 GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
2112 EXPECT_NE(0u, program);
2113 }
2114
2115 // Verify that functions without return statements still compile
TEST_P(GLSLTest_ES3,MissingReturnArrayOfStructs)2116 TEST_P(GLSLTest_ES3, MissingReturnArrayOfStructs)
2117 {
2118 constexpr char kVS[] =
2119 "#version 300 es\n"
2120 "in float v_varying;\n"
2121 "struct s { float a; int b; vec2 c; };\n"
2122 "s[2] f() { if (v_varying > 0.0) { return s[2](s(1.0, 1, vec2(1.0, 1.0)), s(1.0, 1, "
2123 "vec2(1.0, 1.0))); } }\n"
2124 "void main() { gl_Position = vec4(f()[0].a, 0, 0, 1); }\n";
2125
2126 GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
2127 EXPECT_NE(0u, program);
2128 }
2129
2130 // Verify that functions without return statements still compile
TEST_P(GLSLTest_ES3,MissingReturnStructOfArrays)2131 TEST_P(GLSLTest_ES3, MissingReturnStructOfArrays)
2132 {
2133 // TODO(crbug.com/998505): Test failing on Android FYI Release (NVIDIA Shield TV)
2134 ANGLE_SKIP_TEST_IF(IsNVIDIAShield());
2135
2136 constexpr char kVS[] =
2137 "#version 300 es\n"
2138 "in float v_varying;\n"
2139 "struct s { float a[2]; int b[2]; vec2 c[2]; };\n"
2140 "s f() { if (v_varying > 0.0) { return s(float[2](1.0, 1.0), int[2](1, 1),"
2141 "vec2[2](vec2(1.0, 1.0), vec2(1.0, 1.0))); } }\n"
2142 "void main() { gl_Position = vec4(f().a[0], 0, 0, 1); }\n";
2143
2144 GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
2145 EXPECT_NE(0u, program);
2146 }
2147
2148 // Verify that non-const index used on an array returned by a function compiles
TEST_P(GLSLTest_ES3,ReturnArrayOfStructsThenNonConstIndex)2149 TEST_P(GLSLTest_ES3, ReturnArrayOfStructsThenNonConstIndex)
2150 {
2151 constexpr char kVS[] = R"(#version 300 es
2152 in float v_varying;
2153 struct s { float a; int b; vec2 c; };
2154 s[2] f()
2155 {
2156 return s[2](s(v_varying, 1, vec2(1.0, 1.0)), s(v_varying / 2.0, 1, vec2(1.0, 1.0)));
2157 }
2158 void main()
2159 {
2160 gl_Position = vec4(f()[uint(v_varying)].a, 0, 0, 1);
2161 })";
2162
2163 GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
2164 EXPECT_NE(0u, program);
2165 }
2166
2167 // Verify that using invariant(all) in both shaders fails in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantAllBoth)2168 TEST_P(GLSLTest_ES3, InvariantAllBoth)
2169 {
2170 constexpr char kFS[] =
2171 "#version 300 es\n"
2172 "#pragma STDGL invariant(all)\n"
2173 "precision mediump float;\n"
2174 "in float v_varying;\n"
2175 "out vec4 my_FragColor;\n"
2176 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
2177
2178 constexpr char kVS[] =
2179 "#version 300 es\n"
2180 "#pragma STDGL invariant(all)\n"
2181 "in vec4 a_position;\n"
2182 "out 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_EQ(0u, program);
2187 }
2188
2189 // Verify that using invariant(all) only in fragment shader succeeds in ESSL 1.00.
TEST_P(GLSLTest,InvariantAllIn)2190 TEST_P(GLSLTest, InvariantAllIn)
2191 {
2192 constexpr char kFS[] =
2193 "#pragma STDGL invariant(all)\n"
2194 "precision mediump float;\n"
2195 "varying float v_varying;\n"
2196 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
2197
2198 constexpr char kVS[] =
2199 "attribute vec4 a_position;\n"
2200 "varying float v_varying;\n"
2201 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
2202
2203 GLuint program = CompileProgram(kVS, kFS);
2204 EXPECT_NE(0u, program);
2205 }
2206
2207 // Verify that using invariant(all) only in fragment shader fails in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantAllIn)2208 TEST_P(GLSLTest_ES3, InvariantAllIn)
2209 {
2210 constexpr char kFS[] =
2211 "#version 300 es\n"
2212 "#pragma STDGL invariant(all)\n"
2213 "precision mediump float;\n"
2214 "in float v_varying;\n"
2215 "out vec4 my_FragColor;\n"
2216 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
2217
2218 constexpr char kVS[] =
2219 "#version 300 es\n"
2220 "in vec4 a_position;\n"
2221 "out 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 fails in ESSL 1.00.
TEST_P(GLSLTest,InvariantAllOut)2229 TEST_P(GLSLTest, InvariantAllOut)
2230 {
2231 constexpr char kFS[] =
2232 "precision mediump float;\n"
2233 "varying float v_varying;\n"
2234 "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
2235
2236 constexpr char kVS[] =
2237 "#pragma STDGL invariant(all)\n"
2238 "attribute vec4 a_position;\n"
2239 "varying float v_varying;\n"
2240 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
2241
2242 GLuint program = CompileProgram(kVS, kFS);
2243 EXPECT_EQ(0u, program);
2244 }
2245
2246 // Verify that using invariant(all) only in vertex shader succeeds in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantAllOut)2247 TEST_P(GLSLTest_ES3, InvariantAllOut)
2248 {
2249 // TODO: ESSL 3.00 -> GLSL 1.20 translation should add "invariant" in fragment shader
2250 // for varyings which are invariant in vertex shader,
2251 // because of invariant(all) being used in vertex shader (http://anglebug.com/40096344)
2252 ANGLE_SKIP_TEST_IF(IsDesktopOpenGL());
2253
2254 constexpr char kFS[] =
2255 "#version 300 es\n"
2256 "precision mediump float;\n"
2257 "in float v_varying;\n"
2258 "out vec4 my_FragColor;\n"
2259 "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
2260
2261 constexpr char kVS[] =
2262 "#version 300 es\n"
2263 "#pragma STDGL invariant(all)\n"
2264 "in vec4 a_position;\n"
2265 "out float v_varying;\n"
2266 "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
2267
2268 GLuint program = CompileProgram(kVS, kFS);
2269 EXPECT_NE(0u, program);
2270 }
2271
TEST_P(GLSLTest,MaxVaryingVec4)2272 TEST_P(GLSLTest, MaxVaryingVec4)
2273 {
2274 // TODO(geofflang): Find out why this doesn't compile on Apple AMD OpenGL drivers
2275 // (http://anglebug.com/42260302)
2276 ANGLE_SKIP_TEST_IF(IsMac() && IsAMD() && IsOpenGL());
2277
2278 GLint maxVaryings = 0;
2279 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2280
2281 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, false, false, false, true);
2282 }
2283
2284 // Verify we can pack registers with one builtin varying.
TEST_P(GLSLTest,MaxVaryingVec4_OneBuiltin)2285 TEST_P(GLSLTest, MaxVaryingVec4_OneBuiltin)
2286 {
2287 GLint maxVaryings = 0;
2288 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2289
2290 // Generate shader code that uses gl_FragCoord.
2291 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 1, 0, true, false, false, true);
2292 }
2293
2294 // Verify we can pack registers with two builtin varyings.
TEST_P(GLSLTest,MaxVaryingVec4_TwoBuiltins)2295 TEST_P(GLSLTest, MaxVaryingVec4_TwoBuiltins)
2296 {
2297 GLint maxVaryings = 0;
2298 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2299
2300 // Generate shader code that uses gl_FragCoord and gl_PointCoord.
2301 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 2, 0, true, true, false, true);
2302 }
2303
2304 // Verify we can pack registers with three builtin varyings.
TEST_P(GLSLTest,MaxVaryingVec4_ThreeBuiltins)2305 TEST_P(GLSLTest, MaxVaryingVec4_ThreeBuiltins)
2306 {
2307 GLint maxVaryings = 0;
2308 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2309
2310 // Generate shader code that uses gl_FragCoord, gl_PointCoord and gl_PointSize.
2311 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 3, 0, true, true, true, true);
2312 }
2313
2314 // This covers a problematic case in D3D9 - we are limited by the number of available semantics,
2315 // rather than total register use.
TEST_P(GLSLTest,MaxVaryingsSpecialCases)2316 TEST_P(GLSLTest, MaxVaryingsSpecialCases)
2317 {
2318 ANGLE_SKIP_TEST_IF(!IsD3D9());
2319
2320 GLint maxVaryings = 0;
2321 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2322
2323 VaryingTestBase(maxVaryings, 0, 0, 0, 0, 0, 0, 0, true, false, false, false);
2324 VaryingTestBase(maxVaryings - 1, 0, 0, 0, 0, 0, 0, 0, true, true, false, false);
2325 VaryingTestBase(maxVaryings - 2, 0, 0, 0, 0, 0, 0, 0, true, true, false, true);
2326
2327 // Special case for gl_PointSize: we get it for free on D3D9.
2328 VaryingTestBase(maxVaryings - 2, 0, 0, 0, 0, 0, 0, 0, true, true, true, true);
2329 }
2330
2331 // This covers a problematic case in D3D9 - we are limited by the number of available semantics,
2332 // rather than total register use.
TEST_P(GLSLTest,MaxMinusTwoVaryingVec2PlusOneSpecialVariable)2333 TEST_P(GLSLTest, MaxMinusTwoVaryingVec2PlusOneSpecialVariable)
2334 {
2335 GLint maxVaryings = 0;
2336 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2337
2338 // Generate shader code that uses gl_FragCoord.
2339 VaryingTestBase(0, 0, maxVaryings, 0, 0, 0, 0, 0, true, false, false, !IsD3D9());
2340 }
2341
TEST_P(GLSLTest,MaxVaryingVec3)2342 TEST_P(GLSLTest, MaxVaryingVec3)
2343 {
2344 GLint maxVaryings = 0;
2345 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2346
2347 VaryingTestBase(0, 0, 0, 0, maxVaryings, 0, 0, 0, false, false, false, true);
2348 }
2349
TEST_P(GLSLTest,MaxVaryingVec3Array)2350 TEST_P(GLSLTest, MaxVaryingVec3Array)
2351 {
2352 GLint maxVaryings = 0;
2353 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2354
2355 VaryingTestBase(0, 0, 0, 0, 0, maxVaryings / 2, 0, 0, false, false, false, true);
2356 }
2357
2358 // Only fails on D3D9 because of packing limitations.
TEST_P(GLSLTest,MaxVaryingVec3AndOneFloat)2359 TEST_P(GLSLTest, MaxVaryingVec3AndOneFloat)
2360 {
2361 GLint maxVaryings = 0;
2362 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2363
2364 VaryingTestBase(1, 0, 0, 0, maxVaryings, 0, 0, 0, false, false, false, !IsD3D9());
2365 }
2366
2367 // Only fails on D3D9 because of packing limitations.
TEST_P(GLSLTest,MaxVaryingVec3ArrayAndOneFloatArray)2368 TEST_P(GLSLTest, MaxVaryingVec3ArrayAndOneFloatArray)
2369 {
2370 GLint maxVaryings = 0;
2371 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2372
2373 VaryingTestBase(0, 1, 0, 0, 0, maxVaryings / 2, 0, 0, false, false, false, !IsD3D9());
2374 }
2375
2376 // Only fails on D3D9 because of packing limitations.
TEST_P(GLSLTest,TwiceMaxVaryingVec2)2377 TEST_P(GLSLTest, TwiceMaxVaryingVec2)
2378 {
2379 // TODO(geofflang): Figure out why this fails on NVIDIA's GLES driver
2380 // (http://anglebug.com/42262492)
2381 ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGLES());
2382
2383 // TODO(geofflang): Find out why this doesn't compile on Apple AMD OpenGL drivers
2384 // (http://anglebug.com/42260302)
2385 ANGLE_SKIP_TEST_IF(IsMac() && IsAMD() && IsOpenGL());
2386
2387 GLint maxVaryings = 0;
2388 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2389
2390 VaryingTestBase(0, 0, 2 * maxVaryings, 0, 0, 0, 0, 0, false, false, false, !IsD3D9());
2391 }
2392
2393 // Disabled because of a failure in D3D9
TEST_P(GLSLTest,MaxVaryingVec2Arrays)2394 TEST_P(GLSLTest, MaxVaryingVec2Arrays)
2395 {
2396 ANGLE_SKIP_TEST_IF(IsD3D9());
2397
2398 // TODO(geofflang): Figure out why this fails on NVIDIA's GLES driver
2399 ANGLE_SKIP_TEST_IF(IsOpenGLES());
2400
2401 // TODO(geofflang): Find out why this doesn't compile on Apple AMD OpenGL drivers
2402 // (http://anglebug.com/42260302)
2403 ANGLE_SKIP_TEST_IF(IsMac() && IsAMD() && IsOpenGL());
2404
2405 GLint maxVaryings = 0;
2406 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2407
2408 // Special case: because arrays of mat2 are packed as small grids of two rows by two columns,
2409 // we should be aware that when we're packing into an odd number of varying registers the
2410 // last row will be empty and can not fit the final vec2 arrary.
2411 GLint maxVec2Arrays = (maxVaryings >> 1) << 1;
2412
2413 VaryingTestBase(0, 0, 0, maxVec2Arrays, 0, 0, 0, 0, false, false, false, true);
2414 }
2415
2416 // Verify max varying with feedback and gl_line enabled
TEST_P(GLSLTest_ES3,MaxVaryingWithFeedbackAndGLline)2417 TEST_P(GLSLTest_ES3, MaxVaryingWithFeedbackAndGLline)
2418 {
2419 // (http://anglebug.com/42263058)
2420 ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsVulkan());
2421
2422 // http://anglebug.com/42263066
2423 ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
2424
2425 GLint maxVaryings = 0;
2426 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2427
2428 std::stringstream vertexShaderSource;
2429 std::stringstream fragmentShaderSource;
2430
2431 // substract 1 here for gl_PointSize
2432 const GLint vec4Count = maxVaryings - 1;
2433 unsigned int varyingCount = 0;
2434 std::string varyingDeclaration;
2435 for (GLint i = 0; i < vec4Count; i++)
2436 {
2437 varyingDeclaration += GenerateVectorVaryingDeclaration(4, 1, varyingCount);
2438 varyingCount += 1;
2439 }
2440 // Generate the vertex shader
2441 vertexShaderSource.clear();
2442 vertexShaderSource << varyingDeclaration;
2443 vertexShaderSource << "\nattribute vec4 a_position;\n";
2444 vertexShaderSource << "\nvoid main()\n{\n";
2445 unsigned int currentVSVarying = 0;
2446 for (GLint i = 0; i < vec4Count; i++)
2447 {
2448 vertexShaderSource << GenerateVectorVaryingSettingCode(4, 1, currentVSVarying);
2449 currentVSVarying += 1;
2450 }
2451 vertexShaderSource << "\tgl_Position = vec4(a_position.rgb, 1);\n";
2452 vertexShaderSource << "\tgl_PointSize = 1.0;\n";
2453 vertexShaderSource << "}\n";
2454
2455 // Generate the fragment shader
2456 fragmentShaderSource.clear();
2457 fragmentShaderSource << "precision highp float;\n";
2458 fragmentShaderSource << varyingDeclaration;
2459 fragmentShaderSource << "\nvoid main() \n{ \n\tvec4 retColor = vec4(0,0,0,0);\n";
2460 unsigned int currentFSVarying = 0;
2461 // Make use of the vec4 varyings
2462 fragmentShaderSource << "\tretColor += ";
2463 for (GLint i = 0; i < vec4Count; i++)
2464 {
2465 fragmentShaderSource << GenerateVectorVaryingUseCode(1, currentFSVarying);
2466 currentFSVarying += 1;
2467 }
2468 fragmentShaderSource << "vec4(0.0, 0.0, 0.0, 0.0);\n";
2469 constexpr GLuint testValue = 234;
2470 fragmentShaderSource << "\tgl_FragColor = (retColor/vec4(" << std::to_string(currentFSVarying)
2471 << ")) /255.0*" << std::to_string(testValue) << ".0;\n";
2472 fragmentShaderSource << "}\n";
2473
2474 std::vector<std::string> tfVaryings = {"gl_Position", "gl_PointSize"};
2475 ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(program1, vertexShaderSource.str().c_str(),
2476 fragmentShaderSource.str().c_str(), tfVaryings,
2477 GL_INTERLEAVED_ATTRIBS);
2478
2479 GLBuffer xfbBuffer;
2480 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfbBuffer);
2481 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 6 * (sizeof(float[4]) + sizeof(float)), nullptr,
2482 GL_STATIC_DRAW);
2483
2484 GLTransformFeedback xfb;
2485 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, xfb);
2486 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, xfbBuffer);
2487
2488 glUseProgram(program1);
2489
2490 const GLint positionLocation = glGetAttribLocation(program1, essl1_shaders::PositionAttrib());
2491 GLBuffer vertexBuffer;
2492 // need to shift half pixel to make sure the line covers the center of the pixel
2493 const Vector3 vertices[2] = {
2494 {-1.0f, -1.0f + 0.5f / static_cast<float>(getWindowHeight()), 0.0f},
2495 {1.0f, -1.0f + 0.5f / static_cast<float>(getWindowHeight()), 0.0f}};
2496 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
2497 glBufferData(GL_ARRAY_BUFFER, sizeof(*vertices) * 2, vertices, GL_STATIC_DRAW);
2498 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
2499 glEnableVertexAttribArray(positionLocation);
2500
2501 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
2502 glClear(GL_COLOR_BUFFER_BIT);
2503
2504 glBeginTransformFeedback(GL_LINES);
2505 glDrawArrays(GL_LINES, 0, 2);
2506 glEndTransformFeedback();
2507
2508 ASSERT_GL_NO_ERROR();
2509
2510 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(testValue, testValue, testValue, testValue));
2511 }
2512
2513 // Verify shader source with a fixed length that is less than the null-terminated length will
2514 // compile.
TEST_P(GLSLTest,FixedShaderLength)2515 TEST_P(GLSLTest, FixedShaderLength)
2516 {
2517 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
2518
2519 const std::string appendGarbage = "abcdefghijklmnopqrstuvwxyz";
2520 const std::string source = "void main() { gl_FragColor = vec4(0, 0, 0, 0); }" + appendGarbage;
2521 const char *sourceArray[1] = {source.c_str()};
2522 GLint lengths[1] = {static_cast<GLint>(source.length() - appendGarbage.length())};
2523 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
2524 glCompileShader(shader);
2525
2526 GLint compileResult;
2527 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
2528 EXPECT_NE(compileResult, 0);
2529 }
2530
2531 // Verify that a negative shader source length is treated as a null-terminated length.
TEST_P(GLSLTest,NegativeShaderLength)2532 TEST_P(GLSLTest, NegativeShaderLength)
2533 {
2534 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
2535
2536 const char *sourceArray[1] = {essl1_shaders::fs::Red()};
2537 GLint lengths[1] = {-10};
2538 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
2539 glCompileShader(shader);
2540
2541 GLint compileResult;
2542 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
2543 EXPECT_NE(compileResult, 0);
2544 }
2545
2546 // Check that having an invalid char after the "." doesn't cause an assert.
TEST_P(GLSLTest,InvalidFieldFirstChar)2547 TEST_P(GLSLTest, InvalidFieldFirstChar)
2548 {
2549 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
2550 const char *source = "void main() {vec4 x; x.}";
2551 glShaderSource(shader, 1, &source, 0);
2552 glCompileShader(shader);
2553
2554 GLint compileResult;
2555 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
2556 EXPECT_EQ(0, compileResult);
2557 }
2558
2559 // Verify that a length array with mixed positive and negative values compiles.
TEST_P(GLSLTest,MixedShaderLengths)2560 TEST_P(GLSLTest, MixedShaderLengths)
2561 {
2562 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
2563
2564 const char *sourceArray[] = {
2565 "void main()",
2566 "{",
2567 " gl_FragColor = vec4(0, 0, 0, 0);",
2568 "}",
2569 };
2570 GLint lengths[] = {
2571 -10,
2572 1,
2573 static_cast<GLint>(strlen(sourceArray[2])),
2574 -1,
2575 };
2576 ASSERT_EQ(ArraySize(sourceArray), ArraySize(lengths));
2577
2578 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
2579 glCompileShader(shader);
2580
2581 GLint compileResult;
2582 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
2583 EXPECT_NE(compileResult, 0);
2584 }
2585
2586 // Verify that zero-length shader source does not affect shader compilation.
TEST_P(GLSLTest,ZeroShaderLength)2587 TEST_P(GLSLTest, ZeroShaderLength)
2588 {
2589 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
2590
2591 const char *sourceArray[] = {
2592 "abcdefg", "34534", "void main() { gl_FragColor = vec4(0, 0, 0, 0); }", "", "abcdefghijklm",
2593 };
2594 GLint lengths[] = {
2595 0, 0, -1, 0, 0,
2596 };
2597 ASSERT_EQ(ArraySize(sourceArray), ArraySize(lengths));
2598
2599 glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
2600 glCompileShader(shader);
2601
2602 GLint compileResult;
2603 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
2604 EXPECT_NE(compileResult, 0);
2605 }
2606
2607 // Tests that bad index expressions don't crash ANGLE's translator.
2608 // https://code.google.com/p/angleproject/issues/detail?id=857
TEST_P(GLSLTest,BadIndexBug)2609 TEST_P(GLSLTest, BadIndexBug)
2610 {
2611 constexpr char kFSSourceVec[] =
2612 "precision mediump float;\n"
2613 "uniform vec4 uniformVec;\n"
2614 "void main()\n"
2615 "{\n"
2616 " gl_FragColor = vec4(uniformVec[int()]);\n"
2617 "}";
2618
2619 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFSSourceVec);
2620 EXPECT_EQ(0u, shader);
2621
2622 if (shader != 0)
2623 {
2624 glDeleteShader(shader);
2625 }
2626
2627 constexpr char kFSSourceMat[] =
2628 "precision mediump float;\n"
2629 "uniform mat4 uniformMat;\n"
2630 "void main()\n"
2631 "{\n"
2632 " gl_FragColor = vec4(uniformMat[int()]);\n"
2633 "}";
2634
2635 shader = CompileShader(GL_FRAGMENT_SHADER, kFSSourceMat);
2636 EXPECT_EQ(0u, shader);
2637
2638 if (shader != 0)
2639 {
2640 glDeleteShader(shader);
2641 }
2642
2643 constexpr char kFSSourceArray[] =
2644 "precision mediump float;\n"
2645 "uniform vec4 uniformArray;\n"
2646 "void main()\n"
2647 "{\n"
2648 " gl_FragColor = vec4(uniformArray[int()]);\n"
2649 "}";
2650
2651 shader = CompileShader(GL_FRAGMENT_SHADER, kFSSourceArray);
2652 EXPECT_EQ(0u, shader);
2653
2654 if (shader != 0)
2655 {
2656 glDeleteShader(shader);
2657 }
2658 }
2659
2660 // Test that structs defined in uniforms are translated correctly.
TEST_P(GLSLTest,StructSpecifiersUniforms)2661 TEST_P(GLSLTest, StructSpecifiersUniforms)
2662 {
2663 constexpr char kFS[] = R"(precision mediump float;
2664
2665 uniform struct S { float field; } s;
2666
2667 void main()
2668 {
2669 gl_FragColor = vec4(1, 0, 0, 1);
2670 gl_FragColor.a += s.field;
2671 })";
2672
2673 GLuint program = CompileProgram(essl1_shaders::vs::Simple(), kFS);
2674 EXPECT_NE(0u, program);
2675 }
2676
2677 // Test that structs declaration followed directly by an initialization is translated correctly.
TEST_P(GLSLTest,StructWithInitializer)2678 TEST_P(GLSLTest, StructWithInitializer)
2679 {
2680 constexpr char kFS[] = R"(precision mediump float;
2681
2682 struct S { float a; } s = S(1.0);
2683
2684 void main()
2685 {
2686 gl_FragColor = vec4(0, 0, 0, 1);
2687 gl_FragColor.r += s.a;
2688 })";
2689
2690 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
2691 glUseProgram(program);
2692
2693 // Test drawing, should be red.
2694 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2695
2696 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2697 EXPECT_GL_NO_ERROR();
2698 }
2699
2700 // Test that structs without initializer, followed by a uniform usage works as expected.
TEST_P(GLSLTest,UniformStructWithoutInitializer)2701 TEST_P(GLSLTest, UniformStructWithoutInitializer)
2702 {
2703 constexpr char kFS[] = R"(precision mediump float;
2704
2705 struct S { float a; };
2706 uniform S u_s;
2707
2708 void main()
2709 {
2710 gl_FragColor = vec4(u_s.a);
2711 })";
2712
2713 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
2714 glUseProgram(program);
2715
2716 // Test drawing, should be red.
2717 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2718
2719 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
2720 EXPECT_GL_NO_ERROR();
2721 }
2722
2723 // Test that structs declaration followed directly by an initialization in a uniform.
TEST_P(GLSLTest,StructWithUniformInitializer)2724 TEST_P(GLSLTest, StructWithUniformInitializer)
2725 {
2726 constexpr char kFS[] = R"(precision mediump float;
2727
2728 struct S { float a; } s = S(1.0);
2729 uniform S us;
2730
2731 void main()
2732 {
2733 gl_FragColor = vec4(0, 0, 0, 1);
2734 gl_FragColor.r += s.a;
2735 gl_FragColor.g += us.a;
2736 })";
2737
2738 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
2739 glUseProgram(program);
2740
2741 // Test drawing, should be red.
2742 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2743
2744 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2745 EXPECT_GL_NO_ERROR();
2746 }
2747
2748 // Test that gl_DepthRange is not stored as a uniform location. Since uniforms
2749 // beginning with "gl_" are filtered out by our validation logic, we must
2750 // bypass the validation to test the behaviour of the implementation.
2751 // (note this test is still Impl-independent)
TEST_P(GLSLTestNoValidation,DepthRangeUniforms)2752 TEST_P(GLSLTestNoValidation, DepthRangeUniforms)
2753 {
2754 constexpr char kFS[] = R"(precision mediump float;
2755
2756 void main()
2757 {
2758 gl_FragColor = vec4(gl_DepthRange.near, gl_DepthRange.far, gl_DepthRange.diff, 1);
2759 })";
2760
2761 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
2762
2763 // We need to bypass validation for this call.
2764 GLint nearIndex = glGetUniformLocation(program, "gl_DepthRange.near");
2765 EXPECT_EQ(-1, nearIndex);
2766
2767 // Test drawing does not throw an exception.
2768 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2769
2770 EXPECT_GL_NO_ERROR();
2771 }
2772
GenerateSmallPowShader(double base,double exponent)2773 std::string GenerateSmallPowShader(double base, double exponent)
2774 {
2775 std::stringstream stream;
2776
2777 stream.precision(8);
2778
2779 double result = pow(base, exponent);
2780
2781 stream << "precision highp float;\n"
2782 << "float fun(float arg)\n"
2783 << "{\n"
2784 << " return pow(arg, " << std::fixed << exponent << ");\n"
2785 << "}\n"
2786 << "\n"
2787 << "void main()\n"
2788 << "{\n"
2789 << " const float a = " << std::scientific << base << ";\n"
2790 << " float b = fun(a);\n"
2791 << " if (abs(" << result << " - b) < " << std::abs(result * 0.001) << ")\n"
2792 << " {\n"
2793 << " gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
2794 << " }\n"
2795 << " else\n"
2796 << " {\n"
2797 << " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
2798 << " }\n"
2799 << "}\n";
2800
2801 return stream.str();
2802 }
2803
2804 // Covers the WebGL test 'glsl/bugs/pow-of-small-constant-in-user-defined-function'
2805 // See http://anglebug.com/40096900
TEST_P(GLSLTest,PowOfSmallConstant)2806 TEST_P(GLSLTest, PowOfSmallConstant)
2807 {
2808 // Test with problematic exponents that are close to an integer.
2809 std::vector<double> testExponents;
2810 std::array<double, 5> epsilonMultipliers = {-100.0, -1.0, 0.0, 1.0, 100.0};
2811 for (double epsilonMultiplier : epsilonMultipliers)
2812 {
2813 for (int i = -4; i <= 5; ++i)
2814 {
2815 if (i >= -1 && i <= 1)
2816 continue;
2817 const double epsilon = 1.0e-8;
2818 double bad = static_cast<double>(i) + epsilonMultiplier * epsilon;
2819 testExponents.push_back(bad);
2820 }
2821 }
2822
2823 // Also test with a few exponents that are not close to an integer.
2824 testExponents.push_back(3.6);
2825 testExponents.push_back(3.4);
2826
2827 for (double testExponent : testExponents)
2828 {
2829 const std::string &fragmentShaderSource = GenerateSmallPowShader(1.0e-6, testExponent);
2830
2831 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), fragmentShaderSource.c_str());
2832
2833 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2834
2835 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2836 EXPECT_GL_NO_ERROR();
2837 }
2838 }
2839
2840 // Test fragment shaders which contain non-constant loop indexers
TEST_P(GLSLTest,LoopIndexingValidation)2841 TEST_P(GLSLTest, LoopIndexingValidation)
2842 {
2843 constexpr char kFS[] = R"(precision mediump float;
2844
2845 uniform float loopMax;
2846
2847 void main()
2848 {
2849 gl_FragColor = vec4(1, 0, 0, 1);
2850 for (float l = 0.0; l < loopMax; l++)
2851 {
2852 if (loopMax > 3.0)
2853 {
2854 gl_FragColor.a += 0.1;
2855 }
2856 }
2857 })";
2858
2859 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
2860
2861 const char *sourceArray[1] = {kFS};
2862 glShaderSource(shader, 1, sourceArray, nullptr);
2863 glCompileShader(shader);
2864
2865 GLint compileResult;
2866 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
2867
2868 // If the test is configured to run limited to Feature Level 9_3, then it is
2869 // assumed that shader compilation will fail with an expected error message containing
2870 // "Loop index cannot be compared with non-constant expression"
2871 if (GetParam() == ES2_D3D9())
2872 {
2873 if (compileResult != 0)
2874 {
2875 FAIL() << "Shader compilation succeeded, expected failure";
2876 }
2877 else
2878 {
2879 GLint infoLogLength;
2880 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
2881
2882 std::string infoLog;
2883 infoLog.resize(infoLogLength);
2884 glGetShaderInfoLog(shader, static_cast<GLsizei>(infoLog.size()), nullptr, &infoLog[0]);
2885
2886 if (infoLog.find("Loop index cannot be compared with non-constant expression") ==
2887 std::string::npos)
2888 {
2889 FAIL() << "Shader compilation failed with unexpected error message";
2890 }
2891 }
2892 }
2893 else
2894 {
2895 EXPECT_NE(0, compileResult);
2896 }
2897
2898 if (shader != 0)
2899 {
2900 glDeleteShader(shader);
2901 }
2902 }
2903
2904 // Tests that the maximum uniforms count returned from querying GL_MAX_VERTEX_UNIFORM_VECTORS
2905 // can actually be used.
TEST_P(GLSLTest,VerifyMaxVertexUniformVectors)2906 TEST_P(GLSLTest, VerifyMaxVertexUniformVectors)
2907 {
2908 // crbug.com/680631
2909 ANGLE_SKIP_TEST_IF(IsOzone() && IsIntel());
2910
2911 int maxUniforms = 10000;
2912 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
2913 EXPECT_GL_NO_ERROR();
2914 std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS = " << maxUniforms << std::endl;
2915
2916 CompileGLSLWithUniformsAndSamplers(maxUniforms, 0, 0, 0, true);
2917 }
2918
2919 // Tests that the maximum uniforms count returned from querying GL_MAX_VERTEX_UNIFORM_VECTORS
2920 // can actually be used along with the maximum number of texture samplers.
TEST_P(GLSLTest,VerifyMaxVertexUniformVectorsWithSamplers)2921 TEST_P(GLSLTest, VerifyMaxVertexUniformVectorsWithSamplers)
2922 {
2923 ANGLE_SKIP_TEST_IF(IsOpenGL() || IsOpenGLES());
2924
2925 // Times out on D3D11 on test infra. http://anglebug.com/42263645
2926 ANGLE_SKIP_TEST_IF(IsD3D11() && IsIntel());
2927
2928 int maxUniforms = 10000;
2929 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
2930 EXPECT_GL_NO_ERROR();
2931 std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS = " << maxUniforms << std::endl;
2932
2933 int maxTextureImageUnits = 0;
2934 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
2935
2936 CompileGLSLWithUniformsAndSamplers(maxUniforms, 0, maxTextureImageUnits, 0, true);
2937 }
2938
2939 // Tests that the maximum uniforms count + 1 from querying GL_MAX_VERTEX_UNIFORM_VECTORS
2940 // fails shader compilation.
TEST_P(GLSLTest,VerifyMaxVertexUniformVectorsExceeded)2941 TEST_P(GLSLTest, VerifyMaxVertexUniformVectorsExceeded)
2942 {
2943 int maxUniforms = 10000;
2944 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
2945 EXPECT_GL_NO_ERROR();
2946 std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS + 1 = " << maxUniforms + 1 << std::endl;
2947
2948 CompileGLSLWithUniformsAndSamplers(maxUniforms + 1, 0, 0, 0, false);
2949 }
2950
2951 // Tests that the maximum uniforms count returned from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
2952 // can actually be used.
TEST_P(GLSLTest,VerifyMaxFragmentUniformVectors)2953 TEST_P(GLSLTest, VerifyMaxFragmentUniformVectors)
2954 {
2955 // crbug.com/680631
2956 ANGLE_SKIP_TEST_IF(IsOzone() && IsIntel());
2957
2958 int maxUniforms = 10000;
2959 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
2960 EXPECT_GL_NO_ERROR();
2961 std::cout << "Validating GL_MAX_FRAGMENT_UNIFORM_VECTORS = " << maxUniforms << std::endl;
2962
2963 CompileGLSLWithUniformsAndSamplers(0, maxUniforms, 0, 0, true);
2964 }
2965
2966 // Tests that the maximum uniforms count returned from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
2967 // can actually be used along with the maximum number of texture samplers.
TEST_P(GLSLTest,VerifyMaxFragmentUniformVectorsWithSamplers)2968 TEST_P(GLSLTest, VerifyMaxFragmentUniformVectorsWithSamplers)
2969 {
2970 ANGLE_SKIP_TEST_IF(IsOpenGL() || IsOpenGLES());
2971
2972 int maxUniforms = 10000;
2973 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
2974 EXPECT_GL_NO_ERROR();
2975
2976 int maxTextureImageUnits = 0;
2977 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
2978
2979 CompileGLSLWithUniformsAndSamplers(0, maxUniforms, 0, maxTextureImageUnits, true);
2980 }
2981
2982 // Tests that the maximum uniforms count + 1 from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
2983 // fails shader compilation.
TEST_P(GLSLTest,VerifyMaxFragmentUniformVectorsExceeded)2984 TEST_P(GLSLTest, VerifyMaxFragmentUniformVectorsExceeded)
2985 {
2986 int maxUniforms = 10000;
2987 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
2988 EXPECT_GL_NO_ERROR();
2989 std::cout << "Validating GL_MAX_FRAGMENT_UNIFORM_VECTORS + 1 = " << maxUniforms + 1
2990 << std::endl;
2991
2992 CompileGLSLWithUniformsAndSamplers(0, maxUniforms + 1, 0, 0, false);
2993 }
2994
2995 // Test compiling shaders using the GL_EXT_shader_texture_lod extension
TEST_P(GLSLTest,TextureLOD)2996 TEST_P(GLSLTest, TextureLOD)
2997 {
2998 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_texture_lod"));
2999
3000 constexpr char kFS[] =
3001 "#extension GL_EXT_shader_texture_lod : require\n"
3002 "uniform sampler2D u_texture;\n"
3003 "void main() {\n"
3004 " gl_FragColor = texture2DGradEXT(u_texture, vec2(0.0, 0.0), vec2(0.0, 0.0), vec2(0.0, "
3005 "0.0));\n"
3006 "}\n";
3007
3008 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
3009 ASSERT_NE(0u, shader);
3010 glDeleteShader(shader);
3011 }
3012
3013 // HLSL generates extra lod0 variants of functions. There was a bug that incorrectly reworte
3014 // function calls to use them in vertex shaders. http://anglebug.com/42262136
TEST_P(GLSLTest,TextureLODRewriteInVertexShader)3015 TEST_P(GLSLTest, TextureLODRewriteInVertexShader)
3016 {
3017 constexpr char kVS[] = R"(
3018 precision highp float;
3019 uniform int uni;
3020 uniform sampler2D texture;
3021
3022 vec4 A();
3023
3024 vec4 B() {
3025 vec4 a;
3026 for(int r=0; r<14; r++){
3027 if (r < uni) return vec4(0.0);
3028 a = A();
3029 }
3030 return a;
3031 }
3032
3033 vec4 A() {
3034 return texture2D(texture, vec2(0.0, 0.0));
3035 }
3036
3037 void main() {
3038 gl_Position = B();
3039 })";
3040
3041 constexpr char kFS[] = R"(
3042 void main() { gl_FragColor = vec4(gl_FragCoord.x / 640.0, gl_FragCoord.y / 480.0, 0, 1); }
3043 )";
3044
3045 ANGLE_GL_PROGRAM(program, kVS, kFS);
3046 }
3047
3048 // Test to verify the a shader can have a sampler unused in a vertex shader
3049 // but used in the fragment shader.
TEST_P(GLSLTest,VerifySamplerInBothVertexAndFragmentShaders)3050 TEST_P(GLSLTest, VerifySamplerInBothVertexAndFragmentShaders)
3051 {
3052 constexpr char kVS[] = R"(
3053 attribute vec2 position;
3054 varying mediump vec2 texCoord;
3055 uniform sampler2D tex;
3056 void main()
3057 {
3058 gl_Position = vec4(position, 0, 1);
3059 texCoord = position * 0.5 + vec2(0.5);
3060 })";
3061
3062 constexpr char kFS[] = R"(
3063 varying mediump vec2 texCoord;
3064 uniform sampler2D tex;
3065 void main()
3066 {
3067 gl_FragColor = texture2D(tex, texCoord);
3068 })";
3069
3070 ANGLE_GL_PROGRAM(program, kVS, kFS);
3071
3072 // Initialize basic red texture.
3073 const std::vector<GLColor> redColors(4, GLColor::red);
3074 GLTexture texture;
3075 glBindTexture(GL_TEXTURE_2D, texture);
3076 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, redColors.data());
3077 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3078 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3079 ASSERT_GL_NO_ERROR();
3080
3081 drawQuad(program, "position", 0.0f);
3082
3083 EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::red);
3084 }
3085
3086 // Test that array of structs containing array of samplers work as expected.
TEST_P(GLSLTest,ArrayOfStructContainingArrayOfSamplers)3087 TEST_P(GLSLTest, ArrayOfStructContainingArrayOfSamplers)
3088 {
3089 constexpr char kFS[] =
3090 "precision mediump float;\n"
3091 "struct Data { mediump sampler2D data[2]; };\n"
3092 "uniform Data test[2];\n"
3093 "void main() {\n"
3094 " gl_FragColor = vec4(texture2D(test[1].data[1], vec2(0.0, 0.0)).r,\n"
3095 " texture2D(test[1].data[0], vec2(0.0, 0.0)).r,\n"
3096 " texture2D(test[0].data[1], vec2(0.0, 0.0)).r,\n"
3097 " texture2D(test[0].data[0], vec2(0.0, 0.0)).r);\n"
3098 "}\n";
3099
3100 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
3101 glUseProgram(program);
3102 GLTexture textures[4];
3103 GLColor expected = MakeGLColor(32, 64, 96, 255);
3104 GLubyte data[8] = {}; // 4 bytes of padding, so that texture can be initialized with 4 bytes
3105 memcpy(data, expected.data(), sizeof(expected));
3106 for (int i = 0; i < 4; i++)
3107 {
3108 int outerIdx = i % 2;
3109 int innerIdx = i / 2;
3110 glActiveTexture(GL_TEXTURE0 + i);
3111 glBindTexture(GL_TEXTURE_2D, textures[i]);
3112 // Each element provides two components.
3113 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data + i);
3114 std::stringstream uniformName;
3115 uniformName << "test[" << innerIdx << "].data[" << outerIdx << "]";
3116 // Then send it as a uniform
3117 GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
3118 // The uniform should be active.
3119 EXPECT_NE(uniformLocation, -1);
3120
3121 glUniform1i(uniformLocation, 3 - i);
3122 }
3123 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3124 EXPECT_PIXEL_COLOR_EQ(0, 0, expected);
3125 }
3126
3127 // Test that if a non-preprocessor token is seen in a disabled if-block then it does not disallow
3128 // extension pragmas later
TEST_P(GLSLTest,NonPreprocessorTokensInIfBlocks)3129 TEST_P(GLSLTest, NonPreprocessorTokensInIfBlocks)
3130 {
3131 constexpr const char *kFS = R"(
3132 #if __VERSION__ >= 300
3133 inout mediump vec4 fragData;
3134 #else
3135 #extension GL_EXT_shader_texture_lod :enable
3136 #endif
3137
3138 void main()
3139 {
3140 }
3141 )";
3142
3143 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
3144 EXPECT_NE(0u, shader);
3145 }
3146
3147 // Test that two constructors which have vec4 and mat2 parameters get disambiguated (issue in
3148 // HLSL).
TEST_P(GLSLTest_ES3,AmbiguousConstructorCall2x2)3149 TEST_P(GLSLTest_ES3, AmbiguousConstructorCall2x2)
3150 {
3151 constexpr char kVS[] =
3152 "#version 300 es\n"
3153 "precision highp float;\n"
3154 "in vec4 a_vec;\n"
3155 "in mat2 a_mat;\n"
3156 "void main()\n"
3157 "{\n"
3158 " gl_Position = vec4(a_vec) + vec4(a_mat);\n"
3159 "}";
3160
3161 GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
3162 EXPECT_NE(0u, program);
3163 }
3164
3165 // Test that two constructors which have mat2x3 and mat3x2 parameters get disambiguated.
3166 // This was suspected to be an issue in HLSL, but HLSL seems to be able to natively choose between
3167 // the function signatures in this case.
TEST_P(GLSLTest_ES3,AmbiguousConstructorCall2x3)3168 TEST_P(GLSLTest_ES3, AmbiguousConstructorCall2x3)
3169 {
3170 constexpr char kVS[] =
3171 "#version 300 es\n"
3172 "precision highp float;\n"
3173 "in mat3x2 a_matA;\n"
3174 "in mat2x3 a_matB;\n"
3175 "void main()\n"
3176 "{\n"
3177 " gl_Position = vec4(a_matA) + vec4(a_matB);\n"
3178 "}";
3179
3180 GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
3181 EXPECT_NE(0u, program);
3182 }
3183
3184 // Test that two functions which have vec4 and mat2 parameters get disambiguated (issue in HLSL).
TEST_P(GLSLTest_ES3,AmbiguousFunctionCall2x2)3185 TEST_P(GLSLTest_ES3, AmbiguousFunctionCall2x2)
3186 {
3187 constexpr char kVS[] =
3188 "#version 300 es\n"
3189 "precision highp float;\n"
3190 "in vec4 a_vec;\n"
3191 "in mat2 a_mat;\n"
3192 "vec4 foo(vec4 a)\n"
3193 "{\n"
3194 " return a;\n"
3195 "}\n"
3196 "vec4 foo(mat2 a)\n"
3197 "{\n"
3198 " return vec4(a[0][0]);\n"
3199 "}\n"
3200 "void main()\n"
3201 "{\n"
3202 " gl_Position = foo(a_vec) + foo(a_mat);\n"
3203 "}";
3204
3205 GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
3206 EXPECT_NE(0u, program);
3207 }
3208
3209 // Test that constructing matrices from non-float types works.
TEST_P(GLSLTest_ES3,ConstructMatrixFromNonFloat)3210 TEST_P(GLSLTest_ES3, ConstructMatrixFromNonFloat)
3211 {
3212 constexpr char kFS[] = R"(#version 300 es
3213 precision highp float;
3214 out vec4 color;
3215
3216 uniform int i;
3217 uniform uint u;
3218 uniform bool b;
3219
3220 void main()
3221 {
3222 mat3x2 mi = mat3x2(i);
3223 mat4 mu = mat4(u);
3224 mat2x4 mb = mat2x4(b);
3225
3226 mat3x2 m = mat3x2(ivec2(i), uvec2(u), bvec2(b));
3227
3228 color = vec4(mi[0][0] == -123.0 ? 1 : 0,
3229 mu[2][2] == 456.0 ? 1 : 0,
3230 mb[1][1] == 1.0 ? 1 : 0,
3231 m[0][1] == -123.0 && m[1][0] == 456.0 && m[2][0] == 1.0 ? 1 : 0);
3232 })";
3233
3234 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3235 glUseProgram(program);
3236
3237 GLint iloc = glGetUniformLocation(program, "i");
3238 GLint uloc = glGetUniformLocation(program, "u");
3239 GLint bloc = glGetUniformLocation(program, "b");
3240 ASSERT_NE(iloc, -1);
3241 ASSERT_NE(uloc, -1);
3242 ASSERT_NE(bloc, -1);
3243 glUniform1i(iloc, -123);
3244 glUniform1ui(uloc, 456);
3245 glUniform1ui(bloc, 1);
3246
3247 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3248 EXPECT_GL_NO_ERROR();
3249
3250 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
3251 }
3252
3253 // Test that constructing vectors from non-float types works.
TEST_P(GLSLTest_ES3,ConstructVectorFromNonFloat)3254 TEST_P(GLSLTest_ES3, ConstructVectorFromNonFloat)
3255 {
3256 constexpr char kFS[] = R"(#version 300 es
3257 precision highp float;
3258 out vec4 color;
3259
3260 uniform ivec2 i;
3261 uniform uvec2 u;
3262 uniform bvec2 b;
3263
3264 void main()
3265 {
3266 vec2 v2 = vec2(i.x, b);
3267 vec3 v3 = vec3(b, u);
3268 vec4 v4 = vec4(i, u);
3269
3270 color = vec4(v2.x == -123.0 && v2.y == 1.0 ? 1 : 0,
3271 v3.x == 1.0 && v3.y == 0.0 && v3.z == 456.0 ? 1 : 0,
3272 v4.x == -123.0 && v4.y == -23.0 && v4.z == 456.0 && v4.w == 76.0 ? 1 : 0,
3273 1);
3274 })";
3275
3276 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3277 glUseProgram(program);
3278
3279 GLint iloc = glGetUniformLocation(program, "i");
3280 GLint uloc = glGetUniformLocation(program, "u");
3281 GLint bloc = glGetUniformLocation(program, "b");
3282 ASSERT_NE(iloc, -1);
3283 ASSERT_NE(uloc, -1);
3284 ASSERT_NE(bloc, -1);
3285 glUniform2i(iloc, -123, -23);
3286 glUniform2ui(uloc, 456, 76);
3287 glUniform2ui(bloc, 1, 0);
3288
3289 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3290 EXPECT_GL_NO_ERROR();
3291
3292 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
3293 }
3294
3295 // Test that constructing non-float vectors from matrix types works.
TEST_P(GLSLTest_ES3,ConstructNonFloatVectorFromMatrix)3296 TEST_P(GLSLTest_ES3, ConstructNonFloatVectorFromMatrix)
3297 {
3298 constexpr char kFS[] = R"(#version 300 es
3299 precision highp float;
3300 out vec4 color;
3301
3302 uniform float f;
3303
3304 void main()
3305 {
3306 mat4 m = mat4(f);
3307 ivec3 vi = ivec3(m);
3308 uvec2 vu = uvec2(m);
3309 bvec4 vb = bvec4(m);
3310 bvec2 vb2 = bvec2(vi.x, m);
3311
3312 color = vec4(vi.x == int(f) ? 1 : 0,
3313 vu.x == uint(f) ? 1 : 0,
3314 vb.x == bool(f) ? 1 : 0,
3315 vb2.x == bool(f) && vb2.y == bool(f) ? 1 : 0);
3316 })";
3317
3318 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3319 glUseProgram(program);
3320
3321 GLint floc = glGetUniformLocation(program, "f");
3322 ASSERT_NE(floc, -1);
3323 glUniform1f(floc, 123);
3324
3325 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3326 EXPECT_GL_NO_ERROR();
3327
3328 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
3329 }
3330
3331 // Test that == and != for vector and matrix types work.
TEST_P(GLSLTest_ES3,NonScalarEqualOperator)3332 TEST_P(GLSLTest_ES3, NonScalarEqualOperator)
3333 {
3334 constexpr char kFS[] = R"(#version 300 es
3335 precision highp float;
3336 out vec4 color;
3337
3338 uniform float f;
3339 uniform int i;
3340 uniform uint u;
3341
3342 void main()
3343 {
3344 mat3x2 m32_1 = mat3x2(vec2(f), vec2(i), vec2(u));
3345 mat3x2 m32_2 = mat3x2(m32_1);
3346 mat3x2 m32_3 = mat3x2(vec2(i), vec2(u), vec2(f));
3347 mat2x3 m23_1 = mat2x3(vec3(f), vec3(i));
3348 mat2x3 m23_2 = mat2x3(m23_1);
3349 mat2x3 m23_3 = mat2x3(vec3(i), vec3(u));
3350 vec2 v2_1 = m32_1[0];
3351 vec2 v2_2 = m32_2[0];
3352 ivec3 v3_1 = ivec3(transpose(m32_1)[0]);
3353 ivec3 v3_2 = ivec3(transpose(m32_2)[0]);
3354 uvec4 v4_1 = uvec4(m32_1[1], m32_1[2]);
3355 uvec4 v4_2 = uvec4(m32_2[1], m32_2[2]);
3356
3357 color = vec4((m32_1 == m32_2 ? 0.5 : 0.0) + (m23_1 == m23_2 ? 0.5 : 0.0),
3358 v2_1 == v2_2 ? 1 : 0,
3359 (v3_1 == v3_2 ? 0.5 : 0.0) +
3360 (v4_1 == v4_2 ? 0.5 : 0.0),
3361 (m32_1 != m32_3 ? 0.125 : 0.0) +
3362 (m23_1 != m23_3 ? 0.125 : 0.0) +
3363 (v2_1 != vec2(v3_2) ? 0.25 : 0.0) +
3364 (v3_1 != ivec3(v4_2) ? 0.25 : 0.0) +
3365 (v4_1 != uvec4(v2_1, v2_2) ? 0.25 : 0.0));
3366 })";
3367
3368 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3369 glUseProgram(program);
3370
3371 GLint floc = glGetUniformLocation(program, "f");
3372 GLint iloc = glGetUniformLocation(program, "i");
3373 GLint uloc = glGetUniformLocation(program, "u");
3374 ASSERT_NE(floc, -1);
3375 ASSERT_NE(iloc, -1);
3376 ASSERT_NE(uloc, -1);
3377 glUniform1f(floc, 1.5);
3378 glUniform1i(iloc, -123);
3379 glUniform1ui(uloc, 456);
3380
3381 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3382 EXPECT_GL_NO_ERROR();
3383
3384 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
3385 }
3386
3387 // Test that == and != for structs and array types work.
TEST_P(GLSLTest_ES31,StructAndArrayEqualOperator)3388 TEST_P(GLSLTest_ES31, StructAndArrayEqualOperator)
3389 {
3390 constexpr char kFS[] = R"(#version 310 es
3391 precision highp float;
3392 out vec4 color;
3393
3394 uniform float f;
3395 uniform int i;
3396 uniform uint u;
3397
3398 struct S
3399 {
3400 float f;
3401 int i;
3402 uint u;
3403 vec4 v;
3404 ivec3 iv;
3405 uvec2 uv;
3406 mat3x2 m32;
3407 mat2x3 m23;
3408 float fa[3][4][5];
3409 int ia[4];
3410 uint ua[6][2];
3411 };
3412
3413 struct T
3414 {
3415 S s1;
3416 S s2[3][2];
3417 };
3418
3419 void main()
3420 {
3421 float fa[5] = float[5](f, f, f, f, f);
3422 int ia[4] = int[4](i, i, i, i);
3423 uint ua[2] = uint[2](u, u);
3424
3425 S s1 = S(f, i, u, vec4(f), ivec3(i), uvec2(u),
3426 mat3x2(vec2(f), vec2(i), vec2(u)),
3427 mat2x3(vec3(f), vec3(i)),
3428 float[3][4][5](
3429 float[4][5](fa, fa, fa, fa),
3430 float[4][5](fa, fa, fa, fa),
3431 float[4][5](fa, fa, fa, fa)),
3432 ia,
3433 uint[6][2](ua, ua, ua, ua, ua, ua));
3434
3435 S s2[2] = S[2](s1, s1);
3436 s2[1].fa[0][1][2] = float(i);
3437
3438 T t1 = T(s1, S[3][2](s2, s2, s2));
3439 T t2 = T(s2[1], S[3][2](s2, s2, s2));
3440
3441 T ta1[2] = T[2](t1, t2);
3442 T ta2[2] = T[2](t1, t2);
3443 T ta3[2] = T[2](t2, t1);
3444
3445 color = vec4((s1 == s2[0] ? 0.5 : 0.0) + (s1 != s2[1] ? 0.5 : 0.0),
3446 (s1.fa[0] == s2[0].fa[0] ? 0.5 : 0.0) + (s1.fa[0] != s2[1].fa[0] ? 0.5 : 0.0),
3447 (ta1[0] == t1 ? 0.5 : 0.0) + (ta1[1] != t1 ? 0.5 : 0.0),
3448 (ta1 == ta2 ? 0.5 : 0.0) + (ta1 != ta3 ? 0.5 : 0.0));
3449 })";
3450
3451 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
3452 glUseProgram(program);
3453
3454 GLint floc = glGetUniformLocation(program, "f");
3455 GLint iloc = glGetUniformLocation(program, "i");
3456 GLint uloc = glGetUniformLocation(program, "u");
3457 ASSERT_NE(floc, -1);
3458 ASSERT_NE(iloc, -1);
3459 ASSERT_NE(uloc, -1);
3460 glUniform1f(floc, 1.5);
3461 glUniform1i(iloc, -123);
3462 glUniform1ui(uloc, 456);
3463
3464 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3465 EXPECT_GL_NO_ERROR();
3466
3467 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
3468 }
3469
3470 // Test that an user-defined function with a large number of float4 parameters doesn't fail due to
3471 // the function name being too long.
TEST_P(GLSLTest_ES3,LargeNumberOfFloat4Parameters)3472 TEST_P(GLSLTest_ES3, LargeNumberOfFloat4Parameters)
3473 {
3474 std::stringstream vertexShaderStream;
3475 // Note: SPIR-V doesn't allow more than 255 parameters to a function.
3476 const unsigned int paramCount = (IsVulkan() || IsMetal()) ? 255u : 1024u;
3477
3478 vertexShaderStream << "#version 300 es\n"
3479 "precision highp float;\n"
3480 "in vec4 a_vec;\n"
3481 "vec4 lotsOfVec4Parameters(";
3482 for (unsigned int i = 0; i < paramCount - 1; ++i)
3483 {
3484 vertexShaderStream << "vec4 a" << i << ", ";
3485 }
3486 vertexShaderStream << "vec4 aLast)\n"
3487 "{\n"
3488 " vec4 sum = vec4(0.0, 0.0, 0.0, 0.0);\n";
3489 for (unsigned int i = 0; i < paramCount - 1; ++i)
3490 {
3491 vertexShaderStream << " sum += a" << i << ";\n";
3492 }
3493 vertexShaderStream << " sum += aLast;\n"
3494 " return sum;\n "
3495 "}\n"
3496 "void main()\n"
3497 "{\n"
3498 " gl_Position = lotsOfVec4Parameters(";
3499 for (unsigned int i = 0; i < paramCount - 1; ++i)
3500 {
3501 vertexShaderStream << "a_vec, ";
3502 }
3503 vertexShaderStream << "a_vec);\n"
3504 "}";
3505
3506 GLuint program = CompileProgram(vertexShaderStream.str().c_str(), essl3_shaders::fs::Red());
3507 EXPECT_NE(0u, program);
3508 }
3509
3510 // This test was written specifically to stress DeferGlobalInitializers AST transformation.
3511 // Test a shader where a global constant array is initialized with an expression containing array
3512 // indexing. This initializer is tricky to constant fold, so if it's not constant folded it needs to
3513 // be handled in a way that doesn't generate statements in the global scope in HLSL output.
3514 // Also includes multiple array initializers in one declaration, where only the second one has
3515 // array indexing. This makes sure that the qualifier for the declaration is set correctly if
3516 // transformations are applied to the declaration also in the case of ESSL output.
TEST_P(GLSLTest_ES3,InitGlobalArrayWithArrayIndexing)3517 TEST_P(GLSLTest_ES3, InitGlobalArrayWithArrayIndexing)
3518 {
3519 // TODO(ynovikov): re-enable once root cause of http://anglebug.com/42260423 is fixed
3520 ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
3521
3522 constexpr char kFS[] =
3523 "#version 300 es\n"
3524 "precision highp float;\n"
3525 "out vec4 my_FragColor;\n"
3526 "const highp float f[2] = float[2](0.1, 0.2);\n"
3527 "const highp float[2] g = float[2](0.3, 0.4), h = float[2](0.5, f[1]);\n"
3528 "void main()\n"
3529 "{\n"
3530 " my_FragColor = vec4(h[1]);\n"
3531 "}";
3532
3533 GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS);
3534 EXPECT_NE(0u, program);
3535 }
3536
3537 // Test that constant global matrix array with an initializer compiles.
TEST_P(GLSLTest_ES3,InitConstantMatrixArray)3538 TEST_P(GLSLTest_ES3, InitConstantMatrixArray)
3539 {
3540 constexpr char kFS[] = R"(#version 300 es
3541 precision highp float;
3542 uniform int index;
3543
3544 const mat4 matrix = mat4(1.0);
3545 const mat4 array[1] = mat4[1](matrix);
3546 out vec4 my_FragColor;
3547 void main() {
3548 my_FragColor = vec4(array[index][1].rgb, 1.0);
3549 })";
3550
3551 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3552
3553 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3554 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3555 }
3556
3557 // Test that index-constant sampler array indexing is supported.
TEST_P(GLSLTest,IndexConstantSamplerArrayIndexing)3558 TEST_P(GLSLTest, IndexConstantSamplerArrayIndexing)
3559 {
3560 constexpr char kFS[] =
3561 "precision mediump float;\n"
3562 "uniform sampler2D uni[2];\n"
3563 "\n"
3564 "float zero(int x)\n"
3565 "{\n"
3566 " return float(x) - float(x);\n"
3567 "}\n"
3568 "\n"
3569 "void main()\n"
3570 "{\n"
3571 " vec4 c = vec4(0,0,0,0);\n"
3572 " for (int ii = 1; ii < 3; ++ii) {\n"
3573 " if (c.x > 255.0) {\n"
3574 " c.x = 255.0 + zero(ii);\n"
3575 " break;\n"
3576 " }\n"
3577 // Index the sampler array with a predictable loop index (index-constant) as opposed to
3578 // a true constant. This is valid in OpenGL ES but isn't in many Desktop OpenGL versions,
3579 // without an extension.
3580 " c += texture2D(uni[ii - 1], vec2(0.5, 0.5));\n"
3581 " }\n"
3582 " gl_FragColor = c;\n"
3583 "}";
3584
3585 GLuint program = CompileProgram(essl1_shaders::vs::Simple(), kFS);
3586 EXPECT_NE(0u, program);
3587 }
3588
3589 // Test that the #pragma directive is supported and doesn't trigger a compilation failure on the
3590 // native driver. The only pragma that gets passed to the OpenGL driver is "invariant" but we don't
3591 // want to test its behavior, so don't use any varyings.
TEST_P(GLSLTest,PragmaDirective)3592 TEST_P(GLSLTest, PragmaDirective)
3593 {
3594 constexpr char kVS[] =
3595 "#pragma STDGL invariant(all)\n"
3596 "void main()\n"
3597 "{\n"
3598 " gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
3599 "}\n";
3600
3601 GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
3602 EXPECT_NE(0u, program);
3603 }
3604
3605 // Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
3606 // The function call that returns the array needs to be evaluated after ++j for the expression to
3607 // return the correct value (true).
TEST_P(GLSLTest_ES3,SequenceOperatorEvaluationOrderArray)3608 TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderArray)
3609 {
3610 constexpr char kFS[] =
3611 "#version 300 es\n"
3612 "precision mediump float;\n"
3613 "out vec4 my_FragColor; \n"
3614 "int[2] func(int param) {\n"
3615 " return int[2](param, param);\n"
3616 "}\n"
3617 "void main() {\n"
3618 " int a[2]; \n"
3619 " for (int i = 0; i < 2; ++i) {\n"
3620 " a[i] = 1;\n"
3621 " }\n"
3622 " int j = 0; \n"
3623 " bool result = ((++j), (a == func(j)));\n"
3624 " my_FragColor = vec4(0.0, (result ? 1.0 : 0.0), 0.0, 1.0);\n"
3625 "}\n";
3626
3627 GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS);
3628 ASSERT_NE(0u, program);
3629
3630 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3631
3632 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3633 }
3634
3635 // Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
3636 // The short-circuiting expression needs to be evaluated after ++j for the expression to return the
3637 // correct value (true).
TEST_P(GLSLTest_ES3,SequenceOperatorEvaluationOrderShortCircuit)3638 TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderShortCircuit)
3639 {
3640 constexpr char kFS[] =
3641 "#version 300 es\n"
3642 "precision mediump float;\n"
3643 "out vec4 my_FragColor; \n"
3644 "void main() {\n"
3645 " int j = 0; \n"
3646 " bool result = ((++j), (j == 1 ? true : (++j == 3)));\n"
3647 " my_FragColor = vec4(0.0, ((result && j == 1) ? 1.0 : 0.0), 0.0, 1.0);\n"
3648 "}\n";
3649
3650 GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS);
3651 ASSERT_NE(0u, program);
3652
3653 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3654
3655 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3656 }
3657
3658 // Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
3659 // Indexing the vector needs to be evaluated after func() for the right result.
TEST_P(GLSLTest_ES3,SequenceOperatorEvaluationOrderDynamicVectorIndexingInLValue)3660 TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderDynamicVectorIndexingInLValue)
3661 {
3662 constexpr char kFS[] =
3663 "#version 300 es\n"
3664 "precision mediump float;\n"
3665 "out vec4 my_FragColor;\n"
3666 "uniform int u_zero;\n"
3667 "int sideEffectCount = 0;\n"
3668 "float func() {\n"
3669 " ++sideEffectCount;\n"
3670 " return -1.0;\n"
3671 "}\n"
3672 "void main() {\n"
3673 " vec4 v = vec4(0.0, 2.0, 4.0, 6.0); \n"
3674 " float f = (func(), (++v[u_zero + sideEffectCount]));\n"
3675 " bool green = abs(f - 3.0) < 0.01 && abs(v[1] - 3.0) < 0.01 && sideEffectCount == 1;\n"
3676 " my_FragColor = vec4(0.0, (green ? 1.0 : 0.0), 0.0, 1.0);\n"
3677 "}\n";
3678
3679 GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS);
3680 ASSERT_NE(0u, program);
3681
3682 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3683
3684 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3685 }
3686
3687 // Test that using gl_PointCoord with GL_TRIANGLES doesn't produce a link error.
3688 // From WebGL test conformance/rendering/point-specific-shader-variables.html
3689 // See http://anglebug.com/42260376
TEST_P(GLSLTest,RenderTrisWithPointCoord)3690 TEST_P(GLSLTest, RenderTrisWithPointCoord)
3691 {
3692 constexpr char kVS[] =
3693 "attribute vec2 aPosition;\n"
3694 "void main()\n"
3695 "{\n"
3696 " gl_Position = vec4(aPosition, 0, 1);\n"
3697 " gl_PointSize = 1.0;\n"
3698 "}";
3699 constexpr char kFS[] =
3700 "void main()\n"
3701 "{\n"
3702 " gl_FragColor = vec4(gl_PointCoord.xy, 0, 1);\n"
3703 " gl_FragColor = vec4(0, 1, 0, 1);\n"
3704 "}";
3705
3706 ANGLE_GL_PROGRAM(prog, kVS, kFS);
3707 drawQuad(prog, "aPosition", 0.5f);
3708 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3709 }
3710
3711 // Convers a bug with the integer pow statement workaround.
TEST_P(GLSLTest,NestedPowStatements)3712 TEST_P(GLSLTest, NestedPowStatements)
3713 {
3714 // https://crbug.com/1127866 - possible NVIDIA driver issue
3715 ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsVulkan() && IsWindows());
3716
3717 constexpr char kFS[] =
3718 "precision mediump float;\n"
3719 "float func(float v)\n"
3720 "{\n"
3721 " float f1 = pow(v, 2.0);\n"
3722 " return pow(f1 + v, 2.0);\n"
3723 "}\n"
3724 "void main()\n"
3725 "{\n"
3726 " float v = func(2.0);\n"
3727 " gl_FragColor = abs(v - 36.0) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
3728 "}";
3729
3730 ANGLE_GL_PROGRAM(prog, essl1_shaders::vs::Simple(), kFS);
3731 drawQuad(prog, essl1_shaders::PositionAttrib(), 0.5f);
3732 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3733 }
3734
3735 // This test covers a crash seen in an application during SPIR-V compilation
TEST_P(GLSLTest_ES3,NestedPowFromUniform)3736 TEST_P(GLSLTest_ES3, NestedPowFromUniform)
3737 {
3738 constexpr char kVS[] = R"(#version 300 es
3739 in vec2 position;
3740 void main()
3741 {
3742 gl_Position = vec4(position, 0, 1);
3743 })";
3744
3745 constexpr char kFS[] = R"(#version 300 es
3746 precision mediump float;
3747 precision mediump int;
3748
3749 uniform highp vec4 scale;
3750 out mediump vec4 out_FragColor;
3751 void main()
3752 {
3753 highp vec4 v0;
3754 v0 = scale;
3755 highp vec3 v1;
3756 v1.xyz = v0.xyz;
3757 if ((v0.y!=1.0))
3758 {
3759 vec3 v3;
3760 v3.xyz = pow(v0.xyz,v0.xxx);
3761 float h0;
3762 if ((v3.x < 3.13))
3763 {
3764 h0 = (v3.x * 1.29);
3765 }
3766 else
3767 {
3768 h0 = ((pow(v3.x,4.16)*1.055)+-5.5);
3769 }
3770 float h1;
3771 if ((v3.y<3.13))
3772 {
3773 h1 = (v3.y*1.29);
3774 }
3775 else
3776 {
3777 h1 = ((pow(v3.y,4.16)*1.055)+-5.5);
3778 }
3779 float h2;
3780 if ((v3.z<3.13))
3781 {
3782 h2 = (v3.z*1.29);
3783 }
3784 else
3785 {
3786 h2 = ((pow(v3.z,4.16)*1.055)+-5.5);
3787 }
3788 v1.xyz = vec3(h0, h1, h2);
3789 }
3790 out_FragColor = vec4(v1, v0.w);
3791 }
3792 )";
3793
3794 ANGLE_GL_PROGRAM(prog, kVS, kFS);
3795
3796 GLint scaleIndex = glGetUniformLocation(prog, "scale");
3797 ASSERT_NE(-1, scaleIndex);
3798
3799 glUseProgram(prog);
3800 glUniform4f(scaleIndex, 0.5, 0.5, 0.5, 0.5);
3801
3802 // Don't crash
3803 drawQuad(prog, "position", 0.5f);
3804 }
3805
3806 // Test that -float calculation is correct.
TEST_P(GLSLTest_ES3,UnaryMinusOperatorFloat)3807 TEST_P(GLSLTest_ES3, UnaryMinusOperatorFloat)
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 float v = atan(tan(0.5), -f);\n"
3816 " o_color = abs(v - 0.5) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
3817 "}\n";
3818
3819 ANGLE_GL_PROGRAM(prog, essl3_shaders::vs::Simple(), kFS);
3820 drawQuad(prog, essl3_shaders::PositionAttrib(), 0.5f);
3821 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3822 }
3823
3824 // Test that atan(vec2, vec2) calculation is correct.
TEST_P(GLSLTest_ES3,AtanVec2)3825 TEST_P(GLSLTest_ES3, AtanVec2)
3826 {
3827 constexpr char kFS[] =
3828 "#version 300 es\n"
3829 "out highp vec4 o_color;\n"
3830 "void main() {\n"
3831 " highp float f = 1.0;\n"
3832 " // atan(tan(0.5), f) should be 0.5.\n"
3833 " highp vec2 v = atan(vec2(tan(0.5)), vec2(f));\n"
3834 " o_color = (abs(v[0] - 0.5) < 0.001 && abs(v[1] - 0.5) < 0.001) ? vec4(0, 1, 0, 1) : "
3835 "vec4(1, 0, 0, 1);\n"
3836 "}\n";
3837
3838 ANGLE_GL_PROGRAM(prog, essl3_shaders::vs::Simple(), kFS);
3839 drawQuad(prog, essl3_shaders::PositionAttrib(), 0.5f);
3840 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3841 }
3842
3843 // Convers a bug with the unary minus operator on signed integer workaround.
TEST_P(GLSLTest_ES3,UnaryMinusOperatorSignedInt)3844 TEST_P(GLSLTest_ES3, UnaryMinusOperatorSignedInt)
3845 {
3846 constexpr char kVS[] =
3847 "#version 300 es\n"
3848 "in highp vec4 position;\n"
3849 "out mediump vec4 v_color;\n"
3850 "uniform int ui_one;\n"
3851 "uniform int ui_two;\n"
3852 "uniform int ui_three;\n"
3853 "void main() {\n"
3854 " int s[3];\n"
3855 " s[0] = ui_one;\n"
3856 " s[1] = -(-(-ui_two + 1) + 1);\n" // s[1] = -ui_two
3857 " s[2] = ui_three;\n"
3858 " int result = 0;\n"
3859 " for (int i = 0; i < ui_three; i++) {\n"
3860 " result += s[i];\n"
3861 " }\n"
3862 " v_color = (result == 2) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
3863 " gl_Position = position;\n"
3864 "}\n";
3865 constexpr char kFS[] =
3866 "#version 300 es\n"
3867 "in mediump vec4 v_color;\n"
3868 "layout(location=0) out mediump vec4 o_color;\n"
3869 "void main() {\n"
3870 " o_color = v_color;\n"
3871 "}\n";
3872
3873 ANGLE_GL_PROGRAM(prog, kVS, kFS);
3874
3875 GLint oneIndex = glGetUniformLocation(prog, "ui_one");
3876 ASSERT_NE(-1, oneIndex);
3877 GLint twoIndex = glGetUniformLocation(prog, "ui_two");
3878 ASSERT_NE(-1, twoIndex);
3879 GLint threeIndex = glGetUniformLocation(prog, "ui_three");
3880 ASSERT_NE(-1, threeIndex);
3881 glUseProgram(prog);
3882 glUniform1i(oneIndex, 1);
3883 glUniform1i(twoIndex, 2);
3884 glUniform1i(threeIndex, 3);
3885
3886 drawQuad(prog, "position", 0.5f);
3887 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3888 }
3889
3890 // Convers a bug with the unary minus operator on unsigned integer workaround.
TEST_P(GLSLTest_ES3,UnaryMinusOperatorUnsignedInt)3891 TEST_P(GLSLTest_ES3, UnaryMinusOperatorUnsignedInt)
3892 {
3893 constexpr char kVS[] =
3894 "#version 300 es\n"
3895 "in highp vec4 position;\n"
3896 "out mediump vec4 v_color;\n"
3897 "uniform uint ui_one;\n"
3898 "uniform uint ui_two;\n"
3899 "uniform uint ui_three;\n"
3900 "void main() {\n"
3901 " uint s[3];\n"
3902 " s[0] = ui_one;\n"
3903 " s[1] = -(-(-ui_two + 1u) + 1u);\n" // s[1] = -ui_two
3904 " s[2] = ui_three;\n"
3905 " uint result = 0u;\n"
3906 " for (uint i = 0u; i < ui_three; i++) {\n"
3907 " result += s[i];\n"
3908 " }\n"
3909 " v_color = (result == 2u) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
3910 " gl_Position = position;\n"
3911 "}\n";
3912 constexpr char kFS[] =
3913 "#version 300 es\n"
3914 "in mediump vec4 v_color;\n"
3915 "layout(location=0) out mediump vec4 o_color;\n"
3916 "void main() {\n"
3917 " o_color = v_color;\n"
3918 "}\n";
3919
3920 ANGLE_GL_PROGRAM(prog, kVS, kFS);
3921
3922 GLint oneIndex = glGetUniformLocation(prog, "ui_one");
3923 ASSERT_NE(-1, oneIndex);
3924 GLint twoIndex = glGetUniformLocation(prog, "ui_two");
3925 ASSERT_NE(-1, twoIndex);
3926 GLint threeIndex = glGetUniformLocation(prog, "ui_three");
3927 ASSERT_NE(-1, threeIndex);
3928 glUseProgram(prog);
3929 glUniform1ui(oneIndex, 1u);
3930 glUniform1ui(twoIndex, 2u);
3931 glUniform1ui(threeIndex, 3u);
3932
3933 drawQuad(prog, "position", 0.5f);
3934 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3935 }
3936
3937 // Test a nested sequence operator with a ternary operator inside. The ternary operator is
3938 // intended to be such that it gets converted to an if statement on the HLSL backend.
TEST_P(GLSLTest,NestedSequenceOperatorWithTernaryInside)3939 TEST_P(GLSLTest, NestedSequenceOperatorWithTernaryInside)
3940 {
3941 // Note that the uniform keep_flop_positive doesn't need to be set - the test expects it to have
3942 // its default value false.
3943 constexpr char kFS[] =
3944 "precision mediump float;\n"
3945 "uniform bool keep_flop_positive;\n"
3946 "float flop;\n"
3947 "void main() {\n"
3948 " flop = -1.0,\n"
3949 " (flop *= -1.0,\n"
3950 " keep_flop_positive ? 0.0 : flop *= -1.0),\n"
3951 " gl_FragColor = vec4(0, -flop, 0, 1);\n"
3952 "}";
3953
3954 ANGLE_GL_PROGRAM(prog, essl1_shaders::vs::Simple(), kFS);
3955 drawQuad(prog, essl1_shaders::PositionAttrib(), 0.5f);
3956 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3957 }
3958
3959 // Test that nesting ternary and short-circuitting operators work.
TEST_P(GLSLTest,NestedTernaryAndShortCircuit)3960 TEST_P(GLSLTest, NestedTernaryAndShortCircuit)
3961 {
3962 // Note that the uniform doesn't need to be set, and will contain the default value of false.
3963 constexpr char kFS[] = R"(
3964 precision mediump float;
3965 uniform bool u;
3966 void main()
3967 {
3968 int a = u ? 12345 : 2; // will be 2
3969 int b = u ? 12345 : 4; // will be 4
3970 int c = u ? 12345 : 0; // will be 0
3971
3972 if (a == 2 // true path is taken
3973 ? (b == 3 // false path is taken
3974 ? (a=0) != 0
3975 : b != 0 // true
3976 ) && ( // short-circuit evaluates RHS
3977 (a=7) == 7 // true, modifies a
3978 || // short-circuit doesn't evaluate RHS
3979 (b=8) == 8
3980 )
3981 : (a == 0 && b == 0
3982 ? (c += int((a=0) == 0 && (b=0) == 0)) != 0
3983 : (c += int((a=0) != 0 && (b=0) != 0)) != 0))
3984 {
3985 c += 15; // will execute
3986 }
3987
3988 // Verify that a is 7, b is 4 and c is 15.
3989 gl_FragColor = vec4(a == 7, b == 4, c == 15, 1);
3990 })";
3991
3992 ANGLE_GL_PROGRAM(prog, essl1_shaders::vs::Simple(), kFS);
3993 drawQuad(prog, essl1_shaders::PositionAttrib(), 0.5f);
3994 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
3995 }
3996
3997 // Test that uniform bvecN passed to functions work.
TEST_P(GLSLTest_ES3,UniformBoolVectorPassedToFunctions)3998 TEST_P(GLSLTest_ES3, UniformBoolVectorPassedToFunctions)
3999 {
4000 constexpr char kFS[] = R"(#version 300 es
4001 precision mediump float;
4002 uniform bvec4 u;
4003 out vec4 color;
4004
4005 bool f(bvec4 bv)
4006 {
4007 return all(bv.xz) && !any(bv.yw);
4008 }
4009
4010 void main() {
4011 color = f(u) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
4012 })";
4013
4014 ANGLE_GL_PROGRAM(prog, essl3_shaders::vs::Simple(), kFS);
4015 glUseProgram(prog);
4016
4017 GLint uloc = glGetUniformLocation(prog, "u");
4018 ASSERT_NE(uloc, -1);
4019 glUniform4ui(uloc, true, false, true, false);
4020
4021 drawQuad(prog, essl3_shaders::PositionAttrib(), 0.5f);
4022 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4023 }
4024
4025 // Test that bvecN in storage buffer passed to functions work.
TEST_P(GLSLTest_ES31,StorageBufferBoolVectorPassedToFunctions)4026 TEST_P(GLSLTest_ES31, StorageBufferBoolVectorPassedToFunctions)
4027 {
4028 constexpr char kCS[] = R"(#version 310 es
4029 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
4030 layout(binding = 0, std430) buffer Output {
4031 bvec4 b;
4032 bool valid;
4033 } outbuf;
4034
4035 bool f_in(bvec4 bv)
4036 {
4037 return all(bv.xz) && !any(bv.yw);
4038 }
4039
4040 bool f_inout(inout bvec4 bv)
4041 {
4042 bool ok = all(bv.xz) && !any(bv.yw);
4043 bv.xw = bvec2(false, true);
4044 return ok;
4045 }
4046
4047 void f_out(out bvec4 bv)
4048 {
4049 bv = bvec4(false, true, false, true);
4050 }
4051
4052 void main() {
4053 bool valid = f_in(outbuf.b);
4054 valid = f_inout(outbuf.b) && valid;
4055 f_out(outbuf.b);
4056 outbuf.valid = valid;
4057 })";
4058
4059 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
4060 glUseProgram(program);
4061
4062 constexpr std::array<GLuint, 5> kOutputInitData = {true, false, true, false, false};
4063 GLBuffer outputBuffer;
4064 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
4065 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kOutputInitData), kOutputInitData.data(),
4066 GL_STATIC_DRAW);
4067 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, outputBuffer);
4068 EXPECT_GL_NO_ERROR();
4069
4070 glDispatchCompute(1, 1, 1);
4071 EXPECT_GL_NO_ERROR();
4072
4073 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4074
4075 const GLuint *ptr = reinterpret_cast<const GLuint *>(
4076 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kOutputInitData), GL_MAP_READ_BIT));
4077 fprintf(stderr, "%d %d %d %d %d\n", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4]);
4078 EXPECT_FALSE(ptr[0]);
4079 EXPECT_TRUE(ptr[1]);
4080 EXPECT_FALSE(ptr[2]);
4081 EXPECT_TRUE(ptr[3]);
4082 EXPECT_TRUE(ptr[4]);
4083 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4084 }
4085
4086 // Test that using a sampler2D and samplerExternalOES in the same shader works
4087 // (anglebug.com/42260512)
TEST_P(GLSLTest,ExternalAnd2DSampler)4088 TEST_P(GLSLTest, ExternalAnd2DSampler)
4089 {
4090 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_EGL_image_external"));
4091
4092 constexpr char kFS[] = R"(#extension GL_OES_EGL_image_external : enable
4093 precision mediump float;
4094 uniform samplerExternalOES tex0;
4095 uniform sampler2D tex1;
4096 void main(void)
4097 {
4098 vec2 uv = vec2(0.0, 0.0);
4099 gl_FragColor = texture2D(tex0, uv) + texture2D(tex1, uv);
4100 })";
4101
4102 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
4103 }
4104
4105 // Tests that monomorphizing functions does not crash if there is a main prototype.
TEST_P(GLSLTest,MonomorphizeMainPrototypeNoCrash)4106 TEST_P(GLSLTest, MonomorphizeMainPrototypeNoCrash)
4107 {
4108 constexpr char kFS[] = R"(precision mediump float;
4109 struct S { sampler2D source; };
4110 vec4 f(S s)
4111 {
4112 return texture2D(s.source, vec2(5));
4113 }
4114 uniform S green;
4115 void main();
4116 void main() {
4117 f(green);
4118 })";
4119 CompileShader(GL_FRAGMENT_SHADER, kFS);
4120 ASSERT_GL_NO_ERROR();
4121 }
4122
4123 // Test that using a varying matrix array is supported.
TEST_P(GLSLTest,VaryingMatrixArray)4124 TEST_P(GLSLTest, VaryingMatrixArray)
4125 {
4126 constexpr char kVS[] =
4127 "uniform vec2 u_a1;\n"
4128 "uniform vec2 u_a2;\n"
4129 "attribute vec4 a_position;\n"
4130 "varying mat2 v_mat[2];\n"
4131 "void main() {\n"
4132 " v_mat[0] = mat2(u_a1, u_a2);\n"
4133 " v_mat[1] = mat2(1.0 - u_a2, 1.0 - u_a1);\n"
4134 " gl_Position = a_position;\n"
4135 "}";
4136
4137 constexpr char kFS[] =
4138 "precision mediump float;\n"
4139 "varying mat2 v_mat[2];\n"
4140 "void main(void)\n"
4141 "{\n"
4142 " gl_FragColor = vec4(v_mat[0][0].x, v_mat[0][0].y, v_mat[1][0].x, 1.0);\n"
4143 "}";
4144
4145 ANGLE_GL_PROGRAM(program, kVS, kFS);
4146
4147 GLint oneIndex = glGetUniformLocation(program, "u_a1");
4148 ASSERT_NE(-1, oneIndex);
4149 GLint twoIndex = glGetUniformLocation(program, "u_a2");
4150 ASSERT_NE(-1, twoIndex);
4151 glUseProgram(program);
4152 glUniform2f(oneIndex, 1, 0.5f);
4153 glUniform2f(twoIndex, 0.25f, 0.125f);
4154
4155 drawQuad(program, "a_position", 0.5f);
4156 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 127, 255 - 63, 255), 1.0);
4157 }
4158
4159 // Test that using a centroid varying matrix array is supported.
TEST_P(GLSLTest_ES3,CentroidVaryingMatrixArray)4160 TEST_P(GLSLTest_ES3, CentroidVaryingMatrixArray)
4161 {
4162 constexpr char kVS[] =
4163 "#version 300 es\n"
4164 "uniform vec2 u_a1;\n"
4165 "uniform vec2 u_a2;\n"
4166 "in vec4 a_position;\n"
4167 "centroid out mat3x2 v_mat[2];\n"
4168 "void main() {\n"
4169 " v_mat[0] = mat3x2(u_a1, u_a2, vec2(0.0));\n"
4170 " v_mat[1] = mat3x2(vec2(0.0), 1.0 - u_a2, 1.0 - u_a1);\n"
4171 " gl_Position = a_position;\n"
4172 "}";
4173
4174 constexpr char kFS[] =
4175 "#version 300 es\n"
4176 "precision mediump float;\n"
4177 "centroid in mat3x2 v_mat[2];\n"
4178 "layout(location = 0) out vec4 out_color;\n"
4179 "void main(void)\n"
4180 "{\n"
4181 " out_color = vec4(v_mat[0][0].x, v_mat[0][0].y, v_mat[1][1].x, 1.0);\n"
4182 "}";
4183
4184 ANGLE_GL_PROGRAM(program, kVS, kFS);
4185
4186 GLint oneIndex = glGetUniformLocation(program, "u_a1");
4187 ASSERT_NE(-1, oneIndex);
4188 GLint twoIndex = glGetUniformLocation(program, "u_a2");
4189 ASSERT_NE(-1, twoIndex);
4190 glUseProgram(program);
4191 glUniform2f(oneIndex, 1, 0.5f);
4192 glUniform2f(twoIndex, 0.25f, 0.125f);
4193
4194 drawQuad(program, "a_position", 0.5f);
4195 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 127, 255 - 63, 255), 1.0);
4196 }
4197
4198 // Test that using a flat varying matrix array is supported.
TEST_P(GLSLTest_ES3,FlatVaryingMatrixArray)4199 TEST_P(GLSLTest_ES3, FlatVaryingMatrixArray)
4200 {
4201 constexpr char kVS[] =
4202 "#version 300 es\n"
4203 "uniform vec2 u_a1;\n"
4204 "uniform vec2 u_a2;\n"
4205 "in vec4 a_position;\n"
4206 "flat out mat2 v_mat[2];\n"
4207 "void main() {\n"
4208 " v_mat[0] = mat2(u_a1, u_a2);\n"
4209 " v_mat[1] = mat2(u_a2, u_a1);\n"
4210 " gl_Position = a_position;\n"
4211 "}";
4212
4213 constexpr char kFS[] =
4214 "#version 300 es\n"
4215 "precision mediump float;\n"
4216 "flat in mat2 v_mat[2];\n"
4217 "layout(location = 0) out vec4 out_color;\n"
4218 "void main(void)\n"
4219 "{\n"
4220 " out_color = vec4(v_mat[0][0].x, v_mat[0][0].y, v_mat[1][0].x, 1.0);\n"
4221 "}";
4222
4223 ANGLE_GL_PROGRAM(program, kVS, kFS);
4224
4225 GLint oneIndex = glGetUniformLocation(program, "u_a1");
4226 ASSERT_NE(-1, oneIndex);
4227 GLint twoIndex = glGetUniformLocation(program, "u_a2");
4228 ASSERT_NE(-1, twoIndex);
4229 glUseProgram(program);
4230 glUniform2f(oneIndex, 1, 0.5f);
4231 glUniform2f(twoIndex, 0.25f, 0.125f);
4232
4233 drawQuad(program, "a_position", 0.5f);
4234 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 127, 63, 255), 1.0);
4235 }
4236
4237 // Test that using a varying matrix array works with a particular input names scheme.
4238 // Test that having "mat3 a[*]" and "mat2 a_0" does not cause internal shader compile failures.
4239 // For a buggy naming scheme both would expand into a_0_0 and cause problems.
TEST_P(GLSLTest_ES3,VaryingMatrixArrayNaming2)4240 TEST_P(GLSLTest_ES3, VaryingMatrixArrayNaming2)
4241 {
4242 constexpr char kVS[] = R"(#version 300 es
4243 precision mediump float;
4244 uniform mat3 r0;
4245 uniform mat2 r1;
4246 in vec4 a_position;
4247 out mat2 a_0;
4248 out mat3 a[2];
4249 void main() {
4250 a[0] = r0;
4251 a[1] = r0 + mat3(1, 1, 1, 1, 1, 1, 1, 1, 1);
4252 a_0 = r1;
4253 gl_Position = a_position;
4254 })";
4255 constexpr char kFS[] = R"(#version 300 es
4256 precision mediump float;
4257 in mat2 a_0;
4258 in mat3 a[2];
4259 layout(location = 0) out vec4 o;
4260 void main(void) {
4261 mat3 diff0 = a[0] - mat3(0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8);
4262 mat3 diff1 = a[1] - mat3(1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8);
4263 mat2 diff2 = a_0 - mat2(3.0, 3.1, 3.2, 3.3);
4264 o.r = all(lessThan(abs(diff0[0]) + abs(diff0[1]) + abs(diff0[2]), vec3(0.01))) ? 1.0 : 0.0;
4265 o.g = all(lessThan(abs(diff1[0]) + abs(diff1[1]) + abs(diff1[2]), vec3(0.01))) ? 1.0 : 0.0;
4266 o.b = all(lessThan(abs(diff2[0]) + abs(diff2[1]), vec2(0.01))) ? 1.0 : 0.0;
4267 o.a = 1.0;
4268 })";
4269 ANGLE_GL_PROGRAM(program, kVS, kFS);
4270
4271 GLint r0 = glGetUniformLocation(program, "r0");
4272 ASSERT_NE(-1, r0);
4273 GLint r1 = glGetUniformLocation(program, "r1");
4274 ASSERT_NE(-1, r1);
4275 glUseProgram(program);
4276 float r0v[] = {0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f};
4277 glUniformMatrix3fv(r0, 1, false, r0v);
4278 float r1v[] = {3.0f, 3.1f, 3.2f, 3.3f};
4279 glUniformMatrix2fv(r1, 1, false, r1v);
4280 drawQuad(program, "a_position", 0.5f);
4281 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 255, 255, 255), 1.0);
4282 }
4283
4284 // Test that literal infinity can be written out from the shader translator.
4285 // 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)4286 TEST_P(GLSLTest_ES3, LiteralInfinityOutput)
4287 {
4288 constexpr char kFS[] =
4289 "#version 300 es\n"
4290 "precision highp float;\n"
4291 "out vec4 out_color;\n"
4292 "uniform float u;\n"
4293 "void main()\n"
4294 "{\n"
4295 " float infVar = 1.0e40 - u;\n"
4296 " bool correct = isinf(infVar) && infVar > 0.0;\n"
4297 " out_color = correct ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4298 "}\n";
4299
4300 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4301 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
4302 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4303 }
4304
4305 // Test that literal negative infinity can be written out from the shader translator.
4306 // 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)4307 TEST_P(GLSLTest_ES3, LiteralNegativeInfinityOutput)
4308 {
4309 constexpr char kFS[] =
4310 "#version 300 es\n"
4311 "precision highp float;\n"
4312 "out vec4 out_color;\n"
4313 "uniform float u;\n"
4314 "void main()\n"
4315 "{\n"
4316 " float infVar = -1.0e40 + u;\n"
4317 " bool correct = isinf(infVar) && infVar < 0.0;\n"
4318 " out_color = correct ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4319 "}\n";
4320
4321 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4322 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
4323 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4324 }
4325
4326 // The following MultipleDeclaration* tests are testing TranslatorHLSL specific simplification
4327 // passes. Because the interaction of multiple passes must be tested, it is difficult to write
4328 // a unittest for them. Instead we add the tests as end2end so will in particular test
4329 // TranslatorHLSL when run on Windows.
4330
4331 // Test that passes splitting multiple declarations and comma operators are correctly ordered.
TEST_P(GLSLTest_ES3,MultipleDeclarationWithCommaOperator)4332 TEST_P(GLSLTest_ES3, MultipleDeclarationWithCommaOperator)
4333 {
4334 constexpr char kFS[] = R"(#version 300 es
4335 precision mediump float;
4336 out vec4 color;
4337
4338 uniform float u;
4339 float c = 0.0;
4340 float sideEffect()
4341 {
4342 c = u;
4343 return c;
4344 }
4345
4346 void main(void)
4347 {
4348 float a = 0.0, b = ((gl_FragCoord.x < 0.5 ? a : sideEffect()), a);
4349 color = vec4(b + c);
4350 })";
4351
4352 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4353 }
4354
4355 // Test that passes splitting multiple declarations and comma operators and for loops are
4356 // correctly ordered.
TEST_P(GLSLTest_ES3,MultipleDeclarationWithCommaOperatorInForLoop)4357 TEST_P(GLSLTest_ES3, MultipleDeclarationWithCommaOperatorInForLoop)
4358 {
4359 constexpr char kFS[] = R"(#version 300 es
4360 precision mediump float;
4361 out vec4 color;
4362
4363 uniform float u;
4364 float c = 0.0;
4365 float sideEffect()
4366 {
4367 c = u;
4368 return c;
4369 }
4370
4371 void main(void)
4372 {
4373 for(float a = 0.0, b = ((gl_FragCoord.x < 0.5 ? a : sideEffect()), a); a < 10.0; a++)
4374 {
4375 b += 1.0;
4376 color = vec4(b);
4377 }
4378 })";
4379
4380 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4381 }
4382
4383 // Test that splitting multiple declaration in for loops works with no loop condition
TEST_P(GLSLTest_ES3,MultipleDeclarationInForLoopEmptyCondition)4384 TEST_P(GLSLTest_ES3, MultipleDeclarationInForLoopEmptyCondition)
4385 {
4386 constexpr char kFS[] =
4387 "#version 300 es\n"
4388 "precision mediump float;\n"
4389 "out vec4 color;\n"
4390 "void main(void)\n"
4391 "{\n"
4392 " for(float a = 0.0, b = 1.0;; a++)\n"
4393 " {\n"
4394 " b += 1.0;\n"
4395 " if (a > 10.0) {break;}\n"
4396 " color = vec4(b);\n"
4397 " }\n"
4398 "}\n";
4399
4400 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4401 }
4402
4403 // Test that splitting multiple declaration in for loops works with no loop expression
TEST_P(GLSLTest_ES3,MultipleDeclarationInForLoopEmptyExpression)4404 TEST_P(GLSLTest_ES3, MultipleDeclarationInForLoopEmptyExpression)
4405 {
4406 constexpr char kFS[] =
4407 "#version 300 es\n"
4408 "precision mediump float;\n"
4409 "out vec4 color;\n"
4410 "void main(void)\n"
4411 "{\n"
4412 " for(float a = 0.0, b = 1.0; a < 10.0;)\n"
4413 " {\n"
4414 " b += 1.0;\n"
4415 " a += 1.0;\n"
4416 " color = vec4(b);\n"
4417 " }\n"
4418 "}\n";
4419
4420 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4421 }
4422
4423 // Test that dynamic indexing of a matrix inside a dynamic indexing of a vector in an l-value works
4424 // correctly.
TEST_P(GLSLTest_ES3,NestedDynamicIndexingInLValue)4425 TEST_P(GLSLTest_ES3, NestedDynamicIndexingInLValue)
4426 {
4427 constexpr char kFS[] =
4428 "#version 300 es\n"
4429 "precision mediump float;\n"
4430 "out vec4 my_FragColor;\n"
4431 "uniform int u_zero;\n"
4432 "void main() {\n"
4433 " mat2 m = mat2(0.0, 0.0, 0.0, 0.0);\n"
4434 " m[u_zero + 1][u_zero + 1] = float(u_zero + 1);\n"
4435 " float f = m[1][1];\n"
4436 " my_FragColor = vec4(1.0 - f, f, 0.0, 1.0);\n"
4437 "}\n";
4438
4439 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4440 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
4441 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4442 }
4443
4444 class WebGLGLSLTest : public GLSLTest
4445 {
4446 protected:
WebGLGLSLTest()4447 WebGLGLSLTest() { setWebGLCompatibilityEnabled(true); }
4448 };
4449
4450 class WebGL2GLSLTest : public GLSLTest
4451 {
4452 protected:
WebGL2GLSLTest()4453 WebGL2GLSLTest() { setWebGLCompatibilityEnabled(true); }
4454 };
4455
TEST_P(WebGLGLSLTest,MaxVaryingVec4PlusFragCoord)4456 TEST_P(WebGLGLSLTest, MaxVaryingVec4PlusFragCoord)
4457 {
4458 GLint maxVaryings = 0;
4459 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4460
4461 // Generate shader code that uses gl_FragCoord, a special fragment shader variables.
4462 // This test should fail, since we are really using (maxVaryings + 1) varyings.
4463 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, true, false, false, false);
4464 }
4465
TEST_P(WebGLGLSLTest,MaxVaryingVec4PlusPointCoord)4466 TEST_P(WebGLGLSLTest, MaxVaryingVec4PlusPointCoord)
4467 {
4468 GLint maxVaryings = 0;
4469 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4470
4471 // Generate shader code that uses gl_FragCoord, a special fragment shader variables.
4472 // This test should fail, since we are really using (maxVaryings + 1) varyings.
4473 VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, false, true, false, false);
4474 }
4475
TEST_P(WebGLGLSLTest,MaxPlusOneVaryingVec3)4476 TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec3)
4477 {
4478 GLint maxVaryings = 0;
4479 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4480
4481 VaryingTestBase(0, 0, 0, 0, maxVaryings + 1, 0, 0, 0, false, false, false, false);
4482 }
4483
TEST_P(WebGLGLSLTest,MaxPlusOneVaryingVec3Array)4484 TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec3Array)
4485 {
4486 GLint maxVaryings = 0;
4487 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4488
4489 VaryingTestBase(0, 0, 0, 0, 0, maxVaryings / 2 + 1, 0, 0, false, false, false, false);
4490 }
4491
TEST_P(WebGLGLSLTest,MaxVaryingVec3AndOneVec2)4492 TEST_P(WebGLGLSLTest, MaxVaryingVec3AndOneVec2)
4493 {
4494 GLint maxVaryings = 0;
4495 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4496
4497 VaryingTestBase(0, 0, 1, 0, maxVaryings, 0, 0, 0, false, false, false, false);
4498 }
4499
TEST_P(WebGLGLSLTest,MaxPlusOneVaryingVec2)4500 TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec2)
4501 {
4502 GLint maxVaryings = 0;
4503 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4504
4505 VaryingTestBase(0, 0, 2 * maxVaryings + 1, 0, 0, 0, 0, 0, false, false, false, false);
4506 }
4507
TEST_P(WebGLGLSLTest,MaxVaryingVec3ArrayAndMaxPlusOneFloatArray)4508 TEST_P(WebGLGLSLTest, MaxVaryingVec3ArrayAndMaxPlusOneFloatArray)
4509 {
4510 GLint maxVaryings = 0;
4511 glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4512
4513 VaryingTestBase(0, maxVaryings / 2 + 1, 0, 0, 0, 0, 0, maxVaryings / 2, false, false, false,
4514 false);
4515 }
4516
4517 // Test that FindLSB and FindMSB return correct values in their corner cases.
TEST_P(GLSLTest_ES31,FindMSBAndFindLSBCornerCases)4518 TEST_P(GLSLTest_ES31, FindMSBAndFindLSBCornerCases)
4519 {
4520 // Suspecting AMD driver bug - failure seen on bots running on AMD R5 230.
4521 ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL() && IsLinux());
4522
4523 // Failing on N5X Oreo http://anglebug.com/42261013
4524 ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
4525
4526 constexpr char kFS[] =
4527 "#version 310 es\n"
4528 "precision mediump float;\n"
4529 "out vec4 my_FragColor;\n"
4530 "uniform int u_zero;\n"
4531 "void main() {\n"
4532 " if (findLSB(u_zero) == -1 && findMSB(u_zero) == -1 && findMSB(u_zero - 1) == -1)\n"
4533 " {\n"
4534 " my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
4535 " }\n"
4536 " else\n"
4537 " {\n"
4538 " my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
4539 " }\n"
4540 "}\n";
4541
4542 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4543 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
4544 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4545 }
4546
4547 // Test that reading from a swizzled vector that is dynamically indexed succeeds.
TEST_P(GLSLTest_ES3,ReadFromDynamicIndexingOfSwizzledVector)4548 TEST_P(GLSLTest_ES3, ReadFromDynamicIndexingOfSwizzledVector)
4549 {
4550 constexpr char kFS[] = R"(#version 300 es
4551 precision highp float;
4552
4553 uniform int index;
4554 uniform vec4 data;
4555
4556 out vec4 color;
4557 void main() {
4558 color = vec4(vec4(data.x, data.y, data.z, data.w).zyxw[index], 0, 0, 1);
4559 })";
4560
4561 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4562 glUseProgram(program);
4563
4564 GLint dataLoc = glGetUniformLocation(program, "data");
4565 glUniform4f(dataLoc, 0.2, 0.4, 0.6, 0.8);
4566 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
4567
4568 EXPECT_PIXEL_NEAR(0, 0, 153, 0, 0, 255, 1);
4569 }
4570
4571 // Test that writing into a swizzled vector that is dynamically indexed succeeds.
TEST_P(GLSLTest_ES3,WriteIntoDynamicIndexingOfSwizzledVector)4572 TEST_P(GLSLTest_ES3, WriteIntoDynamicIndexingOfSwizzledVector)
4573 {
4574 // http://anglebug.com/40644616
4575 ANGLE_SKIP_TEST_IF(IsOpenGL());
4576
4577 // The shader first assigns v.x to v.z (1.0)
4578 // Then v.y to v.y (2.0)
4579 // Then v.z to v.x (1.0)
4580 constexpr char kFS[] =
4581 "#version 300 es\n"
4582 "precision highp float;\n"
4583 "out vec4 my_FragColor;\n"
4584 "void main() {\n"
4585 " vec3 v = vec3(1.0, 2.0, 3.0);\n"
4586 " for (int i = 0; i < 3; i++) {\n"
4587 " v.zyx[i] = v[i];\n"
4588 " }\n"
4589 " my_FragColor = distance(v, vec3(1.0, 2.0, 1.0)) < 0.01 ? vec4(0, 1, 0, 1) : vec4(1, "
4590 "0, 0, 1);\n"
4591 "}\n";
4592
4593 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4594 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
4595 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4596 }
4597
4598 // Test including Ternary using a uniform block is correctly
4599 // expanded.
TEST_P(GLSLTest_ES3,NamelessUniformBlockTernary)4600 TEST_P(GLSLTest_ES3, NamelessUniformBlockTernary)
4601 {
4602 const char kVS[] = R"(#version 300 es
4603 precision highp float;
4604 out vec4 color_interp;
4605 void main()
4606 {
4607 color_interp = vec4(0.0);
4608 }
4609 )";
4610 const char kFS[] = R"(#version 300 es
4611 precision highp float;
4612 out vec4 fragColor;
4613 in vec4 color_interp;
4614 layout(std140) uniform TestData {
4615 int a;
4616 int b;
4617 };
4618 void main()
4619 {
4620 int c, a1;
4621 a1 += c > 0 ? a : b;
4622 fragColor = vec4(a1,a1,a1,1.0);
4623 }
4624 )";
4625 ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
4626 }
4627
4628 // Test that uniform block variables work as comma expression results.
TEST_P(GLSLTest_ES3,UniformBlockCommaExpressionResult)4629 TEST_P(GLSLTest_ES3, UniformBlockCommaExpressionResult)
4630 {
4631 constexpr char kFS[] = R"(#version 300 es
4632 precision highp float;
4633 layout (std140) uniform C {
4634 float u;
4635 float v;
4636 };
4637 out vec4 o;
4638 void main() {
4639 vec2 z = vec2(1.0 - u, v);
4640 vec2 b = vec2((z=z, u)); // Being tested.
4641 o = vec4(b.x, z.x, b.x, 1.0);
4642 })";
4643 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4644 glUseProgram(program);
4645
4646 constexpr GLfloat kInput1Data[2] = {1.f, 0.f};
4647 GLBuffer input1;
4648 glBindBuffer(GL_UNIFORM_BUFFER, input1);
4649 glBufferData(GL_UNIFORM_BUFFER, sizeof(GLfloat) * 2, &kInput1Data, GL_STATIC_COPY);
4650 const GLuint kInput1Index = glGetUniformBlockIndex(program, "C");
4651 glUniformBlockBinding(program, kInput1Index, 1);
4652 glBindBufferBase(GL_UNIFORM_BUFFER, 1, input1);
4653 glBindBuffer(GL_UNIFORM_BUFFER, 0);
4654 ASSERT_GL_NO_ERROR();
4655
4656 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
4657 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::magenta);
4658 ASSERT_GL_NO_ERROR();
4659 }
4660
4661 // Test that the length() method is correctly translated in Vulkan atomic counter buffer emulation.
TEST_P(GLSLTest_ES31,AtomicCounterArrayLength)4662 TEST_P(GLSLTest_ES31, AtomicCounterArrayLength)
4663 {
4664 // Crashes on an assertion. The driver reports no atomic counter buffers when queried from the
4665 // program, but ANGLE believes there to be one.
4666 //
4667 // This is likely due to the fact that ANGLE generates the following code, as a side effect of
4668 // the code on which .length() is being called:
4669 //
4670 // _uac1[(_uvalue = _utestSideEffectValue)];
4671 //
4672 // The driver is optimizing the subscription out, and calling the atomic counter inactive. This
4673 // was observed on nvidia, mesa and amd/windows.
4674 //
4675 // The fix would be for ANGLE to skip uniforms it believes should exist, but when queried, the
4676 // driver says don't.
4677 //
4678 // http://anglebug.com/42262426
4679 ANGLE_SKIP_TEST_IF(IsOpenGL());
4680
4681 constexpr char kCS[] = R"(#version 310 es
4682 precision mediump float;
4683 layout(local_size_x=1) in;
4684
4685 layout(binding = 0) uniform atomic_uint ac1[2][3][4];
4686 uniform uint testSideEffectValue;
4687
4688 layout(binding = 1, std140) buffer Result
4689 {
4690 uint value;
4691 } result;
4692
4693 void main() {
4694 bool passed = true;
4695 if (ac1.length() != 2)
4696 {
4697 passed = false;
4698 }
4699 uint value = 0u;
4700 if (ac1[value = testSideEffectValue].length() != 3)
4701 {
4702 passed = false;
4703 }
4704 if (value != testSideEffectValue)
4705 {
4706 passed = false;
4707 }
4708 if (ac1[1][value = testSideEffectValue + 1u].length() != 4)
4709 {
4710 passed = false;
4711 }
4712 if (value != testSideEffectValue + 1u)
4713 {
4714 passed = false;
4715 }
4716 result.value = passed ? 255u : 127u;
4717 })";
4718
4719 constexpr unsigned int kUniformTestValue = 17;
4720 constexpr unsigned int kExpectedSuccessValue = 255;
4721 constexpr unsigned int kAtomicCounterRows = 2;
4722 constexpr unsigned int kAtomicCounterCols = 3;
4723
4724 GLint maxAtomicCounters = 0;
4725 glGetIntegerv(GL_MAX_COMPUTE_ATOMIC_COUNTERS, &maxAtomicCounters);
4726 EXPECT_GL_NO_ERROR();
4727
4728 // Required minimum is 8 by the spec
4729 EXPECT_GE(maxAtomicCounters, 8);
4730 ANGLE_SKIP_TEST_IF(static_cast<uint32_t>(maxAtomicCounters) <
4731 kAtomicCounterRows * kAtomicCounterCols);
4732
4733 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
4734 glUseProgram(program);
4735
4736 constexpr unsigned int kBufferData[kAtomicCounterRows * kAtomicCounterCols] = {};
4737 GLBuffer atomicCounterBuffer;
4738 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
4739 glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(kBufferData), kBufferData, GL_STATIC_DRAW);
4740 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
4741
4742 constexpr unsigned int kOutputInitValue = 0;
4743 GLBuffer shaderStorageBuffer;
4744 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer);
4745 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kOutputInitValue), &kOutputInitValue,
4746 GL_STATIC_DRAW);
4747 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, shaderStorageBuffer);
4748
4749 GLint uniformLocation = glGetUniformLocation(program, "testSideEffectValue");
4750 EXPECT_NE(uniformLocation, -1);
4751 glUniform1ui(uniformLocation, kUniformTestValue);
4752 EXPECT_GL_NO_ERROR();
4753
4754 glDispatchCompute(1, 1, 1);
4755
4756 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4757
4758 const GLuint *ptr = reinterpret_cast<const GLuint *>(
4759 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(GLuint), GL_MAP_READ_BIT));
4760 EXPECT_EQ(*ptr, kExpectedSuccessValue);
4761 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4762 }
4763
4764 // Test that inactive images don't cause any errors.
TEST_P(GLSLTest_ES31,InactiveImages)4765 TEST_P(GLSLTest_ES31, InactiveImages)
4766 {
4767 ANGLE_SKIP_TEST_IF(IsD3D11());
4768
4769 constexpr char kCS[] = R"(#version 310 es
4770 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
4771 layout(rgba32ui) uniform highp readonly uimage2D image1;
4772 layout(rgba32ui) uniform highp readonly uimage2D image2[4];
4773 void main()
4774 {
4775 })";
4776
4777 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
4778
4779 glUseProgram(program);
4780 glDispatchCompute(1, 1, 1);
4781 EXPECT_GL_NO_ERROR();
4782
4783 // Verify that the images are indeed inactive.
4784 GLuint index = glGetProgramResourceIndex(program, GL_UNIFORM, "image1");
4785 EXPECT_GL_NO_ERROR();
4786 EXPECT_EQ(GL_INVALID_INDEX, index);
4787
4788 index = glGetProgramResourceIndex(program, GL_UNIFORM, "image2");
4789 EXPECT_GL_NO_ERROR();
4790 EXPECT_EQ(GL_INVALID_INDEX, index);
4791 }
4792
4793 // Test that inactive atomic counters don't cause any errors.
TEST_P(GLSLTest_ES31,InactiveAtomicCounters)4794 TEST_P(GLSLTest_ES31, InactiveAtomicCounters)
4795 {
4796 constexpr char kCS[] = R"(#version 310 es
4797 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
4798 layout(binding = 0, offset = 0) uniform atomic_uint ac1;
4799 layout(binding = 0, offset = 4) uniform atomic_uint ac2[5];
4800 void main()
4801 {
4802 })";
4803
4804 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
4805
4806 glUseProgram(program);
4807 glDispatchCompute(1, 1, 1);
4808 EXPECT_GL_NO_ERROR();
4809
4810 // Verify that the atomic counters are indeed inactive.
4811 GLuint index = glGetProgramResourceIndex(program, GL_UNIFORM, "ac1");
4812 EXPECT_GL_NO_ERROR();
4813 EXPECT_EQ(GL_INVALID_INDEX, index);
4814
4815 index = glGetProgramResourceIndex(program, GL_UNIFORM, "ac2");
4816 EXPECT_GL_NO_ERROR();
4817 EXPECT_EQ(GL_INVALID_INDEX, index);
4818 }
4819
4820 // Test that inactive samplers in structs don't cause any errors.
TEST_P(GLSLTest_ES31,InactiveSamplersInStructCS)4821 TEST_P(GLSLTest_ES31, InactiveSamplersInStructCS)
4822 {
4823 constexpr char kCS[] = R"(#version 310 es
4824 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
4825 struct S
4826 {
4827 vec4 v;
4828 sampler2D t[10];
4829 };
4830 uniform S s;
4831 void main()
4832 {
4833 })";
4834
4835 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
4836
4837 glUseProgram(program);
4838 glDispatchCompute(1, 1, 1);
4839 EXPECT_GL_NO_ERROR();
4840 }
4841
4842 // Test that array indices for arrays of arrays of basic types work as expected.
TEST_P(GLSLTest_ES31,ArraysOfArraysBasicType)4843 TEST_P(GLSLTest_ES31, ArraysOfArraysBasicType)
4844 {
4845 constexpr char kFS[] =
4846 "#version 310 es\n"
4847 "precision mediump float;\n"
4848 "out vec4 my_FragColor;\n"
4849 "uniform ivec2 test[2][2];\n"
4850 "void main() {\n"
4851 " bool passed = true;\n"
4852 " for (int i = 0; i < 2; i++) {\n"
4853 " for (int j = 0; j < 2; j++) {\n"
4854 " if (test[i][j] != ivec2(i + 1, j + 1)) {\n"
4855 " passed = false;\n"
4856 " }\n"
4857 " }\n"
4858 " }\n"
4859 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4860 "}\n";
4861
4862 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4863 glUseProgram(program);
4864 for (int i = 0; i < 2; i++)
4865 {
4866 for (int j = 0; j < 2; j++)
4867 {
4868 std::stringstream uniformName;
4869 uniformName << "test[" << i << "][" << j << "]";
4870 GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
4871 // All array indices should be used.
4872 EXPECT_NE(uniformLocation, -1);
4873 glUniform2i(uniformLocation, i + 1, j + 1);
4874 }
4875 }
4876 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
4877 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4878 }
4879
4880 // Test that array indices for arrays of arrays of basic types work as expected
4881 // inside blocks.
TEST_P(GLSLTest_ES31,ArraysOfArraysBlockBasicType)4882 TEST_P(GLSLTest_ES31, ArraysOfArraysBlockBasicType)
4883 {
4884 // anglebug.com/42262465 - fails on AMD Windows
4885 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL());
4886 constexpr char kFS[] =
4887 "#version 310 es\n"
4888 "precision mediump float;\n"
4889 "out vec4 my_FragColor;\n"
4890 "layout(packed) uniform UBO { ivec2 test[2][2]; } ubo_data;\n"
4891 "void main() {\n"
4892 " bool passed = true;\n"
4893 " for (int i = 0; i < 2; i++) {\n"
4894 " for (int j = 0; j < 2; j++) {\n"
4895 " if (ubo_data.test[i][j] != ivec2(i + 1, j + 1)) {\n"
4896 " passed = false;\n"
4897 " }\n"
4898 " }\n"
4899 " }\n"
4900 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4901 "}\n";
4902
4903 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4904 glUseProgram(program);
4905 // Use interface queries to determine buffer size and offset
4906 GLuint uboBlockIndex = glGetProgramResourceIndex(program, GL_UNIFORM_BLOCK, "UBO");
4907 GLenum uboDataSizeProp = GL_BUFFER_DATA_SIZE;
4908 GLint uboDataSize;
4909 glGetProgramResourceiv(program, GL_UNIFORM_BLOCK, uboBlockIndex, 1, &uboDataSizeProp, 1,
4910 nullptr, &uboDataSize);
4911 std::unique_ptr<char[]> uboData(new char[uboDataSize]);
4912 for (int i = 0; i < 2; i++)
4913 {
4914 std::stringstream resourceName;
4915 resourceName << "UBO.test[" << i << "][0]";
4916 GLenum resourceProps[] = {GL_ARRAY_STRIDE, GL_OFFSET};
4917 struct
4918 {
4919 GLint stride;
4920 GLint offset;
4921 } values;
4922 GLuint resourceIndex =
4923 glGetProgramResourceIndex(program, GL_UNIFORM, resourceName.str().c_str());
4924 ASSERT_NE(resourceIndex, GL_INVALID_INDEX);
4925 glGetProgramResourceiv(program, GL_UNIFORM, resourceIndex, 2, &resourceProps[0], 2, nullptr,
4926 &values.stride);
4927 for (int j = 0; j < 2; j++)
4928 {
4929 GLint(&dataPtr)[2] =
4930 *reinterpret_cast<GLint(*)[2]>(&uboData[values.offset + j * values.stride]);
4931 dataPtr[0] = i + 1;
4932 dataPtr[1] = j + 1;
4933 }
4934 }
4935 GLBuffer ubo;
4936 glBindBuffer(GL_UNIFORM_BUFFER, ubo);
4937 glBufferData(GL_UNIFORM_BUFFER, uboDataSize, &uboData[0], GL_STATIC_DRAW);
4938 GLuint ubo_index = glGetUniformBlockIndex(program, "UBO");
4939 ASSERT_NE(ubo_index, GL_INVALID_INDEX);
4940 glUniformBlockBinding(program, ubo_index, 5);
4941 glBindBufferBase(GL_UNIFORM_BUFFER, 5, ubo);
4942 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
4943 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4944 }
4945
4946 // Test that arrays of arrays of samplers work as expected.
TEST_P(GLSLTest_ES31,ArraysOfArraysSampler)4947 TEST_P(GLSLTest_ES31, ArraysOfArraysSampler)
4948 {
4949 constexpr char kFS[] =
4950 "#version 310 es\n"
4951 "precision mediump float;\n"
4952 "out vec4 my_FragColor;\n"
4953 "uniform mediump isampler2D test[2][2];\n"
4954 "void main() {\n"
4955 " bool passed = true;\n"
4956 "#define DO_CHECK(i,j) \\\n"
4957 " if (texture(test[i][j], vec2(0.0, 0.0)) != ivec4(i + 1, j + 1, 0, 1)) { \\\n"
4958 " passed = false; \\\n"
4959 " }\n"
4960 " DO_CHECK(0, 0)\n"
4961 " DO_CHECK(0, 1)\n"
4962 " DO_CHECK(1, 0)\n"
4963 " DO_CHECK(1, 1)\n"
4964 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4965 "}\n";
4966
4967 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4968 glUseProgram(program);
4969 GLTexture textures[2][2];
4970 for (int i = 0; i < 2; i++)
4971 {
4972 for (int j = 0; j < 2; j++)
4973 {
4974 // First generate the texture
4975 int textureUnit = i * 2 + j;
4976 glActiveTexture(GL_TEXTURE0 + textureUnit);
4977 glBindTexture(GL_TEXTURE_2D, textures[i][j]);
4978 GLint texData[2] = {i + 1, j + 1};
4979 glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32I, 1, 1, 0, GL_RG_INTEGER, GL_INT, &texData[0]);
4980 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4981 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4982 // Then send it as a uniform
4983 std::stringstream uniformName;
4984 uniformName << "test[" << i << "][" << j << "]";
4985 GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
4986 // All array indices should be used.
4987 EXPECT_NE(uniformLocation, -1);
4988 glUniform1i(uniformLocation, textureUnit);
4989 }
4990 }
4991 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
4992 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4993 }
4994
4995 // Test that arrays of arrays of images work as expected.
TEST_P(GLSLTest_ES31,ArraysOfArraysImage)4996 TEST_P(GLSLTest_ES31, ArraysOfArraysImage)
4997 {
4998 // http://anglebug.com/42263641
4999 ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
5000
5001 // Fails on D3D due to mistranslation.
5002 ANGLE_SKIP_TEST_IF(IsD3D());
5003
5004 // Fails on Android on GLES.
5005 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
5006
5007 GLint maxTextures, maxComputeImageUniforms;
5008 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextures);
5009 glGetIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &maxComputeImageUniforms);
5010 ANGLE_SKIP_TEST_IF(maxTextures < 1 * 2 * 3);
5011 ANGLE_SKIP_TEST_IF(maxComputeImageUniforms < 1 * 2 * 3);
5012
5013 constexpr char kComputeShader[] = R"(#version 310 es
5014 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
5015 layout(binding = 0, r32ui) uniform highp readonly uimage2D image[1][2][3];
5016 layout(binding = 1, std430) buffer Output {
5017 uint image_value;
5018 } outbuf;
5019
5020 void main(void)
5021 {
5022 outbuf.image_value = uint(0.0);
5023 outbuf.image_value += imageLoad(image[0][0][0], ivec2(0, 0)).x;
5024 outbuf.image_value += imageLoad(image[0][0][1], ivec2(0, 0)).x;
5025 outbuf.image_value += imageLoad(image[0][0][2], ivec2(0, 0)).x;
5026 outbuf.image_value += imageLoad(image[0][1][0], ivec2(0, 0)).x;
5027 outbuf.image_value += imageLoad(image[0][1][1], ivec2(0, 0)).x;
5028 outbuf.image_value += imageLoad(image[0][1][2], ivec2(0, 0)).x;
5029 })";
5030 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
5031 EXPECT_GL_NO_ERROR();
5032
5033 glUseProgram(program);
5034
5035 GLuint outputInitData[1] = {10};
5036 GLBuffer outputBuffer;
5037 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
5038 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), outputInitData, GL_STATIC_DRAW);
5039 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
5040 EXPECT_GL_NO_ERROR();
5041
5042 GLuint imageData = 200u;
5043 GLTexture images[1][2][3];
5044 for (int i = 0; i < 1; i++)
5045 {
5046 for (int j = 0; j < 2; j++)
5047 {
5048 for (int k = 0; k < 3; k++)
5049 {
5050 glBindTexture(GL_TEXTURE_2D, images[i][j][k]);
5051 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
5052 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT,
5053 &imageData);
5054 glBindImageTexture(i * 6 + j * 3 + k, images[i][j][k], 0, GL_FALSE, 0, GL_READ_ONLY,
5055 GL_R32UI);
5056 EXPECT_GL_NO_ERROR();
5057 }
5058 }
5059 }
5060
5061 glDispatchCompute(1, 1, 1);
5062 EXPECT_GL_NO_ERROR();
5063
5064 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5065
5066 // read back
5067 const GLuint *ptr = reinterpret_cast<const GLuint *>(
5068 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
5069 memcpy(outputInitData, ptr, sizeof(outputInitData));
5070 EXPECT_EQ(outputInitData[0], imageData * 1 * 2 * 3);
5071 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
5072 }
5073
5074 // Test that multiple arrays of arrays of images work as expected.
TEST_P(GLSLTest_ES31,ConsecutiveArraysOfArraysImage)5075 TEST_P(GLSLTest_ES31, ConsecutiveArraysOfArraysImage)
5076 {
5077 // http://anglebug.com/42263641
5078 ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
5079
5080 // Fails on D3D due to mistranslation.
5081 ANGLE_SKIP_TEST_IF(IsD3D());
5082
5083 constexpr GLsizei kImage1Layers = 3;
5084 constexpr GLsizei kImage1Rows = 2;
5085 constexpr GLsizei kImage1Cols = 1;
5086 constexpr GLsizei kImage2Rows = 2;
5087 constexpr GLsizei kImage2Cols = 4;
5088
5089 constexpr GLsizei kImage1Units = kImage1Layers * kImage1Rows * kImage1Cols;
5090 constexpr GLsizei kImage2Units = kImage2Rows * kImage2Cols;
5091 constexpr GLsizei kImage3Units = 1;
5092
5093 constexpr GLsizei kTotalImageCount = kImage1Units + kImage2Units + kImage3Units;
5094
5095 GLint maxTextures, maxComputeImageUniforms;
5096 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextures);
5097 glGetIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &maxComputeImageUniforms);
5098 ANGLE_SKIP_TEST_IF(maxTextures < kTotalImageCount);
5099 ANGLE_SKIP_TEST_IF(maxComputeImageUniforms < kTotalImageCount);
5100
5101 constexpr char kComputeShader[] = R"(#version 310 es
5102 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
5103 layout(binding = 0, r32ui) uniform highp readonly uimage2D image1[3][2][1];
5104 layout(binding = 6, r32ui) uniform highp readonly uimage2D image2[2][4];
5105 layout(binding = 14, r32ui) uniform highp readonly uimage2D image3;
5106 layout(binding = 0, std430) buffer Output {
5107 uint image_value;
5108 } outbuf;
5109
5110 void main(void)
5111 {
5112 outbuf.image_value = uint(0.0);
5113
5114 outbuf.image_value += imageLoad(image1[0][0][0], ivec2(0, 0)).x;
5115 outbuf.image_value += imageLoad(image1[0][1][0], ivec2(0, 0)).x;
5116 outbuf.image_value += imageLoad(image1[1][0][0], ivec2(0, 0)).x;
5117 outbuf.image_value += imageLoad(image1[1][1][0], ivec2(0, 0)).x;
5118 outbuf.image_value += imageLoad(image1[2][0][0], ivec2(0, 0)).x;
5119 outbuf.image_value += imageLoad(image1[2][1][0], ivec2(0, 0)).x;
5120
5121 outbuf.image_value += imageLoad(image2[0][0], ivec2(0, 0)).x;
5122 outbuf.image_value += imageLoad(image2[0][1], ivec2(0, 0)).x;
5123 outbuf.image_value += imageLoad(image2[0][2], ivec2(0, 0)).x;
5124 outbuf.image_value += imageLoad(image2[0][3], ivec2(0, 0)).x;
5125 outbuf.image_value += imageLoad(image2[1][0], ivec2(0, 0)).x;
5126 outbuf.image_value += imageLoad(image2[1][1], ivec2(0, 0)).x;
5127 outbuf.image_value += imageLoad(image2[1][2], ivec2(0, 0)).x;
5128 outbuf.image_value += imageLoad(image2[1][3], ivec2(0, 0)).x;
5129
5130 outbuf.image_value += imageLoad(image3, ivec2(0, 0)).x;
5131 })";
5132 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
5133 EXPECT_GL_NO_ERROR();
5134
5135 glUseProgram(program);
5136
5137 constexpr GLuint kOutputInitData = 10;
5138 GLBuffer outputBuffer;
5139 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
5140 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kOutputInitData), &kOutputInitData,
5141 GL_STATIC_DRAW);
5142 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, outputBuffer);
5143 EXPECT_GL_NO_ERROR();
5144
5145 constexpr GLsizei kImage1Binding = 0;
5146 constexpr GLsizei kImage2Binding = kImage1Binding + kImage1Units;
5147 constexpr GLsizei kImage3Binding = kImage2Binding + kImage2Units;
5148
5149 constexpr GLuint kImage1Data = 13;
5150 GLTexture images1[kImage1Layers][kImage1Rows][kImage1Cols];
5151 for (int layer = 0; layer < kImage1Layers; layer++)
5152 {
5153 for (int row = 0; row < kImage1Rows; row++)
5154 {
5155 for (int col = 0; col < kImage1Cols; col++)
5156 {
5157 glBindTexture(GL_TEXTURE_2D, images1[layer][row][col]);
5158 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
5159 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT,
5160 &kImage1Data);
5161 glBindImageTexture(kImage1Binding + (layer * kImage1Rows + row) * kImage1Cols + col,
5162 images1[layer][row][col], 0, GL_FALSE, 0, GL_READ_ONLY,
5163 GL_R32UI);
5164 EXPECT_GL_NO_ERROR();
5165 }
5166 }
5167 }
5168
5169 constexpr GLuint kImage2Data = 17;
5170 GLTexture images2[kImage2Rows][kImage2Cols];
5171 for (int row = 0; row < kImage2Rows; row++)
5172 {
5173 for (int col = 0; col < kImage2Cols; col++)
5174 {
5175 glBindTexture(GL_TEXTURE_2D, images2[row][col]);
5176 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
5177 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT,
5178 &kImage2Data);
5179 glBindImageTexture(kImage2Binding + row * kImage2Cols + col, images2[row][col], 0,
5180 GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
5181 EXPECT_GL_NO_ERROR();
5182 }
5183 }
5184
5185 constexpr GLuint kImage3Data = 19;
5186 GLTexture image3;
5187 glBindTexture(GL_TEXTURE_2D, image3);
5188 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
5189 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &kImage3Data);
5190 glBindImageTexture(kImage3Binding, image3, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
5191 EXPECT_GL_NO_ERROR();
5192
5193 glDispatchCompute(1, 1, 1);
5194 EXPECT_GL_NO_ERROR();
5195
5196 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5197
5198 // read back
5199 const GLuint *ptr = reinterpret_cast<const GLuint *>(
5200 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kOutputInitData), GL_MAP_READ_BIT));
5201 EXPECT_EQ(*ptr,
5202 kImage1Data * kImage1Units + kImage2Data * kImage2Units + kImage3Data * kImage3Units);
5203 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
5204 }
5205
5206 // Test that arrays of arrays of images of r32f format work when passed to functions.
TEST_P(GLSLTest_ES31,ArraysOfArraysOfR32fImages)5207 TEST_P(GLSLTest_ES31, ArraysOfArraysOfR32fImages)
5208 {
5209 // Skip if GL_OES_shader_image_atomic is not enabled.
5210 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_image_atomic"));
5211
5212 // http://anglebug.com/42263641
5213 ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
5214
5215 // Fails on D3D due to mistranslation.
5216 ANGLE_SKIP_TEST_IF(IsD3D());
5217
5218 // Fails on Android on GLES.
5219 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
5220
5221 // http://anglebug.com/42263895
5222 ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGL());
5223
5224 GLint maxComputeImageUniforms;
5225 glGetIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &maxComputeImageUniforms);
5226 ANGLE_SKIP_TEST_IF(maxComputeImageUniforms < 7);
5227
5228 constexpr char kComputeShader[] = R"(#version 310 es
5229 #extension GL_OES_shader_image_atomic : require
5230
5231 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
5232 layout(binding = 0, r32f) uniform highp image2D image1[2][3];
5233 layout(binding = 6, r32f) uniform highp image2D image2;
5234
5235 void testFunction(highp image2D imageOut[2][3])
5236 {
5237 // image1 is an array of 1x1 images.
5238 // image2 is a 1x4 image with the following data:
5239 //
5240 // (0, 0): 234.5
5241 // (0, 1): 4.0
5242 // (0, 2): 456.0
5243 // (0, 3): 987.0
5244
5245
5246 // Write to [0][0]
5247 imageStore(imageOut[0][0], ivec2(0, 0), vec4(1234.5));
5248
5249 // Write to [0][1]
5250 imageStore(imageOut[0][1], ivec2(0, 0), imageLoad(image2, ivec2(0, 0)));
5251
5252 // Write to [0][2]
5253 imageStore(imageOut[0][2], ivec2(0, 0), vec4(imageSize(image2).y));
5254
5255 // Write to [1][0]
5256 imageStore(imageOut[1][0], ivec2(0,
5257 imageSize(image2).y - int(imageLoad(image2, ivec2(0, 1)).x)
5258 ), vec4(678.0));
5259
5260 // Write to [1][1]
5261 imageStore(imageOut[1][1], ivec2(0, 0),
5262 vec4(imageAtomicExchange(image2, ivec2(0, 2), 135.0)));
5263
5264 // Write to [1][2]
5265 imageStore(imageOut[1][2], ivec2(0, 0),
5266 imageLoad(image2, ivec2(imageSize(image2).x - 1, 3)));
5267 }
5268
5269 void main(void)
5270 {
5271 testFunction(image1);
5272 })";
5273 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
5274 EXPECT_GL_NO_ERROR();
5275
5276 glUseProgram(program);
5277
5278 constexpr GLsizei kImageRows = 2;
5279 constexpr GLsizei kImageCols = 3;
5280 constexpr GLfloat kImageData = 0;
5281 GLTexture images[kImageRows][kImageCols];
5282 for (size_t row = 0; row < kImageRows; row++)
5283 {
5284 for (size_t col = 0; col < kImageCols; col++)
5285 {
5286 glBindTexture(GL_TEXTURE_2D, images[row][col]);
5287 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, 1, 1);
5288 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED, GL_FLOAT, &kImageData);
5289 glBindImageTexture(row * kImageCols + col, images[row][col], 0, GL_FALSE, 0,
5290 GL_READ_WRITE, GL_R32F);
5291 EXPECT_GL_NO_ERROR();
5292 }
5293 }
5294
5295 constexpr GLsizei kImage2Size = 4;
5296 constexpr std::array<GLfloat, kImage2Size> kImage2Data = {
5297 234.5f,
5298 4.0f,
5299 456.0f,
5300 987.0f,
5301 };
5302 GLTexture image2;
5303 glBindTexture(GL_TEXTURE_2D, image2);
5304 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, 1, kImage2Size);
5305 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, kImage2Size, GL_RED, GL_FLOAT, kImage2Data.data());
5306 glBindImageTexture(6, image2, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
5307 EXPECT_GL_NO_ERROR();
5308
5309 glDispatchCompute(1, 1, 1);
5310 EXPECT_GL_NO_ERROR();
5311
5312 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5313
5314 // Verify the previous dispatch with another dispatch
5315 constexpr char kVerifyShader[] = R"(#version 310 es
5316 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
5317 layout(binding = 0, r32f) uniform highp readonly image2D image1[2][3];
5318 layout(binding = 6, r32f) uniform highp readonly image2D image2;
5319 layout(binding = 0, std430) buffer Output {
5320 float image2Data[4];
5321 float image1Data[6];
5322 } outbuf;
5323
5324 void main(void)
5325 {
5326 for (int i = 0; i < 4; ++i)
5327 {
5328 outbuf.image2Data[i] = imageLoad(image2, ivec2(0, i)).x;
5329 }
5330 outbuf.image1Data[0] = imageLoad(image1[0][0], ivec2(0, 0)).x;
5331 outbuf.image1Data[1] = imageLoad(image1[0][1], ivec2(0, 0)).x;
5332 outbuf.image1Data[2] = imageLoad(image1[0][2], ivec2(0, 0)).x;
5333 outbuf.image1Data[3] = imageLoad(image1[1][0], ivec2(0, 0)).x;
5334 outbuf.image1Data[4] = imageLoad(image1[1][1], ivec2(0, 0)).x;
5335 outbuf.image1Data[5] = imageLoad(image1[1][2], ivec2(0, 0)).x;
5336 })";
5337 ANGLE_GL_COMPUTE_PROGRAM(verifyProgram, kVerifyShader);
5338 EXPECT_GL_NO_ERROR();
5339
5340 glUseProgram(verifyProgram);
5341
5342 constexpr std::array<GLfloat, kImage2Size + kImageRows * kImageCols> kOutputInitData = {};
5343 GLBuffer outputBuffer;
5344 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
5345 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kOutputInitData), kOutputInitData.data(),
5346 GL_STATIC_DRAW);
5347 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, outputBuffer);
5348 EXPECT_GL_NO_ERROR();
5349
5350 glDispatchCompute(1, 1, 1);
5351 EXPECT_GL_NO_ERROR();
5352
5353 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5354
5355 // Verify
5356 const GLfloat *ptr = reinterpret_cast<const GLfloat *>(
5357 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kOutputInitData), GL_MAP_READ_BIT));
5358
5359 EXPECT_EQ(ptr[0], kImage2Data[0]);
5360 EXPECT_EQ(ptr[1], kImage2Data[1]);
5361 EXPECT_NEAR(ptr[2], 135.0f, 0.0001f);
5362 EXPECT_EQ(ptr[3], kImage2Data[3]);
5363
5364 EXPECT_NEAR(ptr[4], 1234.5f, 0.0001f);
5365 EXPECT_NEAR(ptr[5], kImage2Data[0], 0.0001f);
5366 EXPECT_NEAR(ptr[6], kImage2Size, 0.0001f);
5367 EXPECT_NEAR(ptr[7], 678.0f, 0.0001f);
5368 EXPECT_NEAR(ptr[8], kImage2Data[2], 0.0001f);
5369 EXPECT_NEAR(ptr[9], kImage2Data[3], 0.0001f);
5370
5371 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
5372 }
5373
5374 // Check that imageLoad gives the correct color after clearing the texture -- anglebug.com/42265826
TEST_P(GLSLTest_ES31,ImageLoadAfterClear)5375 TEST_P(GLSLTest_ES31, ImageLoadAfterClear)
5376 {
5377 ANGLE_GL_PROGRAM(program,
5378 R"(#version 310 es
5379 precision highp float;
5380 void main()
5381 {
5382 gl_Position.x = ((gl_VertexID & 1) == 0 ? -1.0 : 1.0);
5383 gl_Position.y = ((gl_VertexID & 2) == 0 ? -1.0 : 1.0);
5384 gl_Position.zw = vec2(0, 1);
5385 })",
5386
5387 R"(#version 310 es
5388 precision highp float;
5389 layout(binding=0, rgba8) readonly highp uniform image2D img;
5390 out vec4 fragColor;
5391 void main()
5392 {
5393 ivec2 imgcoord = ivec2(floor(gl_FragCoord.xy));
5394 fragColor = vec4(1, 0, 0, 0) + imageLoad(img, imgcoord);
5395 })");
5396 ASSERT_TRUE(program.valid());
5397 glUseProgram(program);
5398
5399 GLTexture tex;
5400 glBindTexture(GL_TEXTURE_2D, tex);
5401 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, getWindowWidth(), getWindowHeight());
5402 glBindImageTexture(0, tex, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
5403
5404 // Clear the texture to green.
5405 GLFramebuffer fbo;
5406 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5407 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
5408 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5409 glClearColor(0, 1, 0, 1);
5410 glClear(GL_COLOR_BUFFER_BIT);
5411 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_FRAMEBUFFER_BARRIER_BIT);
5412
5413 // Draw the texture via imageLoad, plus red, into the main framebuffer. Make sure the texture
5414 // was still green. (green + red == yellow.)
5415 glBindFramebuffer(GL_FRAMEBUFFER, 0);
5416 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5417 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5418
5419 EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::yellow);
5420 ASSERT_GL_NO_ERROR();
5421 }
5422
5423 // Check that writeonly image2D handles can be passed as function args.
TEST_P(GLSLTest_ES31,WriteOnlyImage2DAsFunctionArg)5424 TEST_P(GLSLTest_ES31, WriteOnlyImage2DAsFunctionArg)
5425 {
5426 // Create an image.
5427 GLTexture tex;
5428 glBindTexture(GL_TEXTURE_2D, tex);
5429 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, getWindowWidth(), getWindowHeight());
5430
5431 // Clear the image to red.
5432 GLFramebuffer fbo;
5433 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5434 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
5435 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5436
5437 glClearColor(1, 0, 0, 1);
5438 glClear(GL_COLOR_BUFFER_BIT);
5439 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5440
5441 const char kVS[] = R"(#version 310 es
5442 precision highp float;
5443 void main()
5444 {
5445 gl_Position.x = ((gl_VertexID & 1) == 0 ? -1.0 : 1.0);
5446 gl_Position.y = ((gl_VertexID & 2) == 0 ? -1.0 : 1.0);
5447 gl_Position.zw = vec2(0, 1);
5448 })";
5449
5450 const char kFS[] = R"(#version 310 es
5451 precision highp float;
5452 layout(binding=0, rgba8) writeonly highp uniform image2D uniformImage;
5453 void store(writeonly highp image2D img, vec4 color)
5454 {
5455 ivec2 imgcoord = ivec2(floor(gl_FragCoord.xy));
5456 imageStore(img, imgcoord, color);
5457 }
5458 void main()
5459 {
5460 store(uniformImage, vec4(1, 1, 0, 1));
5461 })";
5462
5463 // Store yellow to the image.
5464 ANGLE_GL_PROGRAM(program, kVS, kFS);
5465 glUseProgram(program);
5466
5467 glBindFramebuffer(GL_FRAMEBUFFER, 0);
5468 glBindImageTexture(0, tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
5469 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5470 glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
5471
5472 // Check that the image is yellow.
5473 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5474 EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::yellow);
5475 ASSERT_GL_NO_ERROR();
5476 }
5477
5478 // Check that readonly image2D handles can be passed as function args.
TEST_P(GLSLTest_ES31,ReadOnlyImage2DAsFunctionArg)5479 TEST_P(GLSLTest_ES31, ReadOnlyImage2DAsFunctionArg)
5480 {
5481 const int w = getWindowWidth();
5482 const int h = getWindowHeight();
5483
5484 // Create an image.
5485 GLTexture tex;
5486 glBindTexture(GL_TEXTURE_2D, tex);
5487 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, w, h);
5488
5489 const std::vector<GLColor> kInitData(w * h, GLColor::red);
5490 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, kInitData.data());
5491
5492 // Create a framebuffer.
5493 GLTexture color;
5494 glBindTexture(GL_TEXTURE_2D, color);
5495 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, w, h);
5496
5497 GLFramebuffer fbo;
5498 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5499 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
5500 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5501
5502 // Initialize the framebuffer with the contents of the texture.
5503 glClearColor(0, 0, 0, 0);
5504 glClear(GL_COLOR_BUFFER_BIT);
5505
5506 const char kVS[] = R"(#version 310 es
5507 precision highp float;
5508 void main()
5509 {
5510 gl_Position.x = ((gl_VertexID & 1) == 0 ? -1.0 : 1.0);
5511 gl_Position.y = ((gl_VertexID & 2) == 0 ? -1.0 : 1.0);
5512 gl_Position.zw = vec2(0, 1);
5513 })";
5514
5515 const char kFS[] = R"(#version 310 es
5516 precision highp float;
5517 layout(binding=0, rgba8) readonly highp uniform image2D uniformImage;
5518 out vec4 color;
5519 vec4 load(readonly highp image2D img)
5520 {
5521 ivec2 imgcoord = ivec2(floor(gl_FragCoord.xy));
5522 return imageLoad(img, imgcoord);
5523 }
5524 void main()
5525 {
5526 color = load(uniformImage);
5527 })";
5528
5529 ANGLE_GL_PROGRAM(program, kVS, kFS);
5530 glUseProgram(program);
5531
5532 glBindImageTexture(0, tex, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
5533 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5534
5535 // Check that the framebuffer is red.
5536 EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::red);
5537 ASSERT_GL_NO_ERROR();
5538 }
5539
5540 // Check that the volatile keyword combined with memoryBarrierImage() allow load/store from
5541 // different aliases of the same image -- anglebug.com/42265813
5542 //
5543 // ES 3.1 requires most image formats to be either readonly or writeonly. (It appears that this
5544 // limitation exists due to atomics, since we still have the volatile keyword and the built-in
5545 // memoryBarrierImage(), which ought to allow us to load and store different aliases of the same
5546 // image.) To test this, we create two aliases of the same image -- one for reading and one for
5547 // writing.
TEST_P(GLSLTest_ES31,AliasedLoadStore)5548 TEST_P(GLSLTest_ES31, AliasedLoadStore)
5549 {
5550
5551 GLTexture tex;
5552 glBindTexture(GL_TEXTURE_2D, tex);
5553 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, getWindowWidth(), getWindowHeight());
5554
5555 GLFramebuffer fbo;
5556 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5557 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
5558 glClearColor(1, 0, 0, 1);
5559 glClear(GL_COLOR_BUFFER_BIT);
5560 glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5561
5562 ANGLE_GL_PROGRAM(program,
5563
5564 R"(#version 310 es
5565 precision highp float;
5566 void main()
5567 {
5568 gl_Position.x = ((gl_VertexID & 1) == 0 ? -1.0 : 1.0);
5569 gl_Position.y = ((gl_VertexID & 2) == 0 ? -1.0 : 1.0);
5570 gl_Position.zw = vec2(0, 1);
5571 })",
5572
5573 R"(#version 310 es
5574 precision highp float;
5575 layout(binding=0, rgba8) volatile readonly highp uniform image2D img_r;
5576 layout(binding=0, rgba8) volatile writeonly highp uniform image2D img_w;
5577 uniform vec4 drawColor;
5578 void main()
5579 {
5580 ivec2 coord = ivec2(floor(gl_FragCoord.xy));
5581 vec4 oldval = imageLoad(img_r, coord);
5582 memoryBarrierImage();
5583 imageStore(img_w, coord, oldval + drawColor);
5584 })");
5585
5586 ASSERT_TRUE(program.valid());
5587 glUseProgram(program);
5588 GLint drawColorLocation = glGetUniformLocation(program, "drawColor");
5589
5590 // Tell the driver the binding is GL_READ_WRITE, since it will be referenced by two image2Ds:
5591 // one readeonly and one writeonly.
5592 glBindImageTexture(0, tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8);
5593
5594 glBindFramebuffer(GL_FRAMEBUFFER, 0);
5595 glUniform4f(drawColorLocation, 0, 1, 0, 0);
5596 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5597 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5598
5599 // Ensure the cleared color was loaded before we stored.
5600 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5601 EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::yellow);
5602
5603 ASSERT_GL_NO_ERROR();
5604
5605 // Now make two draws to ensure the imageStore is coherent.
5606 glClear(GL_COLOR_BUFFER_BIT);
5607 glBindFramebuffer(GL_FRAMEBUFFER, 0);
5608 glUniform4f(drawColorLocation, 0, 1, 0, 0);
5609 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5610 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5611 glUniform4f(drawColorLocation, 0, 0, 1, 0);
5612 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5613 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5614
5615 // Ensure the first imageStore was loaded by the second imageLoad.
5616 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5617 EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::white);
5618
5619 ASSERT_GL_NO_ERROR();
5620 }
5621
5622 // Test that structs containing arrays of samplers work as expected.
TEST_P(GLSLTest_ES31,StructArraySampler)5623 TEST_P(GLSLTest_ES31, StructArraySampler)
5624 {
5625 constexpr char kFS[] =
5626 "#version 310 es\n"
5627 "precision mediump float;\n"
5628 "out vec4 my_FragColor;\n"
5629 "struct Data { mediump sampler2D data[2]; };\n"
5630 "uniform Data test;\n"
5631 "void main() {\n"
5632 " my_FragColor = vec4(texture(test.data[0], vec2(0.0, 0.0)).rg,\n"
5633 " texture(test.data[1], vec2(0.0, 0.0)).rg);\n"
5634 "}\n";
5635
5636 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5637 glUseProgram(program);
5638 GLTexture textures[2];
5639 GLColor expected = MakeGLColor(32, 64, 96, 255);
5640 GLubyte data[6] = {}; // Two bytes of padding, so that texture can be initialized with 4 bytes
5641 memcpy(data, expected.data(), sizeof(expected));
5642 for (int i = 0; i < 2; i++)
5643 {
5644 glActiveTexture(GL_TEXTURE0 + i);
5645 glBindTexture(GL_TEXTURE_2D, textures[i]);
5646 // Each element provides two components.
5647 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data + 2 * i);
5648 std::stringstream uniformName;
5649 uniformName << "test.data[" << i << "]";
5650 // Then send it as a uniform
5651 GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
5652 // The uniform should be active.
5653 EXPECT_NE(uniformLocation, -1);
5654 glUniform1i(uniformLocation, i);
5655 }
5656 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
5657 EXPECT_PIXEL_COLOR_EQ(0, 0, expected);
5658 }
5659
5660 // Test that arrays of arrays of samplers inside structs work as expected.
TEST_P(GLSLTest_ES31,StructArrayArraySampler)5661 TEST_P(GLSLTest_ES31, StructArrayArraySampler)
5662 {
5663 constexpr char kFS[] =
5664 "#version 310 es\n"
5665 "precision mediump float;\n"
5666 "out vec4 my_FragColor;\n"
5667 "struct Data { mediump isampler2D data[2][2]; };\n"
5668 "uniform Data test;\n"
5669 "void main() {\n"
5670 " bool passed = true;\n"
5671 "#define DO_CHECK(i,j) \\\n"
5672 " if (texture(test.data[i][j], vec2(0.0, 0.0)) != ivec4(i + 1, j + 1, 0, 1)) { \\\n"
5673 " passed = false; \\\n"
5674 " }\n"
5675 " DO_CHECK(0, 0)\n"
5676 " DO_CHECK(0, 1)\n"
5677 " DO_CHECK(1, 0)\n"
5678 " DO_CHECK(1, 1)\n"
5679 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
5680 "}\n";
5681
5682 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5683 glUseProgram(program);
5684 GLTexture textures[2][2];
5685 for (int i = 0; i < 2; i++)
5686 {
5687 for (int j = 0; j < 2; j++)
5688 {
5689 // First generate the texture
5690 int textureUnit = i * 2 + j;
5691 glActiveTexture(GL_TEXTURE0 + textureUnit);
5692 glBindTexture(GL_TEXTURE_2D, textures[i][j]);
5693 GLint texData[2] = {i + 1, j + 1};
5694 glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32I, 1, 1, 0, GL_RG_INTEGER, GL_INT, &texData[0]);
5695 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5696 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5697 // Then send it as a uniform
5698 std::stringstream uniformName;
5699 uniformName << "test.data[" << i << "][" << j << "]";
5700 GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
5701 // All array indices should be used.
5702 EXPECT_NE(uniformLocation, -1);
5703 glUniform1i(uniformLocation, textureUnit);
5704 }
5705 }
5706 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
5707 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5708 }
5709
5710 // Test that an array of structs with arrays of arrays of samplers works.
TEST_P(GLSLTest_ES31,ArrayStructArrayArraySampler)5711 TEST_P(GLSLTest_ES31, ArrayStructArrayArraySampler)
5712 {
5713 GLint numTextures;
5714 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
5715 ANGLE_SKIP_TEST_IF(numTextures < 2 * (2 * 2 + 2 * 2));
5716 constexpr char kFS[] =
5717 "#version 310 es\n"
5718 "precision mediump float;\n"
5719 "out vec4 my_FragColor;\n"
5720 "struct Data { mediump isampler2D data0[2][2]; mediump isampler2D data1[2][2]; };\n"
5721 "uniform Data test[2];\n"
5722 "void main() {\n"
5723 " bool passed = true;\n"
5724 "#define DO_CHECK_ikl(i,k,l) \\\n"
5725 " if (texture(test[i].data0[k][l], vec2(0.0, 0.0)) != ivec4(i, 0, k, l)+1) { \\\n"
5726 " passed = false; \\\n"
5727 " } \\\n"
5728 " if (texture(test[i].data1[k][l], vec2(0.0, 0.0)) != ivec4(i, 1, k, l)+1) { \\\n"
5729 " passed = false; \\\n"
5730 " }\n"
5731 "#define DO_CHECK_ik(i,k) \\\n"
5732 " DO_CHECK_ikl(i, k, 0) \\\n"
5733 " DO_CHECK_ikl(i, k, 1)\n"
5734 "#define DO_CHECK_i(i) \\\n"
5735 " DO_CHECK_ik(i, 0) \\\n"
5736 " DO_CHECK_ik(i, 1)\n"
5737 " DO_CHECK_i(0)\n"
5738 " DO_CHECK_i(1)\n"
5739 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
5740 "}\n";
5741
5742 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5743 glUseProgram(program);
5744 GLTexture textures[2][2][2][2];
5745 for (int i = 0; i < 2; i++)
5746 {
5747 for (int j = 0; j < 2; j++)
5748 {
5749 for (int k = 0; k < 2; k++)
5750 {
5751 for (int l = 0; l < 2; l++)
5752 {
5753 // First generate the texture
5754 int textureUnit = l + 2 * (k + 2 * (j + 2 * i));
5755 glActiveTexture(GL_TEXTURE0 + textureUnit);
5756 glBindTexture(GL_TEXTURE_2D, textures[i][j][k][l]);
5757 GLint texData[4] = {i + 1, j + 1, k + 1, l + 1};
5758 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT,
5759 &texData[0]);
5760 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5761 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5762 // Then send it as a uniform
5763 std::stringstream uniformName;
5764 uniformName << "test[" << i << "].data" << j << "[" << k << "][" << l << "]";
5765 GLint uniformLocation =
5766 glGetUniformLocation(program, uniformName.str().c_str());
5767 // All array indices should be used.
5768 EXPECT_NE(uniformLocation, -1);
5769 glUniform1i(uniformLocation, textureUnit);
5770 }
5771 }
5772 }
5773 }
5774 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
5775 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5776 }
5777
5778 // Test that a complex chain of structs and arrays of samplers works as expected.
TEST_P(GLSLTest_ES31,ComplexStructArraySampler)5779 TEST_P(GLSLTest_ES31, ComplexStructArraySampler)
5780 {
5781 GLint numTextures;
5782 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
5783 ANGLE_SKIP_TEST_IF(numTextures < 2 * 3 * (2 + 3));
5784 constexpr char kFS[] =
5785 "#version 310 es\n"
5786 "precision mediump float;\n"
5787 "out vec4 my_FragColor;\n"
5788 "struct Data { mediump isampler2D data0[2]; mediump isampler2D data1[3]; };\n"
5789 "uniform Data test[2][3];\n"
5790 "const vec2 ZERO = vec2(0.0, 0.0);\n"
5791 "void main() {\n"
5792 " bool passed = true;\n"
5793 "#define DO_CHECK_INNER0(i,j,l) \\\n"
5794 " if (texture(test[i][j].data0[l], ZERO) != ivec4(i, j, 0, l) + 1) { \\\n"
5795 " passed = false; \\\n"
5796 " }\n"
5797 "#define DO_CHECK_INNER1(i,j,l) \\\n"
5798 " if (texture(test[i][j].data1[l], ZERO) != ivec4(i, j, 1, l) + 1) { \\\n"
5799 " passed = false; \\\n"
5800 " }\n"
5801 "#define DO_CHECK(i,j) \\\n"
5802 " DO_CHECK_INNER0(i, j, 0) \\\n"
5803 " DO_CHECK_INNER0(i, j, 1) \\\n"
5804 " DO_CHECK_INNER1(i, j, 0) \\\n"
5805 " DO_CHECK_INNER1(i, j, 1) \\\n"
5806 " DO_CHECK_INNER1(i, j, 2)\n"
5807 " DO_CHECK(0, 0)\n"
5808 " DO_CHECK(0, 1)\n"
5809 " DO_CHECK(0, 2)\n"
5810 " DO_CHECK(1, 0)\n"
5811 " DO_CHECK(1, 1)\n"
5812 " DO_CHECK(1, 2)\n"
5813 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
5814 "}\n";
5815
5816 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5817 glUseProgram(program);
5818 struct Data
5819 {
5820 GLTexture data1[2];
5821 GLTexture data2[3];
5822 };
5823 Data textures[2][3];
5824 for (int i = 0; i < 2; i++)
5825 {
5826 for (int j = 0; j < 3; j++)
5827 {
5828 GLTexture *arrays[] = {&textures[i][j].data1[0], &textures[i][j].data2[0]};
5829 size_t arrayLengths[] = {2, 3};
5830 size_t arrayOffsets[] = {0, 2};
5831 size_t totalArrayLength = 5;
5832 for (int k = 0; k < 2; k++)
5833 {
5834 GLTexture *array = arrays[k];
5835 size_t arrayLength = arrayLengths[k];
5836 size_t arrayOffset = arrayOffsets[k];
5837 for (int l = 0; l < static_cast<int>(arrayLength); l++)
5838 {
5839 // First generate the texture
5840 int textureUnit = arrayOffset + l + totalArrayLength * (j + 3 * i);
5841 glActiveTexture(GL_TEXTURE0 + textureUnit);
5842 glBindTexture(GL_TEXTURE_2D, array[l]);
5843 GLint texData[4] = {i + 1, j + 1, k + 1, l + 1};
5844 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT,
5845 &texData[0]);
5846 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5847 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5848 // Then send it as a uniform
5849 std::stringstream uniformName;
5850 uniformName << "test[" << i << "][" << j << "].data" << k << "[" << l << "]";
5851 GLint uniformLocation =
5852 glGetUniformLocation(program, uniformName.str().c_str());
5853 // All array indices should be used.
5854 EXPECT_NE(uniformLocation, -1);
5855 glUniform1i(uniformLocation, textureUnit);
5856 }
5857 }
5858 }
5859 }
5860 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
5861 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5862 }
5863
TEST_P(GLSLTest_ES31,ArraysOfArraysStructDifferentTypesSampler)5864 TEST_P(GLSLTest_ES31, ArraysOfArraysStructDifferentTypesSampler)
5865 {
5866 GLint numTextures;
5867 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
5868 ANGLE_SKIP_TEST_IF(numTextures < 3 * (2 + 2));
5869 constexpr char kFS[] =
5870 "#version 310 es\n"
5871 "precision mediump float;\n"
5872 "out vec4 my_FragColor;\n"
5873 "struct Data { mediump isampler2D data0[2]; mediump sampler2D data1[2]; };\n"
5874 "uniform Data test[3];\n"
5875 "ivec4 f2i(vec4 x) { return ivec4(x * 4.0 + 0.5); }"
5876 "void main() {\n"
5877 " bool passed = true;\n"
5878 "#define DO_CHECK_ik(i,k) \\\n"
5879 " if (texture(test[i].data0[k], vec2(0.0, 0.0)) != ivec4(i, 0, k, 0)+1) { \\\n"
5880 " passed = false; \\\n"
5881 " } \\\n"
5882 " if (f2i(texture(test[i].data1[k], vec2(0.0, 0.0))) != ivec4(i, 1, k, 0)+1) { \\\n"
5883 " passed = false; \\\n"
5884 " }\n"
5885 "#define DO_CHECK_i(i) \\\n"
5886 " DO_CHECK_ik(i, 0) \\\n"
5887 " DO_CHECK_ik(i, 1)\n"
5888 " DO_CHECK_i(0)\n"
5889 " DO_CHECK_i(1)\n"
5890 " DO_CHECK_i(2)\n"
5891 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
5892 "}\n";
5893
5894 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5895 glUseProgram(program);
5896 GLTexture textures[3][2][2];
5897 for (int i = 0; i < 3; i++)
5898 {
5899 for (int j = 0; j < 2; j++)
5900 {
5901 for (int k = 0; k < 2; k++)
5902 {
5903 // First generate the texture
5904 int textureUnit = k + 2 * (j + 2 * i);
5905 glActiveTexture(GL_TEXTURE0 + textureUnit);
5906 glBindTexture(GL_TEXTURE_2D, textures[i][j][k]);
5907 GLint texData[4] = {i + 1, j + 1, k + 1, 1};
5908 GLubyte texDataFloat[4] = {static_cast<GLubyte>((i + 1) * 64 - 1),
5909 static_cast<GLubyte>((j + 1) * 64 - 1),
5910 static_cast<GLubyte>((k + 1) * 64 - 1), 64};
5911 if (j == 0)
5912 {
5913 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT,
5914 &texData[0]);
5915 }
5916 else
5917 {
5918 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5919 &texDataFloat[0]);
5920 }
5921 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5922 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5923 // Then send it as a uniform
5924 std::stringstream uniformName;
5925 uniformName << "test[" << i << "].data" << j << "[" << k << "]";
5926 GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
5927 // All array indices should be used.
5928 EXPECT_NE(uniformLocation, -1);
5929 glUniform1i(uniformLocation, textureUnit);
5930 }
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 samplers as parameters works as expected.
TEST_P(GLSLTest_ES31,ParameterArraysOfArraysSampler)5938 TEST_P(GLSLTest_ES31, ParameterArraysOfArraysSampler)
5939 {
5940 // anglebug.com/42262476 - no sampler array params on Android
5941 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
5942
5943 constexpr char kFS[] =
5944 "#version 310 es\n"
5945 "precision mediump float;\n"
5946 "out vec4 my_FragColor;\n"
5947 "uniform mediump isampler2D test[2][3];\n"
5948 "const vec2 ZERO = vec2(0.0, 0.0);\n"
5949 "\n"
5950 "bool check(mediump isampler2D data[2][3]);\n"
5951 "bool check(mediump isampler2D data[2][3]) {\n"
5952 "#define DO_CHECK(i,j) \\\n"
5953 " if (texture(data[i][j], ZERO) != ivec4(i+1, j+1, 0, 1)) { \\\n"
5954 " return false; \\\n"
5955 " }\n"
5956 " DO_CHECK(0, 0)\n"
5957 " DO_CHECK(0, 1)\n"
5958 " DO_CHECK(0, 2)\n"
5959 " DO_CHECK(1, 0)\n"
5960 " DO_CHECK(1, 1)\n"
5961 " DO_CHECK(1, 2)\n"
5962 " return true;\n"
5963 "}\n"
5964 "void main() {\n"
5965 " bool passed = check(test);\n"
5966 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
5967 "}\n";
5968
5969 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5970 glUseProgram(program);
5971 GLTexture textures[2][3];
5972 for (int i = 0; i < 2; i++)
5973 {
5974 for (int j = 0; j < 3; j++)
5975 {
5976 // First generate the texture
5977 int textureUnit = i * 3 + j;
5978 glActiveTexture(GL_TEXTURE0 + textureUnit);
5979 glBindTexture(GL_TEXTURE_2D, textures[i][j]);
5980 GLint texData[2] = {i + 1, j + 1};
5981 glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32I, 1, 1, 0, GL_RG_INTEGER, GL_INT, &texData[0]);
5982 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5983 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5984 // Then send it as a uniform
5985 std::stringstream uniformName;
5986 uniformName << "test[" << i << "][" << j << "]";
5987 GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
5988 // All array indices should be used.
5989 EXPECT_NE(uniformLocation, -1);
5990 glUniform1i(uniformLocation, textureUnit);
5991 }
5992 }
5993 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
5994 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5995 }
5996
5997 // Test that structs with arrays of arrays of samplers as parameters works as expected.
TEST_P(GLSLTest_ES31,ParameterStructArrayArraySampler)5998 TEST_P(GLSLTest_ES31, ParameterStructArrayArraySampler)
5999 {
6000 // anglebug.com/42262476 - no sampler array params on Android
6001 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
6002
6003 constexpr char kFS[] =
6004 "#version 310 es\n"
6005 "precision mediump float;\n"
6006 "out vec4 my_FragColor;\n"
6007 "struct Data { mediump isampler2D data[2][3]; };\n"
6008 "uniform Data test;\n"
6009 "const vec2 ZERO = vec2(0.0, 0.0);\n"
6010 "\n"
6011 "bool check(Data data) {\n"
6012 "#define DO_CHECK(i,j) \\\n"
6013 " if (texture(data.data[i][j], ZERO) != ivec4(i+1, j+1, 0, 1)) { \\\n"
6014 " return false; \\\n"
6015 " }\n"
6016 " DO_CHECK(0, 0)\n"
6017 " DO_CHECK(0, 1)\n"
6018 " DO_CHECK(0, 2)\n"
6019 " DO_CHECK(1, 0)\n"
6020 " DO_CHECK(1, 1)\n"
6021 " DO_CHECK(1, 2)\n"
6022 " return true;\n"
6023 "}\n"
6024 "void main() {\n"
6025 " bool passed = check(test);\n"
6026 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
6027 "}\n";
6028
6029 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
6030 glUseProgram(program);
6031 GLTexture textures[2][3];
6032 for (int i = 0; i < 2; i++)
6033 {
6034 for (int j = 0; j < 3; j++)
6035 {
6036 // First generate the texture
6037 int textureUnit = i * 3 + j;
6038 glActiveTexture(GL_TEXTURE0 + textureUnit);
6039 glBindTexture(GL_TEXTURE_2D, textures[i][j]);
6040 GLint texData[2] = {i + 1, j + 1};
6041 glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32I, 1, 1, 0, GL_RG_INTEGER, GL_INT, &texData[0]);
6042 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6043 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6044 // Then send it as a uniform
6045 std::stringstream uniformName;
6046 uniformName << "test.data[" << i << "][" << j << "]";
6047 GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
6048 // All array indices should be used.
6049 EXPECT_NE(uniformLocation, -1);
6050 glUniform1i(uniformLocation, textureUnit);
6051 }
6052 }
6053 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
6054 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6055 }
6056
6057 // Test that arrays of arrays of structs with arrays of arrays of samplers
6058 // as parameters works as expected.
TEST_P(GLSLTest_ES31,ParameterArrayArrayStructArrayArraySampler)6059 TEST_P(GLSLTest_ES31, ParameterArrayArrayStructArrayArraySampler)
6060 {
6061 // anglebug.com/42262476 - no sampler array params on Android
6062 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
6063
6064 GLint numTextures;
6065 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
6066 ANGLE_SKIP_TEST_IF(numTextures < 3 * 2 * 2 * 2);
6067 constexpr char kFS[] =
6068 "#version 310 es\n"
6069 "precision mediump float;\n"
6070 "out vec4 my_FragColor;\n"
6071 "struct Data { mediump isampler2D data[2][2]; };\n"
6072 "uniform Data test[3][2];\n"
6073 "const vec2 ZERO = vec2(0.0, 0.0);\n"
6074 "\n"
6075 "bool check(Data data[3][2]) {\n"
6076 "#define DO_CHECK_ijkl(i,j,k,l) \\\n"
6077 " if (texture(data[i][j].data[k][l], ZERO) != ivec4(i, j, k, l) + 1) { \\\n"
6078 " return false; \\\n"
6079 " }\n"
6080 "#define DO_CHECK_ij(i,j) \\\n"
6081 " DO_CHECK_ijkl(i, j, 0, 0) \\\n"
6082 " DO_CHECK_ijkl(i, j, 0, 1) \\\n"
6083 " DO_CHECK_ijkl(i, j, 1, 0) \\\n"
6084 " DO_CHECK_ijkl(i, j, 1, 1)\n"
6085 " DO_CHECK_ij(0, 0)\n"
6086 " DO_CHECK_ij(1, 0)\n"
6087 " DO_CHECK_ij(2, 0)\n"
6088 " DO_CHECK_ij(0, 1)\n"
6089 " DO_CHECK_ij(1, 1)\n"
6090 " DO_CHECK_ij(2, 1)\n"
6091 " return true;\n"
6092 "}\n"
6093 "void main() {\n"
6094 " bool passed = check(test);\n"
6095 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
6096 "}\n";
6097
6098 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
6099 glUseProgram(program);
6100 GLTexture textures[3][2][2][2];
6101 for (int i = 0; i < 3; i++)
6102 {
6103 for (int j = 0; j < 2; j++)
6104 {
6105 for (int k = 0; k < 2; k++)
6106 {
6107 for (int l = 0; l < 2; l++)
6108 {
6109 // First generate the texture
6110 int textureUnit = l + 2 * (k + 2 * (j + 2 * i));
6111 glActiveTexture(GL_TEXTURE0 + textureUnit);
6112 glBindTexture(GL_TEXTURE_2D, textures[i][j][k][l]);
6113 GLint texData[4] = {i + 1, j + 1, k + 1, l + 1};
6114 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT,
6115 &texData[0]);
6116 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6117 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6118 // Then send it as a uniform
6119 std::stringstream uniformName;
6120 uniformName << "test[" << i << "][" << j << "].data[" << k << "][" << l << "]";
6121 GLint uniformLocation =
6122 glGetUniformLocation(program, uniformName.str().c_str());
6123 // All array indices should be used.
6124 EXPECT_NE(uniformLocation, -1);
6125 glUniform1i(uniformLocation, textureUnit);
6126 }
6127 }
6128 }
6129 }
6130 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
6131 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6132 }
6133
6134 // Test that 3D arrays with sub-arrays passed as parameters works as expected.
TEST_P(GLSLTest_ES31,ParameterArrayArrayArraySampler)6135 TEST_P(GLSLTest_ES31, ParameterArrayArrayArraySampler)
6136 {
6137 GLint numTextures;
6138 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
6139 ANGLE_SKIP_TEST_IF(numTextures < 2 * 3 * 4 + 4);
6140
6141 // anglebug.com/42262476 - no sampler array params on Android
6142 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
6143
6144 // http://anglebug.com/42264082
6145 ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
6146
6147 constexpr char kFS[] =
6148 "#version 310 es\n"
6149 "precision mediump float;\n"
6150 "out vec4 my_FragColor;\n"
6151 "uniform mediump isampler2D test[2][3][4];\n"
6152 "uniform mediump isampler2D test2[4];\n"
6153 "const vec2 ZERO = vec2(0.0, 0.0);\n"
6154 "\n"
6155 "bool check1D(mediump isampler2D arr[4], int x, int y) {\n"
6156 " if (texture(arr[0], ZERO) != ivec4(x, y, 0, 0)+1) return false;\n"
6157 " if (texture(arr[1], ZERO) != ivec4(x, y, 1, 0)+1) return false;\n"
6158 " if (texture(arr[2], ZERO) != ivec4(x, y, 2, 0)+1) return false;\n"
6159 " if (texture(arr[3], ZERO) != ivec4(x, y, 3, 0)+1) return false;\n"
6160 " return true;\n"
6161 "}\n"
6162 "bool check2D(mediump isampler2D arr[3][4], int x) {\n"
6163 " if (!check1D(arr[0], x, 0)) return false;\n"
6164 " if (!check1D(arr[1], x, 1)) return false;\n"
6165 " if (!check1D(arr[2], x, 2)) return false;\n"
6166 " return true;\n"
6167 "}\n"
6168 "bool check3D(mediump isampler2D arr[2][3][4]) {\n"
6169 " if (!check2D(arr[0], 0)) return false;\n"
6170 " if (!check2D(arr[1], 1)) return false;\n"
6171 " return true;\n"
6172 "}\n"
6173 "void main() {\n"
6174 " bool passed = check3D(test) && check1D(test2, 7, 8);\n"
6175 " my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
6176 "}\n";
6177
6178 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
6179 glUseProgram(program);
6180 GLTexture textures1[2][3][4];
6181 GLTexture textures2[4];
6182 for (int i = 0; i < 2; i++)
6183 {
6184 for (int j = 0; j < 3; j++)
6185 {
6186 for (int k = 0; k < 4; k++)
6187 {
6188 // First generate the texture
6189 int textureUnit = k + 4 * (j + 3 * i);
6190 glActiveTexture(GL_TEXTURE0 + textureUnit);
6191 glBindTexture(GL_TEXTURE_2D, textures1[i][j][k]);
6192 GLint texData[3] = {i + 1, j + 1, k + 1};
6193 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32I, 1, 1, 0, GL_RGB_INTEGER, GL_INT,
6194 &texData[0]);
6195 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6196 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6197 // Then send it as a uniform
6198 std::stringstream uniformName;
6199 uniformName << "test[" << i << "][" << j << "][" << k << "]";
6200 GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
6201 // All array indices should be used.
6202 EXPECT_NE(uniformLocation, -1);
6203 glUniform1i(uniformLocation, textureUnit);
6204 }
6205 }
6206 }
6207 for (int k = 0; k < 4; k++)
6208 {
6209 // First generate the texture
6210 int textureUnit = 2 * 3 * 4 + k;
6211 glActiveTexture(GL_TEXTURE0 + textureUnit);
6212 glBindTexture(GL_TEXTURE_2D, textures2[k]);
6213 GLint texData[3] = {7 + 1, 8 + 1, k + 1};
6214 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32I, 1, 1, 0, GL_RGB_INTEGER, GL_INT, &texData[0]);
6215 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6216 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6217 // Then send it as a uniform
6218 std::stringstream uniformName;
6219 uniformName << "test2[" << k << "]";
6220 GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
6221 // All array indices should be used.
6222 EXPECT_NE(uniformLocation, -1);
6223 glUniform1i(uniformLocation, textureUnit);
6224 }
6225 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
6226 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6227 }
6228
6229 // Test that names do not collide when translating arrays of arrays of samplers.
TEST_P(GLSLTest_ES31,ArraysOfArraysNameCollisionSampler)6230 TEST_P(GLSLTest_ES31, ArraysOfArraysNameCollisionSampler)
6231 {
6232 ANGLE_SKIP_TEST_IF(IsVulkan()); // anglebug.com/42262269 - rewriter can create name collisions
6233 GLint numTextures;
6234 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
6235 ANGLE_SKIP_TEST_IF(numTextures < 2 * 2 + 3 * 3 + 4 * 4);
6236 // anglebug.com/42262476 - no sampler array params on Android
6237 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
6238 constexpr char kFS[] =
6239 "#version 310 es\n"
6240 "precision mediump sampler2D;\n"
6241 "precision mediump float;\n"
6242 "uniform sampler2D test_field1_field2[2][2];\n"
6243 "struct S1 { sampler2D field2[3][3]; }; uniform S1 test_field1;\n"
6244 "struct S2 { sampler2D field1_field2[4][4]; }; uniform S2 test;\n"
6245 "vec4 func1(sampler2D param_field1_field2[2][2],\n"
6246 " int param_field1_field2_offset,\n"
6247 " S1 param_field1,\n"
6248 " S2 param) {\n"
6249 " return vec4(0.0, 1.0, 0.0, 0.0);\n"
6250 "}\n"
6251 "out vec4 my_FragColor;\n"
6252 "void main() {\n"
6253 " my_FragColor = vec4(0.0, 0.0, 0.0, 1.0);\n"
6254 " my_FragColor += func1(test_field1_field2, 0, test_field1, test);\n"
6255 " vec2 uv = vec2(0.0);\n"
6256 " my_FragColor += texture(test_field1_field2[0][0], uv) +\n"
6257 " texture(test_field1.field2[0][0], uv) +\n"
6258 " texture(test.field1_field2[0][0], uv);\n"
6259 "}\n";
6260 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
6261 glActiveTexture(GL_TEXTURE0);
6262 GLTexture tex;
6263 glBindTexture(GL_TEXTURE_2D, tex);
6264 GLint zero = 0;
6265 glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 1, 1, 0, GL_RED, GL_UNSIGNED_BYTE, &zero);
6266 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
6267 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6268 }
6269
6270 // Test that regular arrays are unmodified.
TEST_P(GLSLTest_ES31,BasicTypeArrayAndArrayOfSampler)6271 TEST_P(GLSLTest_ES31, BasicTypeArrayAndArrayOfSampler)
6272 {
6273 constexpr char kFS[] =
6274 "#version 310 es\n"
6275 "precision mediump sampler2D;\n"
6276 "precision mediump float;\n"
6277 "uniform sampler2D sampler_array[2][2];\n"
6278 "uniform int array[3][2];\n"
6279 "vec4 func1(int param[2],\n"
6280 " int param2[3]) {\n"
6281 " return vec4(0.0, 1.0, 0.0, 0.0);\n"
6282 "}\n"
6283 "out vec4 my_FragColor;\n"
6284 "void main() {\n"
6285 " my_FragColor = texture(sampler_array[0][0], vec2(0.0));\n"
6286 " my_FragColor += func1(array[1], int[](1, 2, 3));\n"
6287 "}\n";
6288 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
6289 glActiveTexture(GL_TEXTURE0);
6290 GLTexture tex;
6291 glBindTexture(GL_TEXTURE_2D, tex);
6292 GLint zero = 0;
6293 glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 1, 1, 0, GL_RED, GL_UNSIGNED_BYTE, &zero);
6294 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
6295 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6296 }
6297
6298 // This test covers a bug (and associated workaround) with nested sampling operations in the HLSL
6299 // compiler DLL.
TEST_P(GLSLTest_ES3,NestedSamplingOperation)6300 TEST_P(GLSLTest_ES3, NestedSamplingOperation)
6301 {
6302 // This seems to be bugged on some version of Android. Might not affect the newest versions.
6303 // TODO(jmadill): Lift suppression when Chromium bots are upgraded.
6304 // Test skipped on Android because of bug with Nexus 5X.
6305 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
6306
6307 constexpr char kVS[] =
6308 "#version 300 es\n"
6309 "out vec2 texCoord;\n"
6310 "in vec2 position;\n"
6311 "void main()\n"
6312 "{\n"
6313 " gl_Position = vec4(position, 0, 1);\n"
6314 " texCoord = position * 0.5 + vec2(0.5);\n"
6315 "}\n";
6316
6317 constexpr char kSimpleFS[] =
6318 "#version 300 es\n"
6319 "in mediump vec2 texCoord;\n"
6320 "out mediump vec4 fragColor;\n"
6321 "void main()\n"
6322 "{\n"
6323 " fragColor = vec4(texCoord, 0, 1);\n"
6324 "}\n";
6325
6326 constexpr char kNestedFS[] =
6327 "#version 300 es\n"
6328 "uniform mediump sampler2D samplerA;\n"
6329 "uniform mediump sampler2D samplerB;\n"
6330 "in mediump vec2 texCoord;\n"
6331 "out mediump vec4 fragColor;\n"
6332 "void main ()\n"
6333 "{\n"
6334 " fragColor = texture(samplerB, texture(samplerA, texCoord).xy);\n"
6335 "}\n";
6336
6337 ANGLE_GL_PROGRAM(initProg, kVS, kSimpleFS);
6338 ANGLE_GL_PROGRAM(nestedProg, kVS, kNestedFS);
6339
6340 // Initialize a first texture with default texCoord data.
6341 GLTexture texA;
6342 glActiveTexture(GL_TEXTURE0);
6343 glBindTexture(GL_TEXTURE_2D, texA);
6344 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
6345 GL_UNSIGNED_BYTE, nullptr);
6346 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6347 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6348
6349 GLFramebuffer fbo;
6350 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6351 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texA, 0);
6352
6353 drawQuad(initProg, "position", 0.5f);
6354 ASSERT_GL_NO_ERROR();
6355
6356 // Initialize a second texture with a simple color pattern.
6357 GLTexture texB;
6358 glActiveTexture(GL_TEXTURE1);
6359 glBindTexture(GL_TEXTURE_2D, texB);
6360
6361 std::array<GLColor, 4> simpleColors = {
6362 {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
6363 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6364 simpleColors.data());
6365 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6366 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6367
6368 // Draw with the nested program, using the first texture to index the second.
6369 glBindFramebuffer(GL_FRAMEBUFFER, 0);
6370 glUseProgram(nestedProg);
6371 GLint samplerALoc = glGetUniformLocation(nestedProg, "samplerA");
6372 ASSERT_NE(-1, samplerALoc);
6373 glUniform1i(samplerALoc, 0);
6374 GLint samplerBLoc = glGetUniformLocation(nestedProg, "samplerB");
6375 ASSERT_NE(-1, samplerBLoc);
6376 glUniform1i(samplerBLoc, 1);
6377
6378 drawQuad(nestedProg, "position", 0.5f);
6379 ASSERT_GL_NO_ERROR();
6380
6381 // Compute four texel centers.
6382 Vector2 windowSize(getWindowWidth(), getWindowHeight());
6383 Vector2 quarterWindowSize = windowSize / 4;
6384 Vector2 ul = quarterWindowSize;
6385 Vector2 ur(windowSize.x() - quarterWindowSize.x(), quarterWindowSize.y());
6386 Vector2 ll(quarterWindowSize.x(), windowSize.y() - quarterWindowSize.y());
6387 Vector2 lr = windowSize - quarterWindowSize;
6388
6389 EXPECT_PIXEL_COLOR_EQ_VEC2(ul, simpleColors[0]);
6390 EXPECT_PIXEL_COLOR_EQ_VEC2(ur, simpleColors[1]);
6391 EXPECT_PIXEL_COLOR_EQ_VEC2(ll, simpleColors[2]);
6392 EXPECT_PIXEL_COLOR_EQ_VEC2(lr, simpleColors[3]);
6393 }
6394
6395 // Tests that using a constant declaration as the only statement in a for loop without curly braces
6396 // doesn't crash.
TEST_P(GLSLTest,ConstantStatementInForLoop)6397 TEST_P(GLSLTest, ConstantStatementInForLoop)
6398 {
6399 constexpr char kVS[] =
6400 "void main()\n"
6401 "{\n"
6402 " for (int i = 0; i < 10; ++i)\n"
6403 " const int b = 0;\n"
6404 "}\n";
6405
6406 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
6407 EXPECT_NE(0u, shader);
6408 glDeleteShader(shader);
6409 }
6410
6411 // Tests that using a constant declaration as a loop init expression doesn't crash. Note that this
6412 // test doesn't work on D3D9 due to looping limitations, so it is only run on ES3.
TEST_P(GLSLTest_ES3,ConstantStatementAsLoopInit)6413 TEST_P(GLSLTest_ES3, ConstantStatementAsLoopInit)
6414 {
6415 constexpr char kVS[] =
6416 "void main()\n"
6417 "{\n"
6418 " for (const int i = 0; i < 0;) {}\n"
6419 "}\n";
6420
6421 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
6422 EXPECT_NE(0u, shader);
6423 glDeleteShader(shader);
6424 }
6425
6426 // Tests that using a constant condition guarding a discard works
6427 // Covers a failing case in the Vulkan backend: http://anglebug.com/42265506
TEST_P(GLSLTest_ES3,ConstantConditionGuardingDiscard)6428 TEST_P(GLSLTest_ES3, ConstantConditionGuardingDiscard)
6429 {
6430 constexpr char kFS[] = R"(#version 300 es
6431 void main()
6432 {
6433 if (true)
6434 {
6435 discard;
6436 }
6437 })";
6438
6439 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
6440 EXPECT_NE(0u, shader);
6441 glDeleteShader(shader);
6442 }
6443
6444 // Tests that nesting a discard in unconditional blocks works
6445 // Covers a failing case in the Vulkan backend: http://anglebug.com/42265506
TEST_P(GLSLTest_ES3,NestedUnconditionalDiscards)6446 TEST_P(GLSLTest_ES3, NestedUnconditionalDiscards)
6447 {
6448 constexpr char kFS[] = R"(#version 300 es
6449 out mediump vec4 c;
6450 void main()
6451 {
6452 {
6453 c = vec4(0);
6454 {
6455 discard;
6456 }
6457 }
6458 })";
6459
6460 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
6461 EXPECT_NE(0u, shader);
6462 glDeleteShader(shader);
6463 }
6464
6465 // Test that uninitialized local variables are initialized to 0.
TEST_P(WebGL2GLSLTest,InitUninitializedLocals)6466 TEST_P(WebGL2GLSLTest, InitUninitializedLocals)
6467 {
6468 // Test skipped on Android GLES because local variable initialization is disabled.
6469 // http://anglebug.com/40096454
6470 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
6471
6472 constexpr char kFS[] =
6473 "#version 300 es\n"
6474 "precision mediump float;\n"
6475 "out vec4 my_FragColor;\n"
6476 "int result = 0;\n"
6477 "void main()\n"
6478 "{\n"
6479 " int u;\n"
6480 " result += u;\n"
6481 " int k = 0;\n"
6482 " for (int i[2], j = i[0] + 1; k < 2; ++k)\n"
6483 " {\n"
6484 " result += j;\n"
6485 " }\n"
6486 " if (result == 2)\n"
6487 " {\n"
6488 " my_FragColor = vec4(0, 1, 0, 1);\n"
6489 " }\n"
6490 " else\n"
6491 " {\n"
6492 " my_FragColor = vec4(1, 0, 0, 1);\n"
6493 " }\n"
6494 "}\n";
6495
6496 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6497
6498 // [WebGL 1.0]
6499 // DrawArrays or drawElements will generate an INVALID_OPERATION error
6500 // if a vertex attribute is enabled as an array via enableVertexAttribArray
6501 // but no buffer is bound to that attribute.
6502 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6503 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6504 }
6505
6506 // Test that uninitialized structs containing arrays of structs are initialized to 0. This
6507 // specifically tests with two different struct variables declared in the same block.
TEST_P(WebGL2GLSLTest,InitUninitializedStructContainingArrays)6508 TEST_P(WebGL2GLSLTest, InitUninitializedStructContainingArrays)
6509 {
6510 // Test skipped on Android GLES because local variable initialization is disabled.
6511 // http://anglebug.com/40096454
6512 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
6513
6514 constexpr char kFS[] =
6515 "precision mediump float;\n"
6516 "struct T\n"
6517 "{\n"
6518 " int a[2];\n"
6519 "};\n"
6520 "struct S\n"
6521 "{\n"
6522 " T t[2];\n"
6523 "};\n"
6524 "void main()\n"
6525 "{\n"
6526 " S s;\n"
6527 " S s2;\n"
6528 " if (s.t[1].a[1] == 0 && s2.t[1].a[1] == 0)\n"
6529 " {\n"
6530 " gl_FragColor = vec4(0, 1, 0, 1);\n"
6531 " }\n"
6532 " else\n"
6533 " {\n"
6534 " gl_FragColor = vec4(1, 0, 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 // Verify that two shaders with the same uniform name and members but different structure names will
6544 // not link.
TEST_P(GLSLTest,StructureNameMatchingTest)6545 TEST_P(GLSLTest, StructureNameMatchingTest)
6546 {
6547 const char *vsSource =
6548 "// Structures must have the same name, sequence of type names, and\n"
6549 "// type definitions, and field names to be considered the same type.\n"
6550 "// GLSL 1.017 4.2.4\n"
6551 "precision mediump float;\n"
6552 "struct info {\n"
6553 " vec4 pos;\n"
6554 " vec4 color;\n"
6555 "};\n"
6556 "\n"
6557 "uniform info uni;\n"
6558 "void main()\n"
6559 "{\n"
6560 " gl_Position = uni.pos;\n"
6561 "}\n";
6562
6563 GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
6564 ASSERT_NE(0u, vs);
6565 glDeleteShader(vs);
6566
6567 const char *fsSource =
6568 "// Structures must have the same name, sequence of type names, and\n"
6569 "// type definitions, and field names to be considered the same type.\n"
6570 "// GLSL 1.017 4.2.4\n"
6571 "precision mediump float;\n"
6572 "struct info1 {\n"
6573 " vec4 pos;\n"
6574 " vec4 color;\n"
6575 "};\n"
6576 "\n"
6577 "uniform info1 uni;\n"
6578 "void main()\n"
6579 "{\n"
6580 " gl_FragColor = uni.color;\n"
6581 "}\n";
6582
6583 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
6584 ASSERT_NE(0u, fs);
6585 glDeleteShader(fs);
6586
6587 GLuint program = CompileProgram(vsSource, fsSource);
6588 EXPECT_EQ(0u, program);
6589 }
6590
6591 // Test that an uninitialized nameless struct inside a for loop init statement works.
TEST_P(WebGL2GLSLTest,UninitializedNamelessStructInForInitStatement)6592 TEST_P(WebGL2GLSLTest, UninitializedNamelessStructInForInitStatement)
6593 {
6594 // Test skipped on Android GLES because local variable initialization is disabled.
6595 // http://anglebug.com/40096454
6596 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
6597
6598 constexpr char kFS[] =
6599 "#version 300 es\n"
6600 "precision highp float;\n"
6601 "out vec4 my_FragColor;\n"
6602 "void main()\n"
6603 "{\n"
6604 " my_FragColor = vec4(1, 0, 0, 1);\n"
6605 " for (struct { float q; } b; b.q < 2.0; b.q++) {\n"
6606 " my_FragColor = vec4(0, 1, 0, 1);\n"
6607 " }\n"
6608 "}\n";
6609
6610 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6611 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6612 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6613 }
6614
6615 // Test that uninitialized global variables are initialized to 0.
TEST_P(WebGLGLSLTest,InitUninitializedGlobals)6616 TEST_P(WebGLGLSLTest, InitUninitializedGlobals)
6617 {
6618 // http://anglebug.com/42261561
6619 ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
6620
6621 constexpr char kFS[] =
6622 "precision mediump float;\n"
6623 "int result;\n"
6624 "int i[2], j = i[0] + 1;\n"
6625 "void main()\n"
6626 "{\n"
6627 " result += j;\n"
6628 " if (result == 1)\n"
6629 " {\n"
6630 " gl_FragColor = vec4(0, 1, 0, 1);\n"
6631 " }\n"
6632 " else\n"
6633 " {\n"
6634 " gl_FragColor = vec4(1, 0, 0, 1);\n"
6635 " }\n"
6636 "}\n";
6637
6638 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
6639 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6640 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6641 }
6642
6643 // Test that an uninitialized nameless struct in the global scope works.
TEST_P(WebGLGLSLTest,UninitializedNamelessStructInGlobalScope)6644 TEST_P(WebGLGLSLTest, UninitializedNamelessStructInGlobalScope)
6645 {
6646 constexpr char kFS[] =
6647 "precision mediump float;\n"
6648 "struct { float q; } b;\n"
6649 "void main()\n"
6650 "{\n"
6651 " gl_FragColor = vec4(1, 0, 0, 1);\n"
6652 " if (b.q == 0.0)\n"
6653 " {\n"
6654 " gl_FragColor = vec4(0, 1, 0, 1);\n"
6655 " }\n"
6656 "}\n";
6657
6658 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
6659 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6660 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6661 }
6662
6663 // Test that uninitialized output arguments are initialized to 0.
TEST_P(WebGL2GLSLTest,InitOutputParams)6664 TEST_P(WebGL2GLSLTest, InitOutputParams)
6665 {
6666 constexpr char kFS[] = R"(#version 300 es
6667 precision mediump float;
6668
6669 struct S { float a; };
6670
6671 out vec4 color;
6672
6673 float f(out float, out vec2 o1, out S o2[2], out float o3[3])
6674 {
6675 float uninitialized_local;
6676
6677 // leave o1 uninitialized
6678 // leave o2 partially uninitialized
6679 o2[0].a = 1.0;
6680
6681 // leave o3 partially uninitialized
6682 o3[1] = 0.5;
6683
6684 return uninitialized_local;
6685 }
6686
6687 void main()
6688 {
6689 float v0 = 345.;
6690 vec2 v1 = vec2(123., 234.);
6691 S v2[2] = S[2](S(-1111.), S(55.));
6692 float v3[3] = float[3](20., 30., 40.);
6693 float v4 = f(v0, v1, v2, v3);
6694
6695 // Everything should be 0 now except for v2[0].a and v3[1] which should be 1.0 and 0.5
6696 // respectively.
6697 color = vec4(v0 + v1.x + v2[0].a + v3[0], // 1.0
6698 v1.y + v2[1].a + v3[1], // 0.5
6699 v3[2] + v4, // 0
6700 1.0);
6701 })";
6702
6703 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6704 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6705 EXPECT_PIXEL_NEAR(0, 0, 255, 127, 0, 255, 1);
6706 }
6707
6708 // Tests nameless struct uniforms.
TEST_P(GLSLTest,EmbeddedStructUniform)6709 TEST_P(GLSLTest, EmbeddedStructUniform)
6710 {
6711 const char kFragmentShader[] = R"(precision mediump float;
6712 uniform struct { float q; } b;
6713 void main()
6714 {
6715 gl_FragColor = vec4(1, 0, 0, 1);
6716 if (b.q == 0.5)
6717 {
6718 gl_FragColor = vec4(0, 1, 0, 1);
6719 }
6720 })";
6721
6722 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
6723 glUseProgram(program);
6724 GLint uniLoc = glGetUniformLocation(program, "b.q");
6725 ASSERT_NE(-1, uniLoc);
6726 glUniform1f(uniLoc, 0.5f);
6727
6728 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6729 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6730 }
6731
6732 // Tests nameless struct uniform arrays.
TEST_P(GLSLTest,EmbeddedStructUniformArray)6733 TEST_P(GLSLTest, EmbeddedStructUniformArray)
6734 {
6735 const char kFragmentShader[] = R"(precision mediump float;
6736 uniform struct { float q; } b[2];
6737 void main()
6738 {
6739 gl_FragColor = vec4(1, 0, 0, 1);
6740 if (b[0].q == 0.5)
6741 {
6742 gl_FragColor = vec4(0, 1, 0, 1);
6743 }
6744 })";
6745
6746 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
6747 glUseProgram(program);
6748 GLint uniLoc = glGetUniformLocation(program, "b[0].q");
6749 ASSERT_NE(-1, uniLoc);
6750 glUniform1f(uniLoc, 0.5f);
6751
6752 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6753 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6754 }
6755
6756 // Test that samplers in structs can be extracted if the first reference to the struct does not
6757 // select an attribute.
TEST_P(GLSLTest,SamplerInStructNoMemberIndexing)6758 TEST_P(GLSLTest, SamplerInStructNoMemberIndexing)
6759 {
6760 constexpr char kVS[] = R"(
6761 uniform struct {
6762 sampler2D n;
6763 vec2 c;
6764 } s;
6765 void main()
6766 {
6767 s;
6768 })";
6769
6770 constexpr char kFS[] = R"(void main()
6771 {
6772 gl_FragColor = vec4(1);
6773 })";
6774
6775 ANGLE_GL_PROGRAM(program, kVS, kFS);
6776 }
6777
6778 // Similar test to SamplerInStructNoMemberIndexing, but the struct variable is an array.
TEST_P(GLSLTest,SamplerInStructArrayNoMemberIndexing)6779 TEST_P(GLSLTest, SamplerInStructArrayNoMemberIndexing)
6780 {
6781 constexpr char kVS[] = R"(
6782 uniform struct
6783 {
6784 sampler2D K;
6785 vec4 c;
6786 } s[6];
6787 void main()
6788 {
6789 s[0];
6790 })";
6791
6792 constexpr char kFS[] = R"(void main()
6793 {
6794 gl_FragColor = vec4(1);
6795 })";
6796
6797 ANGLE_GL_PROGRAM(program, kVS, kFS);
6798 }
6799
6800 // Tests that rewriting samplers in structs doesn't mess up indexing.
TEST_P(GLSLTest,SamplerInStructMemberIndexing)6801 TEST_P(GLSLTest, SamplerInStructMemberIndexing)
6802 {
6803 const char kVertexShader[] = R"(attribute vec2 position;
6804 varying vec2 texCoord;
6805 void main()
6806 {
6807 gl_Position = vec4(position, 0, 1);
6808 texCoord = position * 0.5 + vec2(0.5);
6809 })";
6810
6811 const char kFragmentShader[] = R"(precision mediump float;
6812 struct S { sampler2D samp; bool b; };
6813 uniform S uni;
6814 varying vec2 texCoord;
6815 void main()
6816 {
6817 uni;
6818 if (uni.b)
6819 {
6820 gl_FragColor = texture2D(uni.samp, texCoord);
6821 }
6822 else
6823 {
6824 gl_FragColor = vec4(1, 0, 0, 1);
6825 }
6826 })";
6827
6828 ANGLE_GL_PROGRAM(program, kVertexShader, kFragmentShader);
6829 glUseProgram(program);
6830
6831 GLint bLoc = glGetUniformLocation(program, "uni.b");
6832 ASSERT_NE(-1, bLoc);
6833 GLint sampLoc = glGetUniformLocation(program, "uni.samp");
6834 ASSERT_NE(-1, sampLoc);
6835
6836 glUniform1i(bLoc, 1);
6837
6838 std::array<GLColor, 4> kGreenPixels = {
6839 {GLColor::green, GLColor::green, GLColor::green, GLColor::green}};
6840
6841 GLTexture tex;
6842 glBindTexture(GL_TEXTURE_2D, tex);
6843 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6844 kGreenPixels.data());
6845 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6846 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6847 ASSERT_GL_NO_ERROR();
6848
6849 drawQuad(program, "position", 0.5f);
6850 ASSERT_GL_NO_ERROR();
6851
6852 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6853 }
6854
6855 // Tests that rewriting samplers in structs works when passed as function argument. In this test,
6856 // the function references another struct, which is not being modified. Regression test for AST
6857 // validation applied to a multipass transformation, where references to declarations were attempted
6858 // to be validated without having the entire shader. In this case, the reference to S2 was flagged
6859 // as invalid because S2's declaration was not visible.
TEST_P(GLSLTest,SamplerInStructAsFunctionArg)6860 TEST_P(GLSLTest, SamplerInStructAsFunctionArg)
6861 {
6862 const char kFS[] = R"(precision mediump float;
6863 struct S { sampler2D samp; bool b; };
6864 struct S2 { float f; };
6865
6866 uniform S us;
6867
6868 float f(S s)
6869 {
6870 S2 s2;
6871 s2.f = float(s.b);
6872 return s2.f;
6873 }
6874
6875 void main()
6876 {
6877 gl_FragColor = vec4(f(us), 0, 0, 1);
6878 })";
6879
6880 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
6881 EXPECT_NE(fs, 0u);
6882 ASSERT_GL_NO_ERROR();
6883 }
6884
6885 // Test that structs with samplers are not allowed in interface blocks. This is forbidden per
6886 // GLES3:
6887 //
6888 // > Types and declarators are the same as for other uniform variable declarations outside blocks,
6889 // > with these exceptions:
6890 // > * opaque types are not allowed
TEST_P(GLSLTest_ES3,StructWithSamplersDisallowedInInterfaceBlock)6891 TEST_P(GLSLTest_ES3, StructWithSamplersDisallowedInInterfaceBlock)
6892 {
6893 const char kFS[] = R"(#version 300 es
6894 precision mediump float;
6895 struct S { sampler2D samp; bool b; };
6896
6897 layout(std140) uniform Buffer { S s; } buffer;
6898
6899 out vec4 color;
6900
6901 void main()
6902 {
6903 color = texture(buffer.s.samp, vec2(0));
6904 })";
6905
6906 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
6907 EXPECT_EQ(fs, 0u);
6908 ASSERT_GL_NO_ERROR();
6909 }
6910
6911 // Tests two nameless struct uniforms.
TEST_P(GLSLTest,TwoEmbeddedStructUniforms)6912 TEST_P(GLSLTest, TwoEmbeddedStructUniforms)
6913 {
6914 const char kFragmentShader[] = R"(precision mediump float;
6915 uniform struct { float q; } b, c;
6916 void main()
6917 {
6918 gl_FragColor = vec4(1, 0, 0, 1);
6919 if (b.q == 0.5 && c.q == 1.0)
6920 {
6921 gl_FragColor = vec4(0, 1, 0, 1);
6922 }
6923 })";
6924
6925 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
6926 glUseProgram(program);
6927
6928 GLint uniLocB = glGetUniformLocation(program, "b.q");
6929 ASSERT_NE(-1, uniLocB);
6930 glUniform1f(uniLocB, 0.5f);
6931
6932 GLint uniLocC = glGetUniformLocation(program, "c.q");
6933 ASSERT_NE(-1, uniLocC);
6934 glUniform1f(uniLocC, 1.0f);
6935
6936 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6937 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6938 }
6939
6940 // Test that a loop condition that has an initializer declares a variable.
TEST_P(GLSLTest_ES3,ConditionInitializerDeclaresVariable)6941 TEST_P(GLSLTest_ES3, ConditionInitializerDeclaresVariable)
6942 {
6943 constexpr char kFS[] =
6944 "#version 300 es\n"
6945 "precision highp float;\n"
6946 "out vec4 my_FragColor;\n"
6947 "void main()\n"
6948 "{\n"
6949 " float i = 0.0;\n"
6950 " while (bool foo = (i < 1.5))\n"
6951 " {\n"
6952 " if (!foo)\n"
6953 " {\n"
6954 " ++i;\n"
6955 " }\n"
6956 " if (i > 3.5)\n"
6957 " {\n"
6958 " break;\n"
6959 " }\n"
6960 " ++i;\n"
6961 " }\n"
6962 " my_FragColor = vec4(i * 0.5 - 1.0, i * 0.5, 0.0, 1.0);\n"
6963 "}\n";
6964
6965 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6966 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
6967 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6968 }
6969
6970 // Test that a variable hides a user-defined function with the same name after its initializer.
6971 // GLSL ES 1.00.17 section 4.2.2: "A variable declaration is visible immediately following the
6972 // initializer if present, otherwise immediately following the identifier"
TEST_P(GLSLTest,VariableHidesUserDefinedFunctionAfterInitializer)6973 TEST_P(GLSLTest, VariableHidesUserDefinedFunctionAfterInitializer)
6974 {
6975 constexpr char kFS[] =
6976 "precision mediump float;\n"
6977 "uniform vec4 u;\n"
6978 "vec4 foo()\n"
6979 "{\n"
6980 " return u;\n"
6981 "}\n"
6982 "void main()\n"
6983 "{\n"
6984 " vec4 foo = foo();\n"
6985 " gl_FragColor = foo + vec4(0, 1, 0, 1);\n"
6986 "}\n";
6987
6988 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
6989 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
6990 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6991 }
6992
6993 // Test that structs with identical members are not ambiguous as function arguments.
TEST_P(GLSLTest,StructsWithSameMembersDisambiguatedByName)6994 TEST_P(GLSLTest, StructsWithSameMembersDisambiguatedByName)
6995 {
6996 constexpr char kFS[] =
6997 "precision mediump float;\n"
6998 "uniform float u_zero;\n"
6999 "struct S { float foo; };\n"
7000 "struct S2 { float foo; };\n"
7001 "float get(S s) { return s.foo + u_zero; }\n"
7002 "float get(S2 s2) { return 0.25 + s2.foo + u_zero; }\n"
7003 "void main()\n"
7004 "{\n"
7005 " S s;\n"
7006 " s.foo = 0.5;\n"
7007 " S2 s2;\n"
7008 " s2.foo = 0.25;\n"
7009 " gl_FragColor = vec4(0.0, get(s) + get(s2), 0.0, 1.0);\n"
7010 "}\n";
7011
7012 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
7013 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
7014 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7015 }
7016
7017 // Test that an inactive varying in vertex shader but used in fragment shader can be linked
7018 // successfully.
TEST_P(GLSLTest,InactiveVaryingInVertexActiveInFragment)7019 TEST_P(GLSLTest, InactiveVaryingInVertexActiveInFragment)
7020 {
7021 // http://anglebug.com/42263408
7022 ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
7023
7024 constexpr char kVS[] =
7025 "attribute vec4 inputAttribute;\n"
7026 "varying vec4 varColor;\n"
7027 "void main()\n"
7028 "{\n"
7029 " gl_Position = inputAttribute;\n"
7030 "}\n";
7031
7032 constexpr char kFS[] =
7033 "precision mediump float;\n"
7034 "varying vec4 varColor;\n"
7035 "void main()\n"
7036 "{\n"
7037 " gl_FragColor = varColor;\n"
7038 "}\n";
7039
7040 ANGLE_GL_PROGRAM(program, kVS, kFS);
7041 drawQuad(program, "inputAttribute", 0.5f);
7042 ASSERT_GL_NO_ERROR();
7043 }
7044
7045 // Test that a varying struct that's not statically used in the fragment shader works.
7046 // GLSL ES 3.00.6 section 4.3.10.
TEST_P(GLSLTest_ES3,VaryingStructNotStaticallyUsedInFragmentShader)7047 TEST_P(GLSLTest_ES3, VaryingStructNotStaticallyUsedInFragmentShader)
7048 {
7049 constexpr char kVS[] =
7050 "#version 300 es\n"
7051 "struct S {\n"
7052 " vec4 field;\n"
7053 "};\n"
7054 "out S varStruct;\n"
7055 "void main()\n"
7056 "{\n"
7057 " gl_Position = vec4(1.0);\n"
7058 " varStruct.field = vec4(0.0, 0.5, 0.0, 0.0);\n"
7059 "}\n";
7060
7061 constexpr char kFS[] =
7062 "#version 300 es\n"
7063 "precision mediump float;\n"
7064 "struct S {\n"
7065 " vec4 field;\n"
7066 "};\n"
7067 "in S varStruct;\n"
7068 "out vec4 col;\n"
7069 "void main()\n"
7070 "{\n"
7071 " col = vec4(1.0);\n"
7072 "}\n";
7073
7074 ANGLE_GL_PROGRAM(program, kVS, kFS);
7075 }
7076
7077 // Test that inactive shader IO block varying are ok.
TEST_P(GLSLTest_ES31,InactiveVaryingIOBlock)7078 TEST_P(GLSLTest_ES31, InactiveVaryingIOBlock)
7079 {
7080 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
7081
7082 constexpr char kVS[] =
7083 R"(#version 310 es
7084 #extension GL_EXT_shader_io_blocks : require
7085
7086 precision highp float;
7087 in vec4 inputAttribute;
7088 out Block { vec4 v; };
7089 out Inactive1 { vec4 value; };
7090 out Inactive2 { vec4 value; } named;
7091
7092 void main()
7093 {
7094 gl_Position = inputAttribute;
7095 v = vec4(0);
7096 })";
7097
7098 constexpr char kFS[] =
7099 R"(#version 310 es
7100 #extension GL_EXT_shader_io_blocks : require
7101
7102 precision highp float;
7103
7104 in Block { vec4 v; };
7105 in Inactive3 { vec4 value; };
7106 in Inactive4 { vec4 value; } named2;
7107
7108 layout(location = 0) out mediump vec4 color;
7109 void main()
7110 {
7111 color = vec4(1, v.xy, 1);
7112 })";
7113
7114 ANGLE_GL_PROGRAM(program, kVS, kFS);
7115 drawQuad(program, "inputAttribute", 0.5f);
7116 ASSERT_GL_NO_ERROR();
7117
7118 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7119 }
7120
7121 // Test that a shader IO block varying that's not declared in the fragment shader links
7122 // successfully.
TEST_P(GLSLTest_ES31,VaryingIOBlockNotDeclaredInFragmentShader)7123 TEST_P(GLSLTest_ES31, VaryingIOBlockNotDeclaredInFragmentShader)
7124 {
7125 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
7126
7127 constexpr char kVS[] =
7128 R"(#version 310 es
7129 #extension GL_EXT_shader_io_blocks : require
7130
7131 precision highp float;
7132 in vec4 inputAttribute;
7133 out Block_inout { vec4 value; } user_out;
7134
7135 void main()
7136 {
7137 gl_Position = inputAttribute;
7138 user_out.value = vec4(4.0, 5.0, 6.0, 7.0);
7139 })";
7140
7141 constexpr char kFS[] =
7142 R"(#version 310 es
7143 #extension GL_EXT_shader_io_blocks : require
7144
7145 precision highp float;
7146 layout(location = 0) out mediump vec4 color;
7147 void main()
7148 {
7149 color = vec4(1, 0, 0, 1);
7150 })";
7151
7152 ANGLE_GL_PROGRAM(program, kVS, kFS);
7153 drawQuad(program, "inputAttribute", 0.5f);
7154 ASSERT_GL_NO_ERROR();
7155
7156 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7157 }
7158
7159 // Test that a shader IO block varying that's not declared in the vertex shader links
7160 // successfully.
TEST_P(GLSLTest_ES31,VaryingIOBlockNotDeclaredInVertexShader)7161 TEST_P(GLSLTest_ES31, VaryingIOBlockNotDeclaredInVertexShader)
7162 {
7163 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
7164
7165 constexpr char kVS[] =
7166 R"(#version 310 es
7167 #extension GL_EXT_shader_io_blocks : require
7168
7169 precision highp float;
7170 in vec4 inputAttribute;
7171
7172 void main()
7173 {
7174 gl_Position = inputAttribute;
7175 })";
7176
7177 constexpr char kFS[] =
7178 R"(#version 310 es
7179 #extension GL_EXT_shader_io_blocks : require
7180
7181 precision highp float;
7182 in Block_inout { vec4 value; } user_in;
7183 layout(location = 0) out mediump vec4 color;
7184
7185 void main()
7186 {
7187 color = vec4(1, 0, 0, 1);
7188 })";
7189
7190 ANGLE_GL_PROGRAM(program, kVS, kFS);
7191 drawQuad(program, "inputAttribute", 0.5f);
7192 ASSERT_GL_NO_ERROR();
7193
7194 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7195 }
7196
7197 // Test that a shader with sample in / sample out can be linked successfully.
TEST_P(GLSLTest_ES31,VaryingTessellationSampleInAndOut)7198 TEST_P(GLSLTest_ES31, VaryingTessellationSampleInAndOut)
7199 {
7200 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
7201 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_multisample_interpolation"));
7202
7203 constexpr char kVS[] =
7204 R"(#version 310 es
7205 #extension GL_OES_shader_multisample_interpolation : require
7206
7207 precision highp float;
7208 in vec4 inputAttribute;
7209
7210 sample out mediump float tc_in;
7211 void main()
7212 {
7213 tc_in = inputAttribute[0];
7214 gl_Position = inputAttribute;
7215 })";
7216
7217 constexpr char kTCS[] =
7218 R"(#version 310 es
7219 #extension GL_EXT_tessellation_shader : require
7220 #extension GL_OES_shader_multisample_interpolation : require
7221 layout (vertices=3) out;
7222
7223 sample in mediump float tc_in[];
7224 sample out mediump float tc_out[];
7225 void main()
7226 {
7227 tc_out[gl_InvocationID] = tc_in[gl_InvocationID];
7228 gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
7229 gl_TessLevelInner[0] = 2.0;
7230 gl_TessLevelInner[1] = 2.0;
7231 gl_TessLevelOuter[0] = 2.0;
7232 gl_TessLevelOuter[1] = 2.0;
7233 gl_TessLevelOuter[2] = 2.0;
7234 gl_TessLevelOuter[3] = 2.0;
7235 })";
7236
7237 constexpr char kTES[] =
7238 R"(#version 310 es
7239 #extension GL_EXT_tessellation_shader : require
7240 #extension GL_OES_shader_multisample_interpolation : require
7241 layout (triangles) in;
7242
7243 sample in mediump float tc_out[];
7244 sample out mediump float te_out;
7245 void main()
7246 {
7247 te_out = tc_out[2];
7248 gl_Position = gl_TessCoord[0] * gl_in[0].gl_Position;
7249 })";
7250
7251 constexpr char kFS[] =
7252 R"(#version 310 es
7253 #extension GL_OES_shader_multisample_interpolation : require
7254
7255 precision highp float;
7256 sample in mediump float te_out;
7257 layout(location = 0) out mediump vec4 color;
7258
7259 void main()
7260 {
7261 float out0 = te_out;
7262 color = vec4(1, 0, 0, 1);
7263 })";
7264
7265 ANGLE_GL_PROGRAM_WITH_TESS(program, kVS, kTCS, kTES, kFS);
7266 drawPatches(program, "inputAttribute", 0.5f, 1.0f, GL_FALSE);
7267 ASSERT_GL_NO_ERROR();
7268 }
7269
7270 // Test that `smooth sample` and `flat sample` pass the validation.
TEST_P(GLSLTest_ES3,AliasedSampleQualifiers)7271 TEST_P(GLSLTest_ES3, AliasedSampleQualifiers)
7272 {
7273 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_multisample_interpolation"));
7274
7275 constexpr char kVS[] =
7276 R"(#version 300 es
7277 #extension GL_OES_shader_multisample_interpolation : require
7278
7279 smooth sample out mediump float f;
7280 flat sample out mediump int i;
7281 void main()
7282 {
7283 f = 1.0;
7284 i = 1;
7285 gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
7286 })";
7287
7288 constexpr char kFS[] =
7289 R"(#version 300 es
7290 #extension GL_OES_shader_multisample_interpolation : require
7291
7292 smooth sample in mediump float f;
7293 flat sample in mediump int i;
7294 out mediump vec4 color;
7295 void main()
7296 {
7297 color = vec4(f, float(i), 0, 1);
7298 })";
7299
7300 ANGLE_GL_PROGRAM(program, kVS, kFS);
7301 }
7302
7303 // Test that `noperspective centroid` passes the validation and compiles.
TEST_P(GLSLTest_ES3,NoPerspectiveCentroid)7304 TEST_P(GLSLTest_ES3, NoPerspectiveCentroid)
7305 {
7306 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_shader_noperspective_interpolation"));
7307
7308 constexpr char kVS[] =
7309 R"(#version 300 es
7310 #extension GL_NV_shader_noperspective_interpolation : require
7311
7312 noperspective centroid out mediump float f;
7313 void main()
7314 {
7315 f = 1.0;
7316 gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
7317 })";
7318
7319 constexpr char kFS[] =
7320 R"(#version 300 es
7321 #extension GL_NV_shader_noperspective_interpolation : require
7322
7323 noperspective centroid in mediump float f;
7324 out mediump vec4 color;
7325 void main()
7326 {
7327 color = vec4(f, 0.0, 0.0, 1.0);
7328 })";
7329
7330 ANGLE_GL_PROGRAM(program, kVS, kFS);
7331 }
7332
7333 // Test that `noperspective sample` passes the validation and compiles.
TEST_P(GLSLTest_ES3,NoPerspectiveSample)7334 TEST_P(GLSLTest_ES3, NoPerspectiveSample)
7335 {
7336 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_multisample_interpolation"));
7337 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_shader_noperspective_interpolation"));
7338
7339 constexpr char kVS[] =
7340 R"(#version 300 es
7341 #extension GL_OES_shader_multisample_interpolation : require
7342 #extension GL_NV_shader_noperspective_interpolation : require
7343
7344 noperspective sample out mediump float f;
7345 void main()
7346 {
7347 f = 1.0;
7348 gl_Position = vec4(f, 0.0, 0.0, 1.0);
7349 })";
7350
7351 constexpr char kFS[] =
7352 R"(#version 300 es
7353 #extension GL_OES_shader_multisample_interpolation : require
7354 #extension GL_NV_shader_noperspective_interpolation : require
7355
7356 noperspective sample in mediump float f;
7357 out mediump vec4 color;
7358 void main()
7359 {
7360 color = vec4(f, 0.0, 0.0, 1.0);
7361 })";
7362
7363 ANGLE_GL_PROGRAM(program, kVS, kFS);
7364 }
7365
7366 // Test that a shader with sample in / sample out can be used successfully when the varying
7367 // precision is different between VS and FS.
TEST_P(GLSLTest_ES31,VaryingSampleInAndOutDifferentPrecision)7368 TEST_P(GLSLTest_ES31, VaryingSampleInAndOutDifferentPrecision)
7369 {
7370 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_multisample_interpolation"));
7371
7372 constexpr char kVS[] =
7373 R"(#version 310 es
7374 #extension GL_OES_shader_multisample_interpolation : require
7375
7376 precision highp float;
7377 in vec4 inputAttribute;
7378
7379 sample out highp float v;
7380 void main()
7381 {
7382 v = inputAttribute[0];
7383 gl_Position = inputAttribute;
7384 })";
7385
7386 constexpr char kFS[] =
7387 R"(#version 310 es
7388 #extension GL_OES_shader_multisample_interpolation : require
7389
7390 precision highp float;
7391 sample in mediump float v;
7392 layout(location = 0) out mediump vec4 color;
7393
7394 void main()
7395 {
7396 color = vec4(round((v + 1.) / 2. * 5.) / 5., 0, 0, 1);
7397 })";
7398
7399 ANGLE_GL_PROGRAM(program, kVS, kFS);
7400 drawQuad(program, "inputAttribute", 0.5f, 1.0f, GL_FALSE);
7401 ASSERT_GL_NO_ERROR();
7402
7403 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, 0, GLColor::red);
7404 }
7405
7406 // Test that a shader IO block varying whose block name is declared multiple(in/out) time links
7407 // successfully.
TEST_P(GLSLTest_ES31,VaryingIOBlockDeclaredAsInAndOut)7408 TEST_P(GLSLTest_ES31, VaryingIOBlockDeclaredAsInAndOut)
7409 {
7410 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
7411 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
7412
7413 constexpr char kVS[] = R"(#version 310 es
7414 #extension GL_EXT_shader_io_blocks : require
7415 precision highp float;
7416 in vec4 inputAttribute;
7417 out Vertex
7418 {
7419 vec4 fv;
7420 } outVertex;
7421 void main()
7422 {
7423 gl_Position = inputAttribute;
7424 outVertex.fv = gl_Position;
7425 })";
7426
7427 constexpr char kTCS[] = R"(#version 310 es
7428 #extension GL_EXT_tessellation_shader : require
7429 #extension GL_EXT_shader_io_blocks : require
7430 precision mediump float;
7431 in Vertex
7432 {
7433 vec4 fv;
7434 } inVertex[];
7435 layout(vertices = 2) out;
7436 out Vertex
7437 {
7438 vec4 fv;
7439 } outVertex[];
7440
7441 void main()
7442 {
7443 gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
7444 outVertex[gl_InvocationID].fv = inVertex[gl_InvocationID].fv;
7445 gl_TessLevelInner[0] = 1.0;
7446 gl_TessLevelInner[1] = 1.0;
7447 gl_TessLevelOuter[0] = 1.0;
7448 gl_TessLevelOuter[1] = 1.0;
7449 gl_TessLevelOuter[2] = 1.0;
7450 gl_TessLevelOuter[3] = 1.0;
7451 })";
7452
7453 constexpr char kTES[] = R"(#version 310 es
7454 #extension GL_EXT_tessellation_shader : require
7455 #extension GL_EXT_shader_io_blocks : require
7456 precision mediump float;
7457 layout (isolines, point_mode) in;
7458 in Vertex
7459 {
7460 vec4 fv;
7461 } inVertex[];
7462 out vec4 result_fv;
7463
7464 void main()
7465 {
7466 gl_Position = gl_in[0].gl_Position;
7467 result_fv = inVertex[0].fv;
7468 })";
7469
7470 constexpr char kFS[] = R"(#version 310 es
7471 precision mediump float;
7472
7473 layout(location = 0) out mediump vec4 color;
7474
7475 void main()
7476 {
7477 // Output solid green
7478 color = vec4(0, 1.0, 0, 1.0);
7479 })";
7480
7481 ANGLE_GL_PROGRAM_WITH_TESS(program, kVS, kTCS, kTES, kFS);
7482 drawPatches(program, "inputAttribute", 0.5f, 1.0f, GL_FALSE);
7483 ASSERT_GL_NO_ERROR();
7484 }
7485
testTessellationTextureBufferAccess(const APIExtensionVersion usedExtension)7486 void GLSLTest_ES31::testTessellationTextureBufferAccess(const APIExtensionVersion usedExtension)
7487 {
7488 ASSERT(usedExtension == APIExtensionVersion::EXT || usedExtension == APIExtensionVersion::OES);
7489
7490 // Vertex shader
7491 constexpr char kVS[] = R"(#version 310 es
7492 precision highp float;
7493 in vec4 inputAttribute;
7494
7495 void main()
7496 {
7497 gl_Position = inputAttribute;
7498 })";
7499
7500 // Tessellation shaders
7501 constexpr char kGLSLVersion[] = R"(#version 310 es
7502 )";
7503 constexpr char kTessEXT[] = R"(#extension GL_EXT_tessellation_shader : require
7504 )";
7505 constexpr char kTessOES[] = R"(#extension GL_OES_tessellation_shader : require
7506 )";
7507 constexpr char kTexBufEXT[] = R"(#extension GL_EXT_texture_buffer : require
7508 )";
7509 constexpr char kTexBufOES[] = R"(#extension GL_OES_texture_buffer : require
7510 )";
7511
7512 std::string tcs;
7513 std::string tes;
7514
7515 tcs.append(kGLSLVersion);
7516 tes.append(kGLSLVersion);
7517
7518 if (usedExtension == APIExtensionVersion::EXT)
7519 {
7520 tcs.append(kTessEXT);
7521 tes.append(kTessEXT);
7522 tes.append(kTexBufEXT);
7523 }
7524 else
7525 {
7526 tcs.append(kTessOES);
7527 tes.append(kTessOES);
7528 tes.append(kTexBufOES);
7529 }
7530
7531 constexpr char kTCSBody[] = R"(precision mediump float;
7532 layout(vertices = 2) out;
7533
7534 void main()
7535 {
7536 gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
7537 gl_TessLevelInner[0] = 1.0;
7538 gl_TessLevelInner[1] = 1.0;
7539 gl_TessLevelOuter[0] = 1.0;
7540 gl_TessLevelOuter[1] = 1.0;
7541 gl_TessLevelOuter[2] = 1.0;
7542 gl_TessLevelOuter[3] = 1.0;
7543 })";
7544 tcs.append(kTCSBody);
7545
7546 constexpr char kTESBody[] = R"(precision mediump float;
7547 layout (isolines, point_mode) in;
7548
7549 uniform highp samplerBuffer tex;
7550
7551 out vec4 tex_color;
7552
7553 void main()
7554 {
7555 tex_color = texelFetch(tex, 0);
7556 gl_Position = gl_in[0].gl_Position;
7557 })";
7558 tes.append(kTESBody);
7559
7560 // Fragment shader
7561 constexpr char kFS[] = R"(#version 310 es
7562 precision mediump float;
7563 layout(location = 0) out mediump vec4 color;
7564
7565 in vec4 tex_color;
7566
7567 void main()
7568 {
7569 color = tex_color;
7570 })";
7571
7572 constexpr GLint kBufferSize = 4;
7573 GLubyte texData[] = {0u, 255u, 0u, 255u};
7574
7575 GLTexture texture;
7576 glBindTexture(GL_TEXTURE_BUFFER, texture);
7577
7578 GLBuffer buffer;
7579 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
7580 glBufferData(GL_TEXTURE_BUFFER, kBufferSize, texData, GL_STATIC_DRAW);
7581 glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGBA8, buffer);
7582 ASSERT_GL_NO_ERROR();
7583
7584 glClearColor(1.0, 0, 0, 1.0);
7585 glClear(GL_COLOR_BUFFER_BIT);
7586
7587 ANGLE_GL_PROGRAM_WITH_TESS(program, kVS, tcs.c_str(), tes.c_str(), kFS);
7588 drawPatches(program, "inputAttribute", 0.5f, 1.0f, GL_FALSE);
7589 ASSERT_GL_NO_ERROR();
7590 }
7591
7592 // Test that texture buffers can be accessed in a tessellation stage (using EXT)
TEST_P(GLSLTest_ES31,TessellationTextureBufferAccessEXT)7593 TEST_P(GLSLTest_ES31, TessellationTextureBufferAccessEXT)
7594 {
7595 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
7596 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_buffer"));
7597 testTessellationTextureBufferAccess(APIExtensionVersion::EXT);
7598 }
7599
7600 // Test that texture buffers can be accessed in a tessellation stage (using OES)
TEST_P(GLSLTest_ES31,TessellationTextureBufferAccessOES)7601 TEST_P(GLSLTest_ES31, TessellationTextureBufferAccessOES)
7602 {
7603 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_tessellation_shader"));
7604 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_buffer"));
7605 testTessellationTextureBufferAccess(APIExtensionVersion::OES);
7606 }
7607
7608 // Test that a varying struct that's not declared in the fragment shader links successfully.
7609 // GLSL ES 3.00.6 section 4.3.10.
TEST_P(GLSLTest_ES3,VaryingStructNotDeclaredInFragmentShader)7610 TEST_P(GLSLTest_ES3, VaryingStructNotDeclaredInFragmentShader)
7611 {
7612 constexpr char kVS[] =
7613 "#version 300 es\n"
7614 "struct S {\n"
7615 " vec4 field;\n"
7616 "};\n"
7617 "out S varStruct;\n"
7618 "void main()\n"
7619 "{\n"
7620 " gl_Position = vec4(1.0);\n"
7621 " varStruct.field = vec4(0.0, 0.5, 0.0, 0.0);\n"
7622 "}\n";
7623
7624 constexpr char kFS[] =
7625 "#version 300 es\n"
7626 "precision mediump float;\n"
7627 "out vec4 col;\n"
7628 "void main()\n"
7629 "{\n"
7630 " col = vec4(1.0);\n"
7631 "}\n";
7632
7633 ANGLE_GL_PROGRAM(program, kVS, kFS);
7634 }
7635
7636 // Test that a varying struct that's not declared in the vertex shader, and is unused in the
7637 // fragment shader links successfully.
TEST_P(GLSLTest_ES3,VaryingStructNotDeclaredInVertexShader)7638 TEST_P(GLSLTest_ES3, VaryingStructNotDeclaredInVertexShader)
7639 {
7640 // GLSL ES allows the vertex shader to not declare a varying if the fragment shader is not
7641 // going to use it. See section 9.1 in
7642 // https://www.khronos.org/registry/OpenGL/specs/es/3.2/GLSL_ES_Specification_3.20.pdf or
7643 // section 4.3.5 in https://www.khronos.org/files/opengles_shading_language.pdf
7644 //
7645 // However, nvidia OpenGL ES drivers fail to link this program.
7646 //
7647 // http://anglebug.com/42262078
7648 ANGLE_SKIP_TEST_IF(IsOpenGLES() && IsNVIDIA());
7649
7650 constexpr char kVS[] =
7651 "#version 300 es\n"
7652 "void main()\n"
7653 "{\n"
7654 " gl_Position = vec4(1.0);\n"
7655 "}\n";
7656
7657 constexpr char kFS[] =
7658 "#version 300 es\n"
7659 "precision mediump float;\n"
7660 "out vec4 col;\n"
7661 "struct S {\n"
7662 " vec4 field;\n"
7663 "};\n"
7664 "in S varStruct;\n"
7665 "void main()\n"
7666 "{\n"
7667 " col = vec4(1.0);\n"
7668 "}\n";
7669
7670 ANGLE_GL_PROGRAM(program, kVS, kFS);
7671 }
7672
7673 // Test that a varying struct that's not initialized in the vertex shader links successfully.
TEST_P(WebGL2GLSLTest,VaryingStructNotInitializedInVertexShader)7674 TEST_P(WebGL2GLSLTest, VaryingStructNotInitializedInVertexShader)
7675 {
7676 // GLSL ES allows the vertex shader to declare but not initialize a varying (with a
7677 // specification that the varying values are undefined in the fragment stage). See section 9.1
7678 // in https://www.khronos.org/registry/OpenGL/specs/es/3.2/GLSL_ES_Specification_3.20.pdf
7679 // or section 4.3.5 in https://www.khronos.org/files/opengles_shading_language.pdf
7680 //
7681 // However, windows and mac OpenGL drivers fail to link this program. With a message like:
7682 //
7683 // > Input of fragment shader 'varStruct' not written by vertex shader
7684 //
7685 // http://anglebug.com/42262078
7686 ANGLE_SKIP_TEST_IF(IsDesktopOpenGL() && (IsMac() || (IsWindows() && !IsNVIDIA())));
7687
7688 constexpr char kVS[] =
7689 "#version 300 es\n"
7690 "struct S {\n"
7691 " vec4 field;\n"
7692 "};\n"
7693 "out S varStruct;\n"
7694 "void main()\n"
7695 "{\n"
7696 " gl_Position = vec4(1.0);\n"
7697 "}\n";
7698
7699 constexpr char kFS[] =
7700 "#version 300 es\n"
7701 "precision mediump float;\n"
7702 "out vec4 col;\n"
7703 "struct S {\n"
7704 " vec4 field;\n"
7705 "};\n"
7706 "in S varStruct;\n"
7707 "void main()\n"
7708 "{\n"
7709 " col = varStruct.field;\n"
7710 "}\n";
7711
7712 ANGLE_GL_PROGRAM(program, kVS, kFS);
7713 }
7714
7715 // Test that a varying struct that gets used in the fragment shader works.
TEST_P(GLSLTest_ES3,VaryingStructUsedInFragmentShader)7716 TEST_P(GLSLTest_ES3, VaryingStructUsedInFragmentShader)
7717 {
7718 constexpr char kVS[] =
7719 "#version 300 es\n"
7720 "in vec4 inputAttribute;\n"
7721 "struct S {\n"
7722 " vec4 field;\n"
7723 "};\n"
7724 "out S varStruct;\n"
7725 "out S varStruct2;\n"
7726 "void main()\n"
7727 "{\n"
7728 " gl_Position = inputAttribute;\n"
7729 " varStruct.field = vec4(0.0, 0.5, 0.0, 1.0);\n"
7730 " varStruct2.field = vec4(0.0, 0.5, 0.0, 1.0);\n"
7731 "}\n";
7732
7733 constexpr char kFS[] =
7734 "#version 300 es\n"
7735 "precision mediump float;\n"
7736 "out vec4 col;\n"
7737 "struct S {\n"
7738 " vec4 field;\n"
7739 "};\n"
7740 "in S varStruct;\n"
7741 "in S varStruct2;\n"
7742 "void main()\n"
7743 "{\n"
7744 " col = varStruct.field + varStruct2.field;\n"
7745 "}\n";
7746
7747 ANGLE_GL_PROGRAM(program, kVS, kFS);
7748 drawQuad(program, "inputAttribute", 0.5f);
7749 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7750 }
7751
7752 // This is a regression test to make sure a red quad is rendered without issues
7753 // when a passthrough function with a vec3 input parameter is used in the fragment shader.
TEST_P(GLSLTest_ES31,SamplerPassthroughFailedLink)7754 TEST_P(GLSLTest_ES31, SamplerPassthroughFailedLink)
7755 {
7756 constexpr char kVS[] =
7757 "precision mediump float;\n"
7758 "attribute vec4 inputAttribute;\n"
7759 "varying mediump vec2 texCoord;\n"
7760 "void main() {\n"
7761 " texCoord = inputAttribute.xy;\n"
7762 " gl_Position = vec4(inputAttribute.x, inputAttribute.y, 0.0, 1.0);\n"
7763 "}\n";
7764
7765 constexpr char kFS[] =
7766 "precision mediump float;\n"
7767 "varying mediump vec2 texCoord;\n"
7768 "uniform sampler2D testSampler;\n"
7769 "vec3 passthrough(vec3 c) {\n"
7770 " return c;\n"
7771 "}\n"
7772 "void main() {\n"
7773 " gl_FragColor = vec4(passthrough(texture2D(testSampler, texCoord).rgb), 1.0);\n"
7774 "}\n";
7775 ANGLE_GL_PROGRAM(program, kVS, kFS);
7776
7777 // Initialize basic red texture.
7778 GLTexture texture;
7779 glBindTexture(GL_TEXTURE_2D, texture);
7780 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
7781 GLColor::red.data());
7782 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7783 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7784 ASSERT_GL_NO_ERROR();
7785
7786 drawQuad(program, "inputAttribute", 0.5f);
7787 ASSERT_GL_NO_ERROR();
7788 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7789 }
7790
7791 // This is a regression test to make sure a red quad is rendered without issues
7792 // when a passthrough function with a vec4 input parameter is used in the fragment shader.
TEST_P(GLSLTest_ES31,SamplerPassthroughIncorrectColor)7793 TEST_P(GLSLTest_ES31, SamplerPassthroughIncorrectColor)
7794 {
7795 constexpr char kVS[] =
7796 "precision mediump float;\n"
7797 "attribute vec4 inputAttribute;\n"
7798 "varying mediump vec2 texCoord;\n"
7799 "void main() {\n"
7800 " texCoord = inputAttribute.xy;\n"
7801 " gl_Position = vec4(inputAttribute.x, inputAttribute.y, 0.0, 1.0);\n"
7802 "}\n";
7803
7804 constexpr char kFS[] =
7805 "precision mediump float;\n"
7806 "varying mediump vec2 texCoord;\n"
7807 "uniform sampler2D testSampler;\n"
7808 "vec4 passthrough(vec4 c) {\n"
7809 " return c;\n"
7810 "}\n"
7811 "void main() {\n"
7812 " gl_FragColor = vec4(passthrough(texture2D(testSampler, texCoord)));\n"
7813 "}\n";
7814 ANGLE_GL_PROGRAM(program, kVS, kFS);
7815
7816 // Initialize basic red texture.
7817 GLTexture texture;
7818 glBindTexture(GL_TEXTURE_2D, texture);
7819 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
7820 GLColor::red.data());
7821 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7822 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7823 ASSERT_GL_NO_ERROR();
7824
7825 drawQuad(program, "inputAttribute", 0.5f);
7826 ASSERT_GL_NO_ERROR();
7827 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7828 }
7829
7830 // Test that multiple multi-field varying structs that get used in the fragment shader work.
TEST_P(GLSLTest_ES3,ComplexVaryingStructsUsedInFragmentShader)7831 TEST_P(GLSLTest_ES3, ComplexVaryingStructsUsedInFragmentShader)
7832 {
7833 // TODO(syoussefi): fails on android with:
7834 //
7835 // > Internal Vulkan error: A return array was too small for the result
7836 //
7837 // http://anglebug.com/42261898
7838 ANGLE_SKIP_TEST_IF(IsVulkan() && IsAndroid());
7839
7840 constexpr char kVS[] =
7841 "#version 300 es\n"
7842 "in vec4 inputAttribute;\n"
7843 "struct S {\n"
7844 " vec4 field1;\n"
7845 " vec4 field2;\n"
7846 "};\n"
7847 "out S varStruct;\n"
7848 "out S varStruct2;\n"
7849 "void main()\n"
7850 "{\n"
7851 " gl_Position = inputAttribute;\n"
7852 " varStruct.field1 = vec4(0.0, 0.5, 0.0, 1.0);\n"
7853 " varStruct.field2 = vec4(0.0, 0.5, 0.0, 1.0);\n"
7854 " varStruct2.field1 = vec4(0.0, 0.5, 0.0, 1.0);\n"
7855 " varStruct2.field2 = vec4(0.0, 0.5, 0.0, 1.0);\n"
7856 "}\n";
7857
7858 constexpr char kFS[] =
7859 "#version 300 es\n"
7860 "precision mediump float;\n"
7861 "out vec4 col;\n"
7862 "struct S {\n"
7863 " vec4 field1;\n"
7864 " vec4 field2;\n"
7865 "};\n"
7866 "in S varStruct;\n"
7867 "in S varStruct2;\n"
7868 "void main()\n"
7869 "{\n"
7870 " col = varStruct.field1 + varStruct2.field2;\n"
7871 "}\n";
7872
7873 ANGLE_GL_PROGRAM(program, kVS, kFS);
7874 drawQuad(program, "inputAttribute", 0.5f);
7875 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7876 }
7877
7878 // Test that an inactive varying array that doesn't get used in the fragment shader works.
TEST_P(GLSLTest_ES3,InactiveVaryingArrayUnusedInFragmentShader)7879 TEST_P(GLSLTest_ES3, InactiveVaryingArrayUnusedInFragmentShader)
7880 {
7881 constexpr char kVS[] =
7882 "#version 300 es\n"
7883 "in vec4 inputAttribute;\n"
7884 "out vec4 varArray[4];\n"
7885 "void main()\n"
7886 "{\n"
7887 " gl_Position = inputAttribute;\n"
7888 " varArray[0] = vec4(1.0, 0.0, 0.0, 1.0);\n"
7889 " varArray[1] = vec4(0.0, 1.0, 0.0, 1.0);\n"
7890 " varArray[2] = vec4(0.0, 0.0, 1.0, 1.0);\n"
7891 " varArray[3] = vec4(1.0, 1.0, 0.0, 1.0);\n"
7892 "}\n";
7893
7894 constexpr char kFS[] =
7895 "#version 300 es\n"
7896 "precision mediump float;\n"
7897 "out vec4 col;\n"
7898 "void main()\n"
7899 "{\n"
7900 " col = vec4(0.0, 0.0, 0.0, 1.0);\n"
7901 "}\n";
7902
7903 ANGLE_GL_PROGRAM(program, kVS, kFS);
7904 drawQuad(program, "inputAttribute", 0.5f);
7905 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
7906 }
7907
7908 // Test that an inactive varying struct that doesn't get used in the fragment shader works.
TEST_P(GLSLTest_ES3,InactiveVaryingStructUnusedInFragmentShader)7909 TEST_P(GLSLTest_ES3, InactiveVaryingStructUnusedInFragmentShader)
7910 {
7911 constexpr char kVS[] =
7912 "#version 300 es\n"
7913 "in vec4 inputAttribute;\n"
7914 "struct S {\n"
7915 " vec4 field;\n"
7916 "};\n"
7917 "out S varStruct;\n"
7918 "out S varStruct2;\n"
7919 "void main()\n"
7920 "{\n"
7921 " gl_Position = inputAttribute;\n"
7922 " varStruct.field = vec4(0.0, 1.0, 0.0, 1.0);\n"
7923 " varStruct2.field = vec4(0.0, 1.0, 0.0, 1.0);\n"
7924 "}\n";
7925
7926 constexpr char kFS[] =
7927 "#version 300 es\n"
7928 "precision mediump float;\n"
7929 "out vec4 col;\n"
7930 "struct S {\n"
7931 " vec4 field;\n"
7932 "};\n"
7933 "in S varStruct;\n"
7934 "in S varStruct2;\n"
7935 "void main()\n"
7936 "{\n"
7937 " col = varStruct.field;\n"
7938 "}\n";
7939
7940 ANGLE_GL_PROGRAM(program, kVS, kFS);
7941 drawQuad(program, "inputAttribute", 0.5f);
7942 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7943 }
7944
7945 // Test that multiple varying matrices that get used in the fragment shader work.
TEST_P(GLSLTest_ES3,VaryingMatrices)7946 TEST_P(GLSLTest_ES3, VaryingMatrices)
7947 {
7948 constexpr char kVS[] =
7949 "#version 300 es\n"
7950 "in vec4 inputAttribute;\n"
7951 "out mat2x2 varMat;\n"
7952 "out mat2x2 varMat2;\n"
7953 "out mat4x3 varMat3;\n"
7954 "void main()\n"
7955 "{\n"
7956 " gl_Position = inputAttribute;\n"
7957 " varMat[0] = vec2(1, 1);\n"
7958 " varMat[1] = vec2(1, 1);\n"
7959 " varMat2[0] = vec2(0.5, 0.5);\n"
7960 " varMat2[1] = vec2(0.5, 0.5);\n"
7961 " varMat3[0] = vec3(0.75, 0.75, 0.75);\n"
7962 " varMat3[1] = vec3(0.75, 0.75, 0.75);\n"
7963 " varMat3[2] = vec3(0.75, 0.75, 0.75);\n"
7964 " varMat3[3] = vec3(0.75, 0.75, 0.75);\n"
7965 "}\n";
7966
7967 constexpr char kFS[] =
7968 "#version 300 es\n"
7969 "precision mediump float;\n"
7970 "out vec4 col;\n"
7971 "in mat2x2 varMat;\n"
7972 "in mat2x2 varMat2;\n"
7973 "in mat4x3 varMat3;\n"
7974 "void main()\n"
7975 "{\n"
7976 " col = vec4(varMat[0].x, varMat2[1].y, varMat3[2].z, 1);\n"
7977 "}\n";
7978
7979 ANGLE_GL_PROGRAM(program, kVS, kFS);
7980 drawQuad(program, "inputAttribute", 0.5f);
7981 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 127, 191, 255), 1);
7982 }
7983
7984 // This test covers passing a struct containing a sampler as a function argument.
TEST_P(GLSLTest,StructsWithSamplersAsFunctionArg)7985 TEST_P(GLSLTest, StructsWithSamplersAsFunctionArg)
7986 {
7987 // Shader failed to compile on Nexus devices. http://anglebug.com/42260860
7988 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
7989
7990 const char kFragmentShader[] = R"(precision mediump float;
7991 struct S { sampler2D samplerMember; };
7992 uniform S uStruct;
7993 uniform vec2 uTexCoord;
7994 vec4 foo(S structVar)
7995 {
7996 return texture2D(structVar.samplerMember, uTexCoord);
7997 }
7998 void main()
7999 {
8000 gl_FragColor = foo(uStruct);
8001 })";
8002
8003 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
8004
8005 // Initialize the texture with green.
8006 GLTexture tex;
8007 glActiveTexture(GL_TEXTURE0);
8008 glBindTexture(GL_TEXTURE_2D, tex);
8009 GLubyte texData[] = {0u, 255u, 0u, 255u};
8010 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
8011 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8012 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8013 ASSERT_GL_NO_ERROR();
8014
8015 // Draw
8016 glUseProgram(program);
8017 GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMember");
8018 ASSERT_NE(-1, samplerMemberLoc);
8019 glUniform1i(samplerMemberLoc, 0);
8020 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
8021 ASSERT_NE(-1, texCoordLoc);
8022 glUniform2f(texCoordLoc, 0.5f, 0.5f);
8023
8024 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
8025 ASSERT_GL_NO_ERROR();
8026
8027 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
8028 }
8029
8030 // This test covers passing a struct containing a sampler as a function argument.
TEST_P(GLSLTest,StructsWithSamplersAsFunctionArgWithPrototype)8031 TEST_P(GLSLTest, StructsWithSamplersAsFunctionArgWithPrototype)
8032 {
8033 // Shader failed to compile on Android. http://anglebug.com/42260860
8034 ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
8035
8036 const char kFragmentShader[] = R"(precision mediump float;
8037 struct S { sampler2D samplerMember; };
8038 uniform S uStruct;
8039 uniform vec2 uTexCoord;
8040 vec4 foo(S structVar);
8041 vec4 foo(S structVar)
8042 {
8043 return texture2D(structVar.samplerMember, uTexCoord);
8044 }
8045 void main()
8046 {
8047 gl_FragColor = foo(uStruct);
8048 })";
8049
8050 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
8051
8052 // Initialize the texture with green.
8053 GLTexture tex;
8054 glActiveTexture(GL_TEXTURE0);
8055 glBindTexture(GL_TEXTURE_2D, tex);
8056 GLubyte texData[] = {0u, 255u, 0u, 255u};
8057 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
8058 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8059 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8060 ASSERT_GL_NO_ERROR();
8061
8062 // Draw
8063 glUseProgram(program);
8064 GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMember");
8065 ASSERT_NE(-1, samplerMemberLoc);
8066 glUniform1i(samplerMemberLoc, 0);
8067 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
8068 ASSERT_NE(-1, texCoordLoc);
8069 glUniform2f(texCoordLoc, 0.5f, 0.5f);
8070
8071 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
8072 ASSERT_GL_NO_ERROR();
8073
8074 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
8075 }
8076
8077 // This test covers passing a struct containing a sampler as a function argument, where the function
8078 // has non-return branch statements.
TEST_P(GLSLTest_ES3,StructsWithSamplersAsFunctionArgWithBranch)8079 TEST_P(GLSLTest_ES3, StructsWithSamplersAsFunctionArgWithBranch)
8080 {
8081 // Shader failed to compile on Nexus devices. http://anglebug.com/42260860
8082 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
8083
8084 const char kFragmentShader[] = R"(precision mediump float;
8085 struct S { sampler2D samplerMember; };
8086 uniform S uStruct;
8087 uniform vec2 uTexCoord;
8088 vec4 foo(S structVar)
8089 {
8090 vec4 result;
8091 while (true)
8092 {
8093 result = texture2D(structVar.samplerMember, uTexCoord);
8094 if (result.x == 12345.)
8095 {
8096 continue;
8097 }
8098 break;
8099 }
8100 return result;
8101 }
8102 void main()
8103 {
8104 gl_FragColor = foo(uStruct);
8105 })";
8106
8107 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
8108
8109 // Initialize the texture with green.
8110 GLTexture tex;
8111 glActiveTexture(GL_TEXTURE0);
8112 glBindTexture(GL_TEXTURE_2D, tex);
8113 GLubyte texData[] = {0u, 255u, 0u, 255u};
8114 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
8115 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8116 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8117 ASSERT_GL_NO_ERROR();
8118
8119 // Draw
8120 glUseProgram(program);
8121 GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMember");
8122 ASSERT_NE(-1, samplerMemberLoc);
8123 glUniform1i(samplerMemberLoc, 0);
8124 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
8125 ASSERT_NE(-1, texCoordLoc);
8126 glUniform2f(texCoordLoc, 0.5f, 0.5f);
8127
8128 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
8129 ASSERT_GL_NO_ERROR();
8130
8131 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
8132 }
8133
8134 // This test covers passing an array of structs containing samplers as a function argument.
TEST_P(GLSLTest,ArrayOfStructsWithSamplersAsFunctionArg)8135 TEST_P(GLSLTest, ArrayOfStructsWithSamplersAsFunctionArg)
8136 {
8137 // Shader failed to compile on Nexus devices. http://anglebug.com/42260860
8138 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
8139
8140 constexpr char kFS[] =
8141 "precision mediump float;\n"
8142 "struct S\n"
8143 "{\n"
8144 " sampler2D samplerMember; \n"
8145 "};\n"
8146 "uniform S uStructs[2];\n"
8147 "uniform vec2 uTexCoord;\n"
8148 "\n"
8149 "vec4 foo(S[2] structs)\n"
8150 "{\n"
8151 " return texture2D(structs[0].samplerMember, uTexCoord);\n"
8152 "}\n"
8153 "void main()\n"
8154 "{\n"
8155 " gl_FragColor = foo(uStructs);\n"
8156 "}\n";
8157
8158 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
8159
8160 // Initialize the texture with green.
8161 GLTexture tex;
8162 glActiveTexture(GL_TEXTURE0);
8163 glBindTexture(GL_TEXTURE_2D, tex);
8164 GLubyte texData[] = {0u, 255u, 0u, 255u};
8165 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
8166 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8167 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8168 ASSERT_GL_NO_ERROR();
8169
8170 // Draw
8171 glUseProgram(program);
8172 GLint samplerMemberLoc = glGetUniformLocation(program, "uStructs[0].samplerMember");
8173 ASSERT_NE(-1, samplerMemberLoc);
8174 glUniform1i(samplerMemberLoc, 0);
8175 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
8176 ASSERT_NE(-1, texCoordLoc);
8177 glUniform2f(texCoordLoc, 0.5f, 0.5f);
8178
8179 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
8180 ASSERT_GL_NO_ERROR();
8181
8182 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
8183 }
8184
8185 // This test covers passing a struct containing an array of samplers as a function argument.
TEST_P(GLSLTest,StructWithSamplerArrayAsFunctionArg)8186 TEST_P(GLSLTest, StructWithSamplerArrayAsFunctionArg)
8187 {
8188 // Shader failed to compile on Nexus devices. http://anglebug.com/42260860
8189 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
8190
8191 constexpr char kFS[] =
8192 "precision mediump float;\n"
8193 "struct S\n"
8194 "{\n"
8195 " sampler2D samplerMembers[2];\n"
8196 "};\n"
8197 "uniform S uStruct;\n"
8198 "uniform vec2 uTexCoord;\n"
8199 "\n"
8200 "vec4 foo(S str)\n"
8201 "{\n"
8202 " return texture2D(str.samplerMembers[0], uTexCoord);\n"
8203 "}\n"
8204 "void main()\n"
8205 "{\n"
8206 " gl_FragColor = foo(uStruct);\n"
8207 "}\n";
8208
8209 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
8210
8211 // Initialize the texture with green.
8212 GLTexture tex;
8213 glActiveTexture(GL_TEXTURE0);
8214 glBindTexture(GL_TEXTURE_2D, tex);
8215 GLubyte texData[] = {0u, 255u, 0u, 255u};
8216 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
8217 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8218 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8219 ASSERT_GL_NO_ERROR();
8220
8221 // Draw
8222 glUseProgram(program);
8223 GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMembers[0]");
8224 ASSERT_NE(-1, samplerMemberLoc);
8225 glUniform1i(samplerMemberLoc, 0);
8226 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
8227 ASSERT_NE(-1, texCoordLoc);
8228 glUniform2f(texCoordLoc, 0.5f, 0.5f);
8229
8230 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
8231 ASSERT_GL_NO_ERROR();
8232
8233 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
8234 }
8235
8236 // This test covers passing nested structs containing a sampler as a function argument.
TEST_P(GLSLTest,NestedStructsWithSamplersAsFunctionArg)8237 TEST_P(GLSLTest, NestedStructsWithSamplersAsFunctionArg)
8238 {
8239 // Shader failed to compile on Nexus devices. http://anglebug.com/42260860
8240 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
8241
8242 // TODO(anglebug.com/40096747): Failing on ARM-based Apple DTKs.
8243 ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && IsDesktopOpenGL());
8244
8245 const char kFragmentShader[] = R"(precision mediump float;
8246 struct S { sampler2D samplerMember; };
8247 struct T { S nest; };
8248 uniform T uStruct;
8249 uniform vec2 uTexCoord;
8250 vec4 foo2(S structVar)
8251 {
8252 return texture2D(structVar.samplerMember, uTexCoord);
8253 }
8254 vec4 foo(T structVar)
8255 {
8256 return foo2(structVar.nest);
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 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
8285 ASSERT_GL_NO_ERROR();
8286
8287 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
8288 }
8289
8290 // This test covers passing a compound structs containing a sampler as a function argument.
TEST_P(GLSLTest,CompoundStructsWithSamplersAsFunctionArg)8291 TEST_P(GLSLTest, CompoundStructsWithSamplersAsFunctionArg)
8292 {
8293 // Shader failed to compile on Nexus devices. http://anglebug.com/42260860
8294 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
8295
8296 const char kFragmentShader[] = R"(precision mediump float;
8297 struct S { sampler2D samplerMember; bool b; };
8298 uniform S uStruct;
8299 uniform vec2 uTexCoord;
8300 vec4 foo(S structVar)
8301 {
8302 if (structVar.b)
8303 return texture2D(structVar.samplerMember, uTexCoord);
8304 else
8305 return vec4(1, 0, 0, 1);
8306 }
8307 void main()
8308 {
8309 gl_FragColor = foo(uStruct);
8310 })";
8311
8312 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
8313
8314 // Initialize the texture with green.
8315 GLTexture tex;
8316 glActiveTexture(GL_TEXTURE0);
8317 glBindTexture(GL_TEXTURE_2D, tex);
8318 GLubyte texData[] = {0u, 255u, 0u, 255u};
8319 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
8320 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8321 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8322 ASSERT_GL_NO_ERROR();
8323
8324 // Draw
8325 glUseProgram(program);
8326 GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMember");
8327 ASSERT_NE(-1, samplerMemberLoc);
8328 glUniform1i(samplerMemberLoc, 0);
8329 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
8330 ASSERT_NE(-1, texCoordLoc);
8331 glUniform2f(texCoordLoc, 0.5f, 0.5f);
8332 GLint bLoc = glGetUniformLocation(program, "uStruct.b");
8333 ASSERT_NE(-1, bLoc);
8334 glUniform1i(bLoc, 1);
8335
8336 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
8337 ASSERT_GL_NO_ERROR();
8338
8339 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
8340 }
8341
8342 // This test covers passing nested compound structs containing a sampler as a function argument.
TEST_P(GLSLTest,NestedCompoundStructsWithSamplersAsFunctionArg)8343 TEST_P(GLSLTest, NestedCompoundStructsWithSamplersAsFunctionArg)
8344 {
8345 // Shader failed to compile on Nexus devices. http://anglebug.com/42260860
8346 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
8347
8348 // TODO(anglebug.com/40096747): Failing on ARM-based Apple DTKs.
8349 ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && IsDesktopOpenGL());
8350
8351 const char kFragmentShader[] = R"(precision mediump float;
8352 struct S { sampler2D samplerMember; bool b; };
8353 struct T { S nest; bool b; };
8354 uniform T uStruct;
8355 uniform vec2 uTexCoord;
8356 vec4 foo2(S structVar)
8357 {
8358 if (structVar.b)
8359 return texture2D(structVar.samplerMember, uTexCoord);
8360 else
8361 return vec4(1, 0, 0, 1);
8362 }
8363 vec4 foo(T structVar)
8364 {
8365 if (structVar.b)
8366 return foo2(structVar.nest);
8367 else
8368 return vec4(1, 0, 0, 1);
8369 }
8370 void main()
8371 {
8372 gl_FragColor = foo(uStruct);
8373 })";
8374
8375 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
8376
8377 // Initialize the texture with green.
8378 GLTexture tex;
8379 glActiveTexture(GL_TEXTURE0);
8380 glBindTexture(GL_TEXTURE_2D, tex);
8381 GLubyte texData[] = {0u, 255u, 0u, 255u};
8382 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
8383 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8384 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8385 ASSERT_GL_NO_ERROR();
8386
8387 // Draw
8388 glUseProgram(program);
8389 GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.nest.samplerMember");
8390 ASSERT_NE(-1, samplerMemberLoc);
8391 glUniform1i(samplerMemberLoc, 0);
8392 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
8393 ASSERT_NE(-1, texCoordLoc);
8394 glUniform2f(texCoordLoc, 0.5f, 0.5f);
8395
8396 GLint bLoc = glGetUniformLocation(program, "uStruct.b");
8397 ASSERT_NE(-1, bLoc);
8398 glUniform1i(bLoc, 1);
8399
8400 GLint nestbLoc = glGetUniformLocation(program, "uStruct.nest.b");
8401 ASSERT_NE(-1, nestbLoc);
8402 glUniform1i(nestbLoc, 1);
8403
8404 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
8405 ASSERT_GL_NO_ERROR();
8406
8407 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
8408 }
8409
8410 // Same as the prior test but with reordered struct members.
TEST_P(GLSLTest,MoreNestedCompoundStructsWithSamplersAsFunctionArg)8411 TEST_P(GLSLTest, MoreNestedCompoundStructsWithSamplersAsFunctionArg)
8412 {
8413 // Shader failed to compile on Nexus devices. http://anglebug.com/42260860
8414 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
8415
8416 // TODO(anglebug.com/40096747): Failing on ARM-based Apple DTKs.
8417 ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && IsDesktopOpenGL());
8418
8419 const char kFragmentShader[] = R"(precision mediump float;
8420 struct S { bool b; sampler2D samplerMember; };
8421 struct T { bool b; S nest; };
8422 uniform T uStruct;
8423 uniform vec2 uTexCoord;
8424 vec4 foo2(S structVar)
8425 {
8426 if (structVar.b)
8427 return texture2D(structVar.samplerMember, uTexCoord);
8428 else
8429 return vec4(1, 0, 0, 1);
8430 }
8431 vec4 foo(T structVar)
8432 {
8433 if (structVar.b)
8434 return foo2(structVar.nest);
8435 else
8436 return vec4(1, 0, 0, 1);
8437 }
8438 void main()
8439 {
8440 gl_FragColor = foo(uStruct);
8441 })";
8442
8443 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
8444
8445 // Initialize the texture with green.
8446 GLTexture tex;
8447 glActiveTexture(GL_TEXTURE0);
8448 glBindTexture(GL_TEXTURE_2D, tex);
8449 GLubyte texData[] = {0u, 255u, 0u, 255u};
8450 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
8451 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8452 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8453 ASSERT_GL_NO_ERROR();
8454
8455 // Draw
8456 glUseProgram(program);
8457 GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.nest.samplerMember");
8458 ASSERT_NE(-1, samplerMemberLoc);
8459 glUniform1i(samplerMemberLoc, 0);
8460 GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
8461 ASSERT_NE(-1, texCoordLoc);
8462 glUniform2f(texCoordLoc, 0.5f, 0.5f);
8463
8464 GLint bLoc = glGetUniformLocation(program, "uStruct.b");
8465 ASSERT_NE(-1, bLoc);
8466 glUniform1i(bLoc, 1);
8467
8468 GLint nestbLoc = glGetUniformLocation(program, "uStruct.nest.b");
8469 ASSERT_NE(-1, nestbLoc);
8470 glUniform1i(nestbLoc, 1);
8471
8472 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
8473 ASSERT_GL_NO_ERROR();
8474
8475 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
8476 }
8477 // Test that a global variable declared after main() works. This is a regression test for an issue
8478 // in global variable initialization.
TEST_P(WebGLGLSLTest,GlobalVariableDeclaredAfterMain)8479 TEST_P(WebGLGLSLTest, GlobalVariableDeclaredAfterMain)
8480 {
8481 constexpr char kFS[] =
8482 "precision mediump float;\n"
8483 "int getFoo();\n"
8484 "uniform int u_zero;\n"
8485 "void main()\n"
8486 "{\n"
8487 " gl_FragColor = vec4(1, 0, 0, 1);\n"
8488 " if (getFoo() == 0)\n"
8489 " {\n"
8490 " gl_FragColor = vec4(0, 1, 0, 1);\n"
8491 " }\n"
8492 "}\n"
8493 "int foo;\n"
8494 "int getFoo()\n"
8495 "{\n"
8496 " foo = u_zero;\n"
8497 " return foo;\n"
8498 "}\n";
8499
8500 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
8501 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
8502 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8503 }
8504
8505 // Test calling array length() with a "this" expression having side effects inside a loop condition.
8506 // The spec says that sequence operator operands need to run in sequence.
TEST_P(GLSLTest_ES3,ArrayLengthOnExpressionWithSideEffectsInLoopCondition)8507 TEST_P(GLSLTest_ES3, ArrayLengthOnExpressionWithSideEffectsInLoopCondition)
8508 {
8509 // "a" gets doubled three times in the below program.
8510 constexpr char kFS[] = R"(#version 300 es
8511 precision highp float;
8512 out vec4 my_FragColor;
8513 uniform int u_zero;
8514 int a;
8515 int[2] doubleA()
8516 {
8517 a *= 2;
8518 return int[2](a, a);
8519 }
8520 void main()
8521 {
8522 a = u_zero + 1;
8523 for (int i = 0; i < doubleA().length(); ++i)
8524 {}
8525 if (a == 8)
8526 {
8527 my_FragColor = vec4(0, 1, 0, 1);
8528 }
8529 else
8530 {
8531 my_FragColor = vec4(1, 0, 0, 1);
8532 }
8533 })";
8534
8535 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8536 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
8537 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8538 }
8539
8540 // Test calling array length() with a "this" expression having side effects that interact with side
8541 // effects of another operand of the same sequence operator. The spec says that sequence operator
8542 // operands need to run in order from left to right (ESSL 3.00.6 section 5.9).
TEST_P(GLSLTest_ES3,ArrayLengthOnExpressionWithSideEffectsInSequence)8543 TEST_P(GLSLTest_ES3, ArrayLengthOnExpressionWithSideEffectsInSequence)
8544 {
8545 constexpr char kFS[] = R"(#version 300 es
8546 precision highp float;
8547 out vec4 my_FragColor;
8548 uniform int u_zero;
8549 int a;
8550 int[3] doubleA()
8551 {
8552 a *= 2;
8553 return int[3](a, a, a);
8554 }
8555 void main()
8556 {
8557 a = u_zero;
8558 int b = (a++, doubleA().length());
8559 if (b == 3 && a == 2)
8560 {
8561 my_FragColor = vec4(0, 1, 0, 1);
8562 }
8563 else
8564 {
8565 my_FragColor = vec4(1, 0, 0, 1);
8566 }
8567 })";
8568
8569 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8570 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
8571 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8572 }
8573
8574 // Test calling array length() with a "this" expression that also contains a call of array length().
8575 // Both "this" expressions also have side effects.
TEST_P(GLSLTest_ES3,NestedArrayLengthMethodsWithSideEffects)8576 TEST_P(GLSLTest_ES3, NestedArrayLengthMethodsWithSideEffects)
8577 {
8578 constexpr char kFS[] = R"(#version 300 es
8579 precision highp float;
8580 out vec4 my_FragColor;
8581 uniform int u_zero;
8582 int a;
8583 int[3] multiplyA(int multiplier)
8584 {
8585 a *= multiplier;
8586 return int[3](a, a, a);
8587 }
8588 void main()
8589 {
8590 a = u_zero + 1;
8591 int b = multiplyA(multiplyA(2).length()).length();
8592 if (b == 3 && a == 6)
8593 {
8594 my_FragColor = vec4(0, 1, 0, 1);
8595 }
8596 else
8597 {
8598 my_FragColor = vec4(1, 0, 0, 1);
8599 }
8600 })";
8601
8602 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8603 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
8604 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8605 }
8606
8607 // Test calling array length() with a "this" expression having side effects inside an if condition.
8608 // This is an issue if the the side effect can be short circuited.
TEST_P(GLSLTest_ES3,ArrayLengthOnShortCircuitedExpressionWithSideEffectsInIfCondition)8609 TEST_P(GLSLTest_ES3, ArrayLengthOnShortCircuitedExpressionWithSideEffectsInIfCondition)
8610 {
8611 // Bug in the shader translator. http://anglebug.com/42262472
8612 ANGLE_SKIP_TEST_IF(true);
8613
8614 // "a" shouldn't get modified by this shader.
8615 constexpr char kFS[] = R"(#version 300 es
8616 precision highp float;
8617 out vec4 my_FragColor;
8618 uniform int u_zero;
8619 int a;
8620 int[2] doubleA()
8621 {
8622 a *= 2;
8623 return int[2](a, a);
8624 }
8625 void main()
8626 {
8627 a = u_zero + 1;
8628 if (u_zero != 0 && doubleA().length() == 2)
8629 {
8630 ++a;
8631 }
8632 if (a == 1)
8633 {
8634 my_FragColor = vec4(0, 1, 0, 1);
8635 }
8636 else
8637 {
8638 my_FragColor = vec4(1, 0, 0, 1);
8639 }
8640 })";
8641
8642 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8643 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
8644 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8645 }
8646
8647 // Test calling array length() with a "this" expression having side effects in a statement where the
8648 // side effect can be short circuited.
TEST_P(GLSLTest_ES3,ArrayLengthOnShortCircuitedExpressionWithSideEffectsInStatement)8649 TEST_P(GLSLTest_ES3, ArrayLengthOnShortCircuitedExpressionWithSideEffectsInStatement)
8650 {
8651 // Bug in the shader translator. http://anglebug.com/42262472
8652 ANGLE_SKIP_TEST_IF(true);
8653
8654 // "a" shouldn't get modified by this shader.
8655 constexpr char kFS[] = R"(#version 300 es
8656 precision highp float;
8657 out vec4 my_FragColor;
8658 uniform int u_zero;
8659 int a;
8660 int[2] doubleA()
8661 {
8662 a *= 2;
8663 return int[2](a, a);
8664 }
8665 void main()
8666 {
8667 a = u_zero + 1;
8668 bool test = u_zero != 0 && doubleA().length() == 2;
8669 if (a == 1)
8670 {
8671 my_FragColor = vec4(0, 1, 0, 1);
8672 }
8673 else
8674 {
8675 my_FragColor = vec4(1, 0, 0, 1);
8676 }
8677 })";
8678
8679 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8680 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
8681 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8682 }
8683
8684 // Test that array length inside vector constructor works.
TEST_P(GLSLTest_ES3,ArrayLengthInVectorConstructor)8685 TEST_P(GLSLTest_ES3, ArrayLengthInVectorConstructor)
8686 {
8687 const char kVS[] = R"(#version 300 es
8688 precision highp float;
8689 flat out uvec4 v;
8690
8691 int[1] f0()
8692 {
8693 return int[1](1);
8694 }
8695 void main()
8696 {
8697 v = uvec4(vec4(f0().length()));
8698
8699 gl_Position.x = ((gl_VertexID & 1) == 0 ? -1.0 : 1.0);
8700 gl_Position.y = ((gl_VertexID & 2) == 0 ? -1.0 : 1.0);
8701 gl_Position.zw = vec2(0, 1);
8702 })";
8703
8704 const char kFS[] = R"(#version 300 es
8705 precision highp float;
8706 flat in uvec4 v;
8707 out vec4 color;
8708
8709 bool isEq(uint a, float b) { return abs(float(a) - b) < 0.01; }
8710
8711 void main()
8712 {
8713 if (isEq(v[0], 1.) &&
8714 isEq(v[1], 1.) &&
8715 isEq(v[2], 1.) &&
8716 isEq(v[3], 1.))
8717 {
8718 color = vec4(0, 1, 0, 1);
8719 }
8720 else
8721 {
8722 color = vec4(1, 0, 0, 1);
8723 }
8724 })";
8725
8726 ANGLE_GL_PROGRAM(program, kVS, kFS);
8727 glUseProgram(program);
8728 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
8729 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8730 }
8731
8732 // Test that array length inside vector constructor works in complex expression.
TEST_P(GLSLTest_ES3,ArrayLengthInVectorConstructorComplex)8733 TEST_P(GLSLTest_ES3, ArrayLengthInVectorConstructorComplex)
8734 {
8735 const char kVS[] = R"(#version 300 es
8736 precision highp float;
8737 out vec4 v;
8738
8739 int[1] f0()
8740 {
8741 return int[1](1);
8742 }
8743 void main()
8744 {
8745 v = vec4(float(uint(f0().length()) + 1u) / 4.);
8746
8747 gl_Position.x = ((gl_VertexID & 1) == 0 ? -1.0 : 1.0);
8748 gl_Position.y = ((gl_VertexID & 2) == 0 ? -1.0 : 1.0);
8749 gl_Position.zw = vec2(0, 1);
8750 })";
8751
8752 const char kFS[] = R"(#version 300 es
8753 precision highp float;
8754 in vec4 v;
8755 out vec4 color;
8756
8757 bool isEq(float a, float b) { return abs(float(a) - b) < 0.01; }
8758
8759 void main()
8760 {
8761 if (isEq(v[0], 0.5) &&
8762 isEq(v[1], 0.5) &&
8763 isEq(v[2], 0.5) &&
8764 isEq(v[3], 0.5))
8765 {
8766 color = vec4(0, 1, 0, 1);
8767 }
8768 else
8769 {
8770 color = vec4(1, 0, 0, 1);
8771 }
8772 })";
8773
8774 ANGLE_GL_PROGRAM(program, kVS, kFS);
8775 glUseProgram(program);
8776 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
8777 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8778 }
8779
8780 // Test that array length inside matrix constructor works.
TEST_P(GLSLTest_ES3,ArrayLengthInMatrixConstructor)8781 TEST_P(GLSLTest_ES3, ArrayLengthInMatrixConstructor)
8782 {
8783 const char kVS[] = R"(#version 300 es
8784 precision highp float;
8785 out mat2x2 v;
8786
8787 int[1] f0()
8788 {
8789 return int[1](1);
8790 }
8791 void main()
8792 {
8793 v = mat2x2(f0().length());
8794
8795 gl_Position.x = ((gl_VertexID & 1) == 0 ? -1.0 : 1.0);
8796 gl_Position.y = ((gl_VertexID & 2) == 0 ? -1.0 : 1.0);
8797 gl_Position.zw = vec2(0, 1);
8798 })";
8799
8800 const char kFS[] = R"(#version 300 es
8801 precision highp float;
8802 in mat2x2 v;
8803 out vec4 color;
8804
8805 bool isEq(float a, float b) { return abs(a - b) < 0.01; }
8806
8807 void main()
8808 {
8809 if (isEq(v[0][0], 1.) &&
8810 isEq(v[0][1], 0.) &&
8811 isEq(v[1][0], 0.) &&
8812 isEq(v[1][1], 1.))
8813 {
8814 color = vec4(0, 1, 0, 1);
8815 }
8816 else
8817 {
8818 color = vec4(1, 0, 0, 1);
8819 }
8820 })";
8821
8822 ANGLE_GL_PROGRAM(program, kVS, kFS);
8823 glUseProgram(program);
8824 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
8825 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8826 }
8827
8828 // Test that array length inside vector constructor inside matrix constructor works.
TEST_P(GLSLTest_ES3,ArrayLengthInVectorInMatrixConstructor)8829 TEST_P(GLSLTest_ES3, ArrayLengthInVectorInMatrixConstructor)
8830 {
8831 const char kVS[] = R"(#version 300 es
8832 precision highp float;
8833 out mat2x2 v;
8834
8835 int[1] f0()
8836 {
8837 return int[1](1);
8838 }
8839 void main()
8840 {
8841 v = mat2x2(vec2(f0().length()), f0().length(), 0);
8842
8843 gl_Position.x = ((gl_VertexID & 1) == 0 ? -1.0 : 1.0);
8844 gl_Position.y = ((gl_VertexID & 2) == 0 ? -1.0 : 1.0);
8845 gl_Position.zw = vec2(0, 1);
8846 })";
8847
8848 const char kFS[] = R"(#version 300 es
8849 precision highp float;
8850 in mat2x2 v;
8851 out vec4 color;
8852
8853 bool isEq(float a, float b) { return abs(a - b) < 0.01; }
8854
8855 void main()
8856 {
8857 if (isEq(v[0][0], 1.) &&
8858 isEq(v[0][1], 1.) &&
8859 isEq(v[1][0], 1.) &&
8860 isEq(v[1][1], 0.))
8861 {
8862 color = vec4(0, 1, 0, 1);
8863 }
8864 else
8865 {
8866 color = vec4(1, 0, 0, 1);
8867 }
8868 })";
8869
8870 ANGLE_GL_PROGRAM(program, kVS, kFS);
8871 glUseProgram(program);
8872 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
8873 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8874 }
8875
8876 // Test that statements inside switch() get translated to correct HLSL.
TEST_P(GLSLTest_ES3,DifferentStatementsInsideSwitch)8877 TEST_P(GLSLTest_ES3, DifferentStatementsInsideSwitch)
8878 {
8879 constexpr char kFS[] = R"(#version 300 es
8880 precision highp float;
8881 uniform int u;
8882 void main()
8883 {
8884 switch (u)
8885 {
8886 case 0:
8887 ivec2 i;
8888 i.yx;
8889 }
8890 })";
8891
8892 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8893 }
8894
8895 // Test that switch fall-through works correctly.
8896 // This is a regression test for http://anglebug.com/40644631
TEST_P(GLSLTest_ES3,SwitchFallThroughCodeDuplication)8897 TEST_P(GLSLTest_ES3, SwitchFallThroughCodeDuplication)
8898 {
8899 constexpr char kFS[] = R"(#version 300 es
8900 precision highp float;
8901 out vec4 my_FragColor;
8902 uniform int u_zero;
8903
8904 void main()
8905 {
8906 int i = 0;
8907 // switch should fall through both cases.
8908 switch(u_zero)
8909 {
8910 case 0:
8911 i += 1;
8912 case 1:
8913 i += 2;
8914 }
8915 if (i == 3)
8916 {
8917 my_FragColor = vec4(0, 1, 0, 1);
8918 }
8919 else
8920 {
8921 my_FragColor = vec4(1, 0, 0, 1);
8922 }
8923 })";
8924
8925 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8926 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
8927 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8928 }
8929
8930 // Test switch/case where default is last.
TEST_P(GLSLTest_ES3,SwitchWithDefaultAtTheEnd)8931 TEST_P(GLSLTest_ES3, SwitchWithDefaultAtTheEnd)
8932 {
8933 constexpr char kFS[] = R"(#version 300 es
8934
8935 precision highp float;
8936 out vec4 my_FragColor;
8937
8938 uniform int u_zero;
8939
8940 void main()
8941 {
8942 switch (u_zero)
8943 {
8944 case 1:
8945 my_FragColor = vec4(1, 0, 0, 1);
8946 break;
8947 default:
8948 my_FragColor = vec4(0, 1, 0, 1);
8949 }
8950 })";
8951
8952 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8953 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
8954 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8955 }
8956
8957 // Test that a switch statement with an empty block inside as a final statement compiles.
TEST_P(GLSLTest_ES3,SwitchFinalCaseHasEmptyBlock)8958 TEST_P(GLSLTest_ES3, SwitchFinalCaseHasEmptyBlock)
8959 {
8960 constexpr char kFS[] = R"(#version 300 es
8961
8962 precision mediump float;
8963 uniform int i;
8964 void main()
8965 {
8966 switch (i)
8967 {
8968 case 0:
8969 break;
8970 default:
8971 {}
8972 }
8973 })";
8974 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8975 }
8976
8977 // Test that a switch statement with an empty declaration inside as a final statement compiles.
TEST_P(GLSLTest_ES3,SwitchFinalCaseHasEmptyDeclaration)8978 TEST_P(GLSLTest_ES3, SwitchFinalCaseHasEmptyDeclaration)
8979 {
8980 constexpr char kFS[] = R"(#version 300 es
8981
8982 precision mediump float;
8983 uniform int i;
8984 void main()
8985 {
8986 switch (i)
8987 {
8988 case 0:
8989 break;
8990 default:
8991 float;
8992 }
8993 })";
8994 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8995 }
8996
8997 // Test switch/case where break/return statements are within blocks.
TEST_P(GLSLTest_ES3,SwitchBreakOrReturnInsideBlocks)8998 TEST_P(GLSLTest_ES3, SwitchBreakOrReturnInsideBlocks)
8999 {
9000 constexpr char kFS[] = R"(#version 300 es
9001
9002 precision highp float;
9003
9004 uniform int u_zero;
9005 out vec4 my_FragColor;
9006
9007 bool test(int n)
9008 {
9009 switch(n) {
9010 case 0:
9011 {
9012 {
9013 break;
9014 }
9015 }
9016 case 1:
9017 {
9018 return true;
9019 }
9020 case 2:
9021 {
9022 n++;
9023 }
9024 }
9025 return false;
9026 }
9027
9028 void main()
9029 {
9030 my_FragColor = test(u_zero + 1) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
9031 })";
9032
9033 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9034 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
9035 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9036 }
9037
9038 // Test switch/case where a variable is declared inside one of the cases and is accessed by a
9039 // subsequent case.
TEST_P(GLSLTest_ES3,SwitchWithVariableDeclarationInside)9040 TEST_P(GLSLTest_ES3, SwitchWithVariableDeclarationInside)
9041 {
9042 constexpr char kFS[] = R"(#version 300 es
9043
9044 precision highp float;
9045 out vec4 my_FragColor;
9046
9047 uniform int u_zero;
9048
9049 void main()
9050 {
9051 my_FragColor = vec4(1, 0, 0, 1);
9052 switch (u_zero)
9053 {
9054 case 0:
9055 ivec2 i;
9056 i = ivec2(1, 0);
9057 default:
9058 my_FragColor = vec4(0, i[0], 0, 1);
9059 }
9060 })";
9061
9062 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9063 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
9064 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9065 }
9066
9067 // Test nested switch/case where a variable is declared inside one of the cases and is accessed by a
9068 // subsequent case.
TEST_P(GLSLTest_ES3,NestedSwitchWithVariableDeclarationInside)9069 TEST_P(GLSLTest_ES3, NestedSwitchWithVariableDeclarationInside)
9070 {
9071 constexpr char kFS[] = R"(#version 300 es
9072
9073 precision highp float;
9074 out vec4 my_FragColor;
9075
9076 uniform int u_zero;
9077 uniform int u_zero2;
9078
9079 void main()
9080 {
9081 my_FragColor = vec4(1, 0, 0, 1);
9082 switch (u_zero)
9083 {
9084 case 0:
9085 ivec2 i;
9086 i = ivec2(1, 0);
9087 switch (u_zero2)
9088 {
9089 case 0:
9090 int j;
9091 default:
9092 j = 1;
9093 i *= j;
9094 }
9095 default:
9096 my_FragColor = vec4(0, i[0], 0, 1);
9097 }
9098 })";
9099
9100 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9101 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
9102 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9103 }
9104
9105 // Test that an empty switch/case statement is translated in a way that compiles and executes the
9106 // init-statement.
TEST_P(GLSLTest_ES3,EmptySwitch)9107 TEST_P(GLSLTest_ES3, EmptySwitch)
9108 {
9109 constexpr char kFS[] = R"(#version 300 es
9110
9111 precision highp float;
9112
9113 uniform int u_zero;
9114 out vec4 my_FragColor;
9115
9116 void main()
9117 {
9118 int i = u_zero;
9119 switch(++i) {}
9120 my_FragColor = (i == 1) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
9121 })";
9122
9123 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9124 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
9125 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9126 }
9127
9128 // Test that an switch over a constant with mismatching cases works.
TEST_P(GLSLTest_ES3,SwitchWithConstantExpr)9129 TEST_P(GLSLTest_ES3, SwitchWithConstantExpr)
9130 {
9131 constexpr char kFS[] = R"(#version 300 es
9132 precision highp float;
9133 out vec4 color;
9134
9135 void main()
9136 {
9137 float r = 0.;
9138 float g = 1.;
9139 float b = 0.;
9140
9141 switch(10)
9142 {
9143 case 44:
9144 r = 0.5;
9145 case 50:
9146 break;
9147 }
9148
9149 switch(20)
9150 {
9151 case 198:
9152 g = 0.5;
9153 default:
9154 g -= 1.;
9155 break;
9156 }
9157
9158 switch(30)
9159 {
9160 default:
9161 b = 0.5;
9162 case 4:
9163 b += 0.5;
9164 break;
9165 }
9166
9167 color = vec4(r, g, b, 1);
9168 })";
9169
9170 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9171 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
9172 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
9173 }
9174
9175 // Test that basic infinite loops are either rejected or are pruned in WebGL
TEST_P(WebGL2GLSLTest,BasicInfiniteLoop)9176 TEST_P(WebGL2GLSLTest, BasicInfiniteLoop)
9177 {
9178 constexpr char kFS[] = R"(#version 300 es
9179 precision highp float;
9180 uniform uint zero;
9181 out vec4 color;
9182
9183 bool globalConstantVariable = true;
9184
9185 float f()
9186 {
9187 // Should not be pruned
9188 while (true)
9189 {
9190 // Should not be pruned
9191 for (int i = 0; true; ++i)
9192 {
9193 if (zero < 10u)
9194 {
9195 switch (zero)
9196 {
9197 case 0u:
9198 // Loops should be pruned because of this `return`.
9199 return 0.7;
9200 default:
9201 break;
9202 }
9203 }
9204 }
9205 }
9206 }
9207
9208 void main()
9209 {
9210 float r = 0.;
9211 float g = 1.;
9212 float b = 0.;
9213
9214 bool localConstantVariable = true;
9215 bool localVariable = true;
9216
9217 // Should be pruned
9218 while (true)
9219 {
9220 r += 0.1;
9221 if (r > 0.)
9222 {
9223 continue;
9224 }
9225 }
9226
9227 if (zero != 0u)
9228 {
9229 localVariable = false;
9230 }
9231
9232 // Should be pruned
9233 while (localConstantVariable)
9234 {
9235 g -= 0.1;
9236 }
9237
9238 // Should not be pruned
9239 while (localConstantVariable)
9240 {
9241 b += 0.3;
9242
9243 if (g > 0.4) { break; }
9244 }
9245
9246 // Should be pruned
9247 for (; globalConstantVariable; )
9248 {
9249 g -= 0.1;
9250
9251 switch (zero)
9252 {
9253 case 0u:
9254 r = 0.4;
9255 break;
9256 default:
9257 r = 0.2;
9258 break;
9259 }
9260 }
9261
9262 // Should not be pruned
9263 while (localVariable)
9264 {
9265 b += 0.2;
9266 localVariable = !localVariable;
9267 }
9268
9269 r = f();
9270
9271 color = vec4(r, g, b, 1);
9272 })";
9273
9274 if (getEGLWindow()->isFeatureEnabled(Feature::RejectWebglShadersWithUndefinedBehavior))
9275 {
9276 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
9277 EXPECT_EQ(0u, shader);
9278 }
9279 else
9280 {
9281 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9282 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
9283 EXPECT_PIXEL_NEAR(0, 0, 178, 255, 127, 255, 1);
9284 }
9285 }
9286
9287 // Test that while(true) loops with break/return are not rejected
TEST_P(WebGL2GLSLTest,NotInfiniteLoop)9288 TEST_P(WebGL2GLSLTest, NotInfiniteLoop)
9289 {
9290 constexpr char kFS[] = R"(#version 300 es
9291 precision highp float;
9292 uniform uint zero;
9293 out vec4 color;
9294
9295 void main()
9296 {
9297 float r = 0.;
9298 float g = 1.;
9299 float b = 0.;
9300
9301 while (true)
9302 {
9303 r += 0.1;
9304 if (r > 0.4)
9305 {
9306 break;
9307 }
9308 }
9309
9310 for (;;)
9311 {
9312 g -= 0.1;
9313
9314 switch (zero)
9315 {
9316 case 0u:
9317 g -= 0.6;
9318 color = vec4(r, g, b, 1);
9319 return;
9320 default:
9321 r = 0.2;
9322 break;
9323 }
9324 }
9325 })";
9326
9327 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9328 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
9329 EXPECT_PIXEL_NEAR(0, 0, 127, 76, 0, 255, 1);
9330 }
9331
9332 // Test that a constant struct inside an expression is handled correctly.
TEST_P(GLSLTest_ES3,ConstStructInsideExpression)9333 TEST_P(GLSLTest_ES3, ConstStructInsideExpression)
9334 {
9335 // Incorrect output color was seen on Android. http://anglebug.com/42260946
9336 ANGLE_SKIP_TEST_IF(IsAndroid() && !IsNVIDIA() && IsOpenGLES());
9337
9338 constexpr char kFS[] = R"(#version 300 es
9339
9340 precision highp float;
9341 out vec4 my_FragColor;
9342
9343 uniform float u_zero;
9344
9345 struct S
9346 {
9347 float field;
9348 };
9349
9350 void main()
9351 {
9352 const S constS = S(1.0);
9353 S nonConstS = constS;
9354 nonConstS.field = u_zero;
9355 bool fail = (constS == nonConstS);
9356 my_FragColor = vec4(0, 1, 0, 1);
9357 if (fail)
9358 {
9359 my_FragColor = vec4(1, 0, 0, 1);
9360 }
9361 })";
9362
9363 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9364 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
9365 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9366 }
9367
9368 // Test that a varying struct that's defined as a part of the declaration is handled correctly.
TEST_P(GLSLTest_ES3,VaryingStructWithInlineDefinition)9369 TEST_P(GLSLTest_ES3, VaryingStructWithInlineDefinition)
9370 {
9371 constexpr char kVS[] = R"(#version 300 es
9372 in vec4 inputAttribute;
9373
9374 flat out struct S
9375 {
9376 int field;
9377 } v_s;
9378
9379 void main()
9380 {
9381 v_s.field = 1;
9382 gl_Position = inputAttribute;
9383 })";
9384
9385 constexpr char kFS[] = R"(#version 300 es
9386
9387 precision highp float;
9388 out vec4 my_FragColor;
9389
9390 flat in struct S
9391 {
9392 int field;
9393 } v_s;
9394
9395 void main()
9396 {
9397 bool success = (v_s.field == 1);
9398 my_FragColor = vec4(1, 0, 0, 1);
9399 if (success)
9400 {
9401 my_FragColor = vec4(0, 1, 0, 1);
9402 }
9403 })";
9404
9405 ANGLE_GL_PROGRAM(program, kVS, kFS);
9406 drawQuad(program, "inputAttribute", 0.5f);
9407 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9408 }
9409
9410 // Test that multi variables struct should not crash in separated struct expressions.
TEST_P(GLSLTest_ES3,VaryingStructWithInlineDefinition2)9411 TEST_P(GLSLTest_ES3, VaryingStructWithInlineDefinition2)
9412 {
9413 constexpr char kVS[] = R"(#version 300 es
9414 in vec4 inputAttribute;
9415 flat out struct A
9416 {
9417 int a;
9418 } z1, z2;
9419 void main()
9420 {
9421 z1.a = 1;
9422 z2.a = 2;
9423 gl_Position = inputAttribute;
9424 })";
9425 constexpr char kFS[] = R"(#version 300 es
9426 precision highp float;
9427 out vec4 my_FragColor;
9428 flat in struct A
9429 {
9430 int a;
9431 } z1, z2;
9432 void main()
9433 {
9434 bool success = (z1.a == 1 && z2.a == 2);
9435 my_FragColor = vec4(1, 0, 0, 1);
9436 if (success)
9437 {
9438 my_FragColor = vec4(0, 1, 0, 1);
9439 }
9440 })";
9441
9442 ANGLE_GL_PROGRAM(program, kVS, kFS);
9443 drawQuad(program.get(), "inputAttribute", 0.5f);
9444 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9445 }
9446
9447 // Test that a varying anonymous struct that is defined as a part of the declaration is handled
9448 // correctly.
TEST_P(GLSLTest_ES3,VaryingAnonymousStructWithInlineDefinition)9449 TEST_P(GLSLTest_ES3, VaryingAnonymousStructWithInlineDefinition)
9450 {
9451 constexpr char kVS[] = R"(#version 300 es
9452 in vec4 inputAttribute;
9453 flat out struct
9454 {
9455 int field;
9456 } v_s;
9457
9458 void main()
9459 {
9460 v_s.field = 1;
9461 gl_Position = inputAttribute;
9462 })";
9463
9464 constexpr char kFS[] = R"(#version 300 es
9465 precision highp float;
9466 out vec4 my_FragColor;
9467 flat in struct
9468 {
9469 int field;
9470 } v_s;
9471 void main()
9472 {
9473 bool success = (v_s.field == 1);
9474 my_FragColor = vec4(1, 0, 0, 1);
9475 if (success)
9476 {
9477 my_FragColor = vec4(0, 1, 0, 1);
9478 }
9479 })";
9480 ANGLE_GL_PROGRAM(program, kVS, kFS);
9481 drawQuad(program.get(), "inputAttribute", 0.5f);
9482 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9483 }
9484
9485 // Test that a varying anonymous structs that are defined as a part of the declaration is handled
9486 // correctly.
TEST_P(GLSLTest_ES3,VaryingAnonymousStructWithInlineDefinition2)9487 TEST_P(GLSLTest_ES3, VaryingAnonymousStructWithInlineDefinition2)
9488 {
9489 constexpr char kVS[] = R"(#version 300 es
9490 in vec4 inputAttribute;
9491 flat out struct
9492 {
9493 int field;
9494 } v_s0, v_s1;
9495 void main()
9496 {
9497 v_s0.field = 1;
9498 v_s1.field = 2;
9499 gl_Position = inputAttribute;
9500 })";
9501 constexpr char kFS[] = R"(#version 300 es
9502 precision highp float;
9503 out vec4 my_FragColor;
9504 flat in struct
9505 {
9506 int field;
9507 } v_s0, v_s1;
9508 void main()
9509 {
9510 bool success = (v_s0.field == 1 && v_s1.field == 2);
9511 my_FragColor = vec4(1, 0, 0, 1);
9512 if (success)
9513 {
9514 my_FragColor = vec4(0, 1, 0, 1);
9515 }
9516 })";
9517 ANGLE_GL_PROGRAM(program, kVS, kFS);
9518 drawQuad(program.get(), "inputAttribute", 0.5f);
9519 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9520 }
9521
9522 // Test that a varying anonymous structs that are defined as a part of the declaration is handled
9523 // in a specific way. Highlights ambiguity of ES "Chapter 9. Shader Interface Matching":
9524 // "When linking shaders, the type of declared vertex outputs and fragment inputs with the same
9525 // name must match"
TEST_P(GLSLTest_ES3,VaryingAnonymousStructWithInlineDefinition3)9526 TEST_P(GLSLTest_ES3, VaryingAnonymousStructWithInlineDefinition3)
9527 {
9528 constexpr char kVS[] = R"(#version 300 es
9529 in vec4 inputAttribute;
9530 flat out struct
9531 {
9532 int field;
9533 } v_s0;
9534 flat out struct
9535 {
9536 int field;
9537 } v_s1;
9538 flat out struct
9539 {
9540 int field;
9541 } v_s2, v_s3;
9542 void main()
9543 {
9544 v_s0.field = 1;
9545 v_s1.field = 2;
9546 v_s2.field = 3;
9547 v_s3.field = 4;
9548 gl_Position = inputAttribute;
9549 })";
9550
9551 constexpr char kFS[] = R"(#version 300 es
9552 precision highp float;
9553 out vec4 my_FragColor;
9554 flat in struct
9555 {
9556 int field;
9557 } v_s0, v_s1, v_s2, v_s3;
9558 void main()
9559 {
9560 bool success = v_s0.field == 1 && v_s1.field == 2 && v_s2.field == 3 && v_s3.field == 4;
9561 my_FragColor = vec4(1, 0, 0, 1);
9562 if (success)
9563 {
9564 my_FragColor = vec4(0, 1, 0, 1);
9565 }
9566 })";
9567
9568 ANGLE_GL_PROGRAM(program, kVS, kFS);
9569 drawQuad(program.get(), "inputAttribute", 0.5f);
9570 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9571 }
9572
9573 // Test that a varying anonymous structs can be compared for equality.
TEST_P(GLSLTest_ES3,VaryingAnonymousStructEquality)9574 TEST_P(GLSLTest_ES3, VaryingAnonymousStructEquality)
9575 {
9576 constexpr char kVS[] = R"(#version 300 es
9577 in vec4 inputAttribute;
9578 flat out struct
9579 {
9580 int field;
9581 } v_s0;
9582 flat out struct
9583 {
9584 int field;
9585 } v_s1;
9586 flat out struct
9587 {
9588 int field;
9589 } v_s2, v_s3;
9590
9591 void main()
9592 {
9593 v_s0.field = 1;
9594 v_s1.field = 2;
9595 v_s2.field = 3;
9596 v_s3.field = 4;
9597 gl_Position = inputAttribute;
9598 })";
9599
9600 constexpr char kFS[] = R"(#version 300 es
9601 precision highp float;
9602 out vec4 my_FragColor;
9603 flat in struct
9604 {
9605 int field;
9606 } v_s0, v_s1, v_s2, v_s3;
9607 void main()
9608 {
9609 bool success = v_s0 != v_s1 && v_s0 != v_s2 && v_s0 != v_s3 && v_s1 != v_s2 && v_s1 != v_s3 && v_s2 != v_s3;
9610 success = success && v_s0.field == 1 && v_s1.field == 2 && v_s2.field == 3 && v_s3.field == 4;
9611 my_FragColor = vec4(1, 0, 0, 1);
9612 if (success)
9613 {
9614 my_FragColor = vec4(0, 1, 0, 1);
9615 }
9616 })";
9617
9618 ANGLE_GL_PROGRAM(program, kVS, kFS);
9619 drawQuad(program.get(), "inputAttribute", 0.5f);
9620 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9621 }
9622
9623 // Test mismatched precision in varying is handled correctly.
TEST_P(GLSLTest_ES3,MismatchPrecisionFloat)9624 TEST_P(GLSLTest_ES3, MismatchPrecisionFloat)
9625 {
9626 constexpr char kVS[] = R"(#version 300 es
9627 in vec4 position;
9628 uniform highp float inVal;
9629 out highp float myVarying;
9630
9631 void main()
9632 {
9633 myVarying = inVal;
9634 gl_Position = position;
9635 })";
9636
9637 constexpr char kFS[] = R"(#version 300 es
9638 precision highp float;
9639 out vec4 my_FragColor;
9640 in mediump float myVarying;
9641
9642 void main()
9643 {
9644 my_FragColor = vec4(1, 0, 0, 1);
9645 if (myVarying > 1.0)
9646 {
9647 my_FragColor = vec4(0, 1, 0, 1);
9648 }
9649 })";
9650
9651 ANGLE_GL_PROGRAM(program, kVS, kFS);
9652
9653 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
9654 glClear(GL_COLOR_BUFFER_BIT);
9655 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
9656
9657 glUseProgram(program);
9658 GLint positionLocation = glGetAttribLocation(program, "position");
9659 std::array<Vector3, 6> quadVertices = GetQuadVertices();
9660 for (Vector3 &vertex : quadVertices)
9661 {
9662 vertex.z() = 0.5f;
9663 }
9664 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
9665 glEnableVertexAttribArray(positionLocation);
9666
9667 GLint inValLoc = glGetUniformLocation(program, "inVal");
9668 ASSERT_NE(-1, inValLoc);
9669 glUniform1f(inValLoc, static_cast<GLfloat>(1.003));
9670
9671 glDrawArrays(GL_TRIANGLES, 0, 6);
9672 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9673 }
9674
9675 // Test mismatched precision in varying is handled correctly.
TEST_P(GLSLTest_ES3,MismatchPrecisionlowpFloat)9676 TEST_P(GLSLTest_ES3, MismatchPrecisionlowpFloat)
9677 {
9678 // Note: SPIRV only has relaxed precision so both lowp and mediump turn into "relaxed
9679 // precision", thus this is the same test as MismatchPrecisionFloat but including it for
9680 // completeness in case something changes.
9681 constexpr char kVS[] = R"(#version 300 es
9682 in vec4 position;
9683 uniform highp float inVal;
9684 out highp float myVarying;
9685
9686 void main()
9687 {
9688 myVarying = inVal;
9689 gl_Position = position;
9690 })";
9691
9692 constexpr char kFS[] = R"(#version 300 es
9693 precision highp float;
9694 out vec4 my_FragColor;
9695 in lowp float myVarying;
9696
9697 void main()
9698 {
9699 my_FragColor = vec4(1, 0, 0, 1);
9700 if (myVarying > 1.0)
9701 {
9702 my_FragColor = vec4(0, 1, 0, 1);
9703 }
9704 })";
9705
9706 ANGLE_GL_PROGRAM(program, kVS, kFS);
9707
9708 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
9709 glClear(GL_COLOR_BUFFER_BIT);
9710 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
9711
9712 glUseProgram(program);
9713 GLint positionLocation = glGetAttribLocation(program, "position");
9714 std::array<Vector3, 6> quadVertices = GetQuadVertices();
9715 for (Vector3 &vertex : quadVertices)
9716 {
9717 vertex.z() = 0.5f;
9718 }
9719 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
9720 glEnableVertexAttribArray(positionLocation);
9721
9722 GLint inValLoc = glGetUniformLocation(program, "inVal");
9723 ASSERT_NE(-1, inValLoc);
9724 glUniform1f(inValLoc, static_cast<GLfloat>(1.003));
9725
9726 glDrawArrays(GL_TRIANGLES, 0, 6);
9727 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9728 }
9729
9730 // Test mismatched precision in varying is handled correctly.
TEST_P(GLSLTest_ES3,MismatchPrecisionVec2UnusedVarying)9731 TEST_P(GLSLTest_ES3, MismatchPrecisionVec2UnusedVarying)
9732 {
9733 constexpr char kVS[] = R"(#version 300 es
9734 in vec2 position;
9735 uniform highp float inVal;
9736 out highp float myVarying;
9737 out highp vec2 texCoord;
9738
9739 void main()
9740 {
9741 myVarying = inVal;
9742 gl_Position = vec4(position, 0, 1);
9743 texCoord = position * 0.5 + vec2(0.5);
9744 })";
9745
9746 constexpr char kFS[] = R"(#version 300 es
9747 precision highp float;
9748 out vec4 my_FragColor;
9749 in mediump float myVarying;
9750 in mediump vec2 texCoord;
9751
9752 void main()
9753 {
9754 my_FragColor = vec4(1, 0, 0, 1);
9755 if (myVarying > 1.0)
9756 {
9757 my_FragColor = vec4(0, 1, 0, 1);
9758 }
9759 })";
9760
9761 ANGLE_GL_PROGRAM(program, kVS, kFS);
9762
9763 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
9764 glClear(GL_COLOR_BUFFER_BIT);
9765 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
9766
9767 glUseProgram(program);
9768 GLint positionLocation = glGetAttribLocation(program, "position");
9769 std::array<Vector3, 6> quadVertices = GetQuadVertices();
9770 for (Vector3 &vertex : quadVertices)
9771 {
9772 vertex.z() = 0.5f;
9773 }
9774 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
9775 glEnableVertexAttribArray(positionLocation);
9776
9777 GLint inValLoc = glGetUniformLocation(program, "inVal");
9778 ASSERT_NE(-1, inValLoc);
9779 glUniform1f(inValLoc, static_cast<GLfloat>(1.003));
9780
9781 glDrawArrays(GL_TRIANGLES, 0, 6);
9782 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9783 }
9784
9785 // Test mismatched precision in varying is handled correctly.
TEST_P(GLSLTest_ES3,MismatchPrecisionMedToHigh)9786 TEST_P(GLSLTest_ES3, MismatchPrecisionMedToHigh)
9787 {
9788 constexpr char kVS[] = R"(#version 300 es
9789 in vec2 position;
9790 uniform highp float inVal;
9791 out mediump float myVarying;
9792
9793 void main()
9794 {
9795 myVarying = inVal;
9796 gl_Position = vec4(position, 0, 1);
9797 })";
9798
9799 constexpr char kFS[] = R"(#version 300 es
9800 precision highp float;
9801 out vec4 my_FragColor;
9802 in highp float myVarying;
9803
9804 void main()
9805 {
9806 my_FragColor = vec4(1, 0, 0, 1);
9807 if (myVarying > 1.0)
9808 {
9809 my_FragColor = vec4(0, 1, 0, 1);
9810 }
9811 })";
9812
9813 ANGLE_GL_PROGRAM(program, kVS, kFS);
9814
9815 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
9816 glClear(GL_COLOR_BUFFER_BIT);
9817 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
9818
9819 glUseProgram(program);
9820 GLint positionLocation = glGetAttribLocation(program, "position");
9821 std::array<Vector3, 6> quadVertices = GetQuadVertices();
9822 for (Vector3 &vertex : quadVertices)
9823 {
9824 vertex.z() = 0.5f;
9825 }
9826 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
9827 glEnableVertexAttribArray(positionLocation);
9828
9829 GLint inValLoc = glGetUniformLocation(program, "inVal");
9830 ASSERT_NE(-1, inValLoc);
9831 glUniform1f(inValLoc, static_cast<GLfloat>(1.003));
9832
9833 glDrawArrays(GL_TRIANGLES, 0, 6);
9834 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9835 }
9836
9837 // Test vector/scalar arithmetic (in this case multiplication and addition).
TEST_P(GLSLTest,VectorScalarMultiplyAndAddInLoop)9838 TEST_P(GLSLTest, VectorScalarMultiplyAndAddInLoop)
9839 {
9840 constexpr char kFS[] = R"(precision mediump float;
9841
9842 void main() {
9843 gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
9844 for (int i = 0; i < 2; i++)
9845 {
9846 gl_FragColor += (2.0 * gl_FragCoord.x);
9847 }
9848 if (gl_FragColor.g == gl_FragColor.r &&
9849 gl_FragColor.b == gl_FragColor.r &&
9850 gl_FragColor.a == gl_FragColor.r)
9851 {
9852 gl_FragColor = vec4(0, 1, 0, 1);
9853 }
9854 })";
9855
9856 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
9857 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
9858 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9859 }
9860
9861 // Test vector/scalar arithmetic (in this case compound division and addition).
TEST_P(GLSLTest,VectorScalarDivideAndAddInLoop)9862 TEST_P(GLSLTest, VectorScalarDivideAndAddInLoop)
9863 {
9864 constexpr char kFS[] = R"(precision mediump float;
9865
9866 void main() {
9867 gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
9868 for (int i = 0; i < 2; i++)
9869 {
9870 float x = gl_FragCoord.x;
9871 gl_FragColor = gl_FragColor + (x /= 2.0);
9872 }
9873 if (gl_FragColor.g == gl_FragColor.r &&
9874 gl_FragColor.b == gl_FragColor.r &&
9875 gl_FragColor.a == gl_FragColor.r)
9876 {
9877 gl_FragColor = vec4(0, 1, 0, 1);
9878 }
9879 })";
9880
9881 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
9882 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
9883 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9884 }
9885
9886 // Test a fuzzer-discovered bug with the VectorizeVectorScalarArithmetic transformation.
TEST_P(GLSLTest,VectorScalarArithmeticWithSideEffectInLoop)9887 TEST_P(GLSLTest, VectorScalarArithmeticWithSideEffectInLoop)
9888 {
9889 // The VectorizeVectorScalarArithmetic transformation was generating invalid code in the past
9890 // (notice how sbcd references i outside the for loop. The loop condition doesn't look right
9891 // either):
9892 //
9893 // #version 450
9894 // void main(){
9895 // (gl_Position = vec4(0.0, 0.0, 0.0, 0.0));
9896 // mat3 _utmp = mat3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
9897 // vec3 _ures = vec3(0.0, 0.0, 0.0);
9898 // vec3 sbcd = vec3(_ures[_ui]);
9899 // for (int _ui = 0; (_ures[((_utmp[_ui] += (((sbcd *= _ures[_ui]), (_ures[_ui] = sbcd.x)),
9900 // sbcd)), _ui)], (_ui < 7)); )
9901 // {
9902 // }
9903 // }
9904
9905 constexpr char kVS[] = R"(
9906 void main()
9907 {
9908 mat3 tmp;
9909 vec3 res;
9910 for(int i; res[tmp[i]+=res[i]*=res[i],i],i<7;);
9911 })";
9912
9913 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
9914
9915 const char *sourceArray[1] = {kVS};
9916 GLint lengths[1] = {static_cast<GLint>(sizeof(kVS) - 1)};
9917 glShaderSource(shader, 1, sourceArray, lengths);
9918 glCompileShader(shader);
9919
9920 GLint compileResult;
9921 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
9922 EXPECT_NE(compileResult, 0);
9923 }
9924
9925 // Test that packing of excessive 3-column variables does not overflow the count of 3-column
9926 // variables in VariablePacker
TEST_P(WebGL2GLSLTest,ExcessiveMat3UniformPacking)9927 TEST_P(WebGL2GLSLTest, ExcessiveMat3UniformPacking)
9928 {
9929 std::ostringstream srcStream;
9930
9931 srcStream << "#version 300 es\n";
9932 srcStream << "precision mediump float;\n";
9933 srcStream << "out vec4 finalColor;\n";
9934 srcStream << "in vec4 color;\n";
9935 srcStream << "uniform mat4 r[254];\n";
9936
9937 srcStream << "uniform mat3 ";
9938 constexpr size_t kNumUniforms = 10000;
9939 for (size_t i = 0; i < kNumUniforms; ++i)
9940 {
9941 if (i > 0)
9942 {
9943 srcStream << ", ";
9944 }
9945 srcStream << "m3a_" << i << "[256]";
9946 }
9947 srcStream << ";\n";
9948
9949 srcStream << "void main(void) { finalColor = color; }\n";
9950 std::string src = std::move(srcStream).str();
9951
9952 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
9953
9954 const char *sourceArray[1] = {src.c_str()};
9955 GLint lengths[1] = {static_cast<GLint>(src.length())};
9956 glShaderSource(shader, 1, sourceArray, lengths);
9957 glCompileShader(shader);
9958
9959 GLint compileResult;
9960 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
9961 EXPECT_EQ(compileResult, 0);
9962 }
9963
9964 // Test that a varying with a flat qualifier that is used as an operand of a folded ternary operator
9965 // is handled correctly.
TEST_P(GLSLTest_ES3,FlatVaryingUsedInFoldedTernary)9966 TEST_P(GLSLTest_ES3, FlatVaryingUsedInFoldedTernary)
9967 {
9968 constexpr char kVS[] = R"(#version 300 es
9969
9970 in vec4 inputAttribute;
9971
9972 flat out int v;
9973
9974 void main()
9975 {
9976 v = 1;
9977 gl_Position = inputAttribute;
9978 })";
9979
9980 constexpr char kFS[] = R"(#version 300 es
9981
9982 precision highp float;
9983 out vec4 my_FragColor;
9984
9985 flat in int v;
9986
9987 void main()
9988 {
9989 my_FragColor = vec4(0, (true ? v : 0), 0, 1);
9990 })";
9991
9992 ANGLE_GL_PROGRAM(program, kVS, kFS);
9993 drawQuad(program, "inputAttribute", 0.5f);
9994 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9995 }
9996
9997 // Verify that the link error message from last link failure is cleared when the new link is
9998 // finished.
TEST_P(GLSLTest,ClearLinkErrorLog)9999 TEST_P(GLSLTest, ClearLinkErrorLog)
10000 {
10001 constexpr char kVS[] = R"(attribute vec4 vert_in;
10002 varying vec4 vert_out;
10003 void main()
10004 {
10005 gl_Position = vert_in;
10006 vert_out = vert_in;
10007 })";
10008
10009 constexpr char kFS[] = R"(precision mediump float;
10010 varying vec4 frag_in;
10011 void main()
10012 {
10013 gl_FragColor = frag_in;
10014 })";
10015
10016 GLuint vs = CompileShader(GL_VERTEX_SHADER, kVS);
10017 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
10018
10019 GLuint program = glCreateProgram();
10020
10021 // The first time the program link fails because of lack of fragment shader.
10022 glAttachShader(program, vs);
10023 glLinkProgram(program);
10024 GLint linkStatus = GL_TRUE;
10025 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
10026 ASSERT_FALSE(linkStatus);
10027
10028 const std::string lackOfFragmentShader = QueryErrorMessage(program);
10029 EXPECT_TRUE(lackOfFragmentShader != "");
10030
10031 // The second time the program link fails because of the mismatch of the varying types.
10032 glAttachShader(program, fs);
10033 glLinkProgram(program);
10034 linkStatus = GL_TRUE;
10035 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
10036 ASSERT_FALSE(linkStatus);
10037
10038 const std::string varyingTypeMismatch = QueryErrorMessage(program);
10039 EXPECT_TRUE(varyingTypeMismatch != "");
10040
10041 EXPECT_EQ(std::string::npos, varyingTypeMismatch.find(lackOfFragmentShader));
10042
10043 glDetachShader(program, vs);
10044 glDetachShader(program, fs);
10045 glDeleteShader(vs);
10046 glDeleteShader(fs);
10047 glDeleteProgram(program);
10048
10049 ASSERT_GL_NO_ERROR();
10050 }
10051
10052 // Verify that a valid program still draws correctly after a shader link error
TEST_P(GLSLTest,DrawAfterShaderLinkError)10053 TEST_P(GLSLTest, DrawAfterShaderLinkError)
10054 {
10055 constexpr char kVS[] = R"(attribute vec4 position;
10056 varying vec4 vColor;
10057 void main()
10058 {
10059 vColor = vec4(0.0, 1.0, 0.0, 1.0);
10060 gl_Position = position;
10061 })";
10062 constexpr char kFS[] = R"(precision mediump float;
10063 varying vec4 vColor;
10064 void main()
10065 {
10066 gl_FragColor = vColor;
10067 })";
10068 constexpr char kBadFS[] = R"(WILL NOT COMPILE;)";
10069
10070 GLuint fsBad = glCreateShader(GL_FRAGMENT_SHADER);
10071
10072 // Create bad fragment shader
10073 {
10074 const char *sourceArray[1] = {kBadFS};
10075 glShaderSource(fsBad, 1, sourceArray, nullptr);
10076 glCompileShader(fsBad);
10077
10078 GLint compileResult;
10079 glGetShaderiv(fsBad, GL_COMPILE_STATUS, &compileResult);
10080 ASSERT_FALSE(compileResult);
10081 }
10082
10083 ANGLE_GL_PROGRAM(program, kVS, kFS);
10084 GLuint fs = GetProgramShader(program, GL_FRAGMENT_SHADER);
10085
10086 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
10087 glClear(GL_COLOR_BUFFER_BIT);
10088 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
10089
10090 glUseProgram(program);
10091 GLint positionLocation = glGetAttribLocation(program, "position");
10092 std::array<Vector3, 6> quadVertices = GetQuadVertices();
10093 for (Vector3 &vertex : quadVertices)
10094 {
10095 vertex.z() = 0.5f;
10096 }
10097 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
10098 glEnableVertexAttribArray(positionLocation);
10099 glDrawArrays(GL_TRIANGLES, 0, 6);
10100 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10101
10102 glDetachShader(program, fs);
10103 glAttachShader(program, fsBad);
10104 glLinkProgram(program);
10105 GLint linkStatus = GL_TRUE;
10106 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
10107 ASSERT_FALSE(linkStatus);
10108
10109 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
10110 glClear(GL_COLOR_BUFFER_BIT);
10111 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
10112
10113 glDrawArrays(GL_TRIANGLES, 0, 6);
10114 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10115 }
10116
10117 // Validate error messages when the link mismatch occurs on the type of a non-struct varying.
TEST_P(GLSLTest,ErrorMessageOfVaryingMismatch)10118 TEST_P(GLSLTest, ErrorMessageOfVaryingMismatch)
10119 {
10120 constexpr char kVS[] = R"(attribute vec4 inputAttribute;
10121 varying vec4 vertex_out;
10122 void main()
10123 {
10124 vertex_out = inputAttribute;
10125 gl_Position = inputAttribute;
10126 })";
10127
10128 constexpr char kFS[] = R"(precision mediump float;
10129 varying float vertex_out;
10130 void main()
10131 {
10132 gl_FragColor = vec4(vertex_out, 0.0, 0.0, 1.0);
10133 })";
10134
10135 validateComponentsInErrorMessage(kVS, kFS, "Types", "varying 'vertex_out'");
10136 }
10137
10138 // Validate error messages when the link mismatch occurs on the name of a varying field.
TEST_P(GLSLTest_ES3,ErrorMessageOfVaryingStructFieldNameMismatch)10139 TEST_P(GLSLTest_ES3, ErrorMessageOfVaryingStructFieldNameMismatch)
10140 {
10141 constexpr char kVS[] = R"(#version 300 es
10142 in vec4 inputAttribute;
10143 struct S {
10144 float val1;
10145 vec4 val2;
10146 };
10147 out S vertex_out;
10148 void main()
10149 {
10150 vertex_out.val2 = inputAttribute;
10151 vertex_out.val1 = inputAttribute[0];
10152 gl_Position = inputAttribute;
10153 })";
10154
10155 constexpr char kFS[] = R"(#version 300 es
10156 precision mediump float;
10157 struct S {
10158 float val1;
10159 vec4 val3;
10160 };
10161 in S vertex_out;
10162 layout (location = 0) out vec4 frag_out;
10163 void main()
10164 {
10165 frag_out = vec4(vertex_out.val1, 0.0, 0.0, 1.0);
10166 })";
10167
10168 validateComponentsInErrorMessage(kVS, kFS, "Field names", "varying 'vertex_out'");
10169 }
10170
10171 // Validate error messages when the link mismatch occurs on the type of a varying field.
TEST_P(GLSLTest_ES3,ErrorMessageOfVaryingStructFieldMismatch)10172 TEST_P(GLSLTest_ES3, ErrorMessageOfVaryingStructFieldMismatch)
10173 {
10174 constexpr char kVS[] = R"(#version 300 es
10175 in vec4 inputAttribute;
10176 struct S {
10177 float val1;
10178 vec4 val2;
10179 };
10180 out S vertex_out;
10181 void main()
10182 {
10183 vertex_out.val2 = inputAttribute;
10184 vertex_out.val1 = inputAttribute[0];
10185 gl_Position = inputAttribute;
10186 })";
10187
10188 constexpr char kFS[] = R"(#version 300 es
10189 precision mediump float;
10190 struct S {
10191 float val1;
10192 vec2 val2;
10193 };
10194 in S vertex_out;
10195 layout (location = 0) out vec4 frag_out;
10196 void main()
10197 {
10198 frag_out = vec4(vertex_out.val1, 0.0, 0.0, 1.0);
10199 })";
10200
10201 validateComponentsInErrorMessage(kVS, kFS, "Types",
10202 "varying 'vertex_out' member 'vertex_out.val2'");
10203 }
10204
10205 // Validate error messages when the link mismatch occurs on the name of a struct member of a uniform
10206 // field.
TEST_P(GLSLTest,ErrorMessageOfLinkUniformStructFieldNameMismatch)10207 TEST_P(GLSLTest, ErrorMessageOfLinkUniformStructFieldNameMismatch)
10208 {
10209 constexpr char kVS[] = R"(
10210 struct T
10211 {
10212 vec2 t1;
10213 vec3 t2;
10214 };
10215 struct S {
10216 T val1;
10217 vec4 val2;
10218 };
10219 uniform S uni;
10220
10221 attribute vec4 inputAttribute;
10222 varying vec4 vertex_out;
10223 void main()
10224 {
10225 vertex_out = uni.val2;
10226 gl_Position = inputAttribute;
10227 })";
10228
10229 constexpr char kFS[] = R"(precision highp float;
10230 struct T
10231 {
10232 vec2 t1;
10233 vec3 t3;
10234 };
10235 struct S {
10236 T val1;
10237 vec4 val2;
10238 };
10239 uniform S uni;
10240
10241 varying vec4 vertex_out;
10242 void main()
10243 {
10244 gl_FragColor = vec4(uni.val1.t1[0], 0.0, 0.0, 1.0);
10245 })";
10246
10247 validateComponentsInErrorMessage(kVS, kFS, "Field names", "uniform 'uni' member 'uni.val1'");
10248 }
10249
10250 // Validate error messages when the link mismatch occurs on the type of a non-struct uniform block
10251 // field.
TEST_P(GLSLTest_ES3,ErrorMessageOfLinkInterfaceBlockFieldMismatch)10252 TEST_P(GLSLTest_ES3, ErrorMessageOfLinkInterfaceBlockFieldMismatch)
10253 {
10254 constexpr char kVS[] = R"(#version 300 es
10255 uniform S {
10256 vec2 val1;
10257 vec4 val2;
10258 } uni;
10259
10260 in vec4 inputAttribute;
10261 out vec4 vertex_out;
10262 void main()
10263 {
10264 vertex_out = uni.val2;
10265 gl_Position = inputAttribute;
10266 })";
10267
10268 constexpr char kFS[] = R"(#version 300 es
10269 precision highp float;
10270 uniform S {
10271 vec2 val1;
10272 vec3 val2;
10273 } uni;
10274
10275 in vec4 vertex_out;
10276 layout (location = 0) out vec4 frag_out;
10277 void main()
10278 {
10279 frag_out = vec4(uni.val1[0], 0.0, 0.0, 1.0);
10280 })";
10281
10282 validateComponentsInErrorMessage(kVS, kFS, "Types", "uniform block 'S' member 'S.val2'");
10283 }
10284
10285 // Validate error messages when the link mismatch occurs on the type of a member of a uniform block
10286 // struct field.
TEST_P(GLSLTest_ES3,ErrorMessageOfLinkInterfaceBlockStructFieldMismatch)10287 TEST_P(GLSLTest_ES3, ErrorMessageOfLinkInterfaceBlockStructFieldMismatch)
10288 {
10289 constexpr char kVS[] = R"(#version 300 es
10290 struct T
10291 {
10292 vec2 t1;
10293 vec3 t2;
10294 };
10295 uniform S {
10296 T val1;
10297 vec4 val2;
10298 } uni;
10299
10300 in vec4 inputAttribute;
10301 out vec4 vertex_out;
10302 void main()
10303 {
10304 vertex_out = uni.val2;
10305 gl_Position = inputAttribute;
10306 })";
10307
10308 constexpr char kFS[] = R"(#version 300 es
10309 precision highp float;
10310 struct T
10311 {
10312 vec2 t1;
10313 vec4 t2;
10314 };
10315 uniform S {
10316 T val1;
10317 vec4 val2;
10318 } uni;
10319
10320 in vec4 vertex_out;
10321 layout (location = 0) out vec4 frag_out;
10322 void main()
10323 {
10324 frag_out = vec4(uni.val1.t1[0], 0.0, 0.0, 1.0);
10325 })";
10326
10327 validateComponentsInErrorMessage(kVS, kFS, "Types", "uniform block 'S' member 'S.val1.t2'");
10328 }
10329
10330 // Test a vertex shader that doesn't declare any varyings with a fragment shader that statically
10331 // uses a varying, but in a statement that gets trivially optimized out by the compiler.
TEST_P(GLSLTest_ES3,FragmentShaderStaticallyUsesVaryingMissingFromVertex)10332 TEST_P(GLSLTest_ES3, FragmentShaderStaticallyUsesVaryingMissingFromVertex)
10333 {
10334 constexpr char kVS[] = R"(#version 300 es
10335 precision mediump float;
10336
10337 void main()
10338 {
10339 gl_Position = vec4(0, 1, 0, 1);
10340 })";
10341
10342 constexpr char kFS[] = R"(#version 300 es
10343 precision mediump float;
10344 in float foo;
10345 out vec4 my_FragColor;
10346
10347 void main()
10348 {
10349 if (false)
10350 {
10351 float unreferenced = foo;
10352 }
10353 my_FragColor = vec4(0, 1, 0, 1);
10354 })";
10355
10356 validateComponentsInErrorMessage(kVS, kFS, "does not match any", "foo");
10357 }
10358
10359 // Test a varying that is statically used but not active in the fragment shader.
TEST_P(GLSLTest_ES3,VaryingStaticallyUsedButNotActiveInFragmentShader)10360 TEST_P(GLSLTest_ES3, VaryingStaticallyUsedButNotActiveInFragmentShader)
10361 {
10362 constexpr char kVS[] = R"(#version 300 es
10363 precision mediump float;
10364 in vec4 iv;
10365 out vec4 v;
10366 void main()
10367 {
10368 gl_Position = iv;
10369 v = iv;
10370 })";
10371
10372 constexpr char kFS[] = R"(#version 300 es
10373 precision mediump float;
10374 in vec4 v;
10375 out vec4 color;
10376 void main()
10377 {
10378 color = true ? vec4(0.0) : v;
10379 })";
10380
10381 ANGLE_GL_PROGRAM(program, kVS, kFS);
10382 }
10383
10384 // Test that linking varyings by location works.
TEST_P(GLSLTest_ES31,LinkVaryingsByLocation)10385 TEST_P(GLSLTest_ES31, LinkVaryingsByLocation)
10386 {
10387 constexpr char kVS[] = R"(#version 310 es
10388 precision highp float;
10389 in vec4 position;
10390 layout(location = 1) out vec4 shaderOutput;
10391 void main() {
10392 gl_Position = position;
10393 shaderOutput = vec4(0.0, 1.0, 0.0, 1.0);
10394 })";
10395
10396 constexpr char kFS[] = R"(#version 310 es
10397 precision highp float;
10398 layout(location = 1) in vec4 shaderInput;
10399 out vec4 outColor;
10400 void main() {
10401 outColor = shaderInput;
10402 })";
10403
10404 ANGLE_GL_PROGRAM(program, kVS, kFS);
10405 drawQuad(program, "position", 0.5f);
10406 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10407 }
10408
10409 // Test nesting floor() calls with a large multiplier inside.
TEST_P(GLSLTest_ES3,NestedFloorWithLargeMultiplierInside)10410 TEST_P(GLSLTest_ES3, NestedFloorWithLargeMultiplierInside)
10411 {
10412 // D3D11 seems to ignore the floor() calls in this particular case, so one of the corners ends
10413 // up red. http://crbug.com/838885
10414 ANGLE_SKIP_TEST_IF(IsD3D11());
10415
10416 constexpr char kFS[] = R"(#version 300 es
10417 precision highp float;
10418 out vec4 my_FragColor;
10419 void main()
10420 {
10421 vec2 coord = gl_FragCoord.xy / 500.0;
10422 my_FragColor = vec4(1, 0, 0, 1);
10423 if (coord.y + 0.1 > floor(1e-6 * floor(coord.x*4e5)))
10424 {
10425 my_FragColor = vec4(0, 1, 0, 1);
10426 }
10427 })";
10428
10429 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
10430 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
10431 // Verify that all the corners of the rendered result are green.
10432 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10433 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
10434 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, 0, GLColor::green);
10435 EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() - 1, GLColor::green);
10436 }
10437
10438 // Verify that a link error is generated when the sum of the number of active image uniforms and
10439 // active shader storage blocks in a rendering pipeline exceeds
10440 // GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES.
TEST_P(GLSLTest_ES31,ExceedCombinedShaderOutputResourcesInVSAndFS)10441 TEST_P(GLSLTest_ES31, ExceedCombinedShaderOutputResourcesInVSAndFS)
10442 {
10443 // TODO([email protected]): enable this test when shader storage buffer is supported on
10444 // D3D11 back-ends.
10445 ANGLE_SKIP_TEST_IF(IsD3D11());
10446
10447 GLint maxVertexShaderStorageBlocks;
10448 GLint maxVertexImageUniforms;
10449 GLint maxFragmentShaderStorageBlocks;
10450 GLint maxFragmentImageUniforms;
10451 GLint maxCombinedShaderStorageBlocks;
10452 GLint maxCombinedImageUniforms;
10453 glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &maxVertexShaderStorageBlocks);
10454 glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &maxVertexImageUniforms);
10455 glGetIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &maxFragmentShaderStorageBlocks);
10456 glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &maxFragmentImageUniforms);
10457 glGetIntegerv(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, &maxCombinedShaderStorageBlocks);
10458 glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS, &maxCombinedImageUniforms);
10459
10460 ASSERT_GE(maxCombinedShaderStorageBlocks, maxVertexShaderStorageBlocks);
10461 ASSERT_GE(maxCombinedShaderStorageBlocks, maxFragmentShaderStorageBlocks);
10462 ASSERT_GE(maxCombinedImageUniforms, maxVertexImageUniforms);
10463 ASSERT_GE(maxCombinedImageUniforms, maxFragmentImageUniforms);
10464
10465 GLint vertexSSBOs = maxVertexShaderStorageBlocks;
10466 GLint fragmentSSBOs = maxFragmentShaderStorageBlocks;
10467 // Limit the sum of ssbos in vertex and fragment shaders to maxCombinedShaderStorageBlocks.
10468 if (vertexSSBOs + fragmentSSBOs > maxCombinedShaderStorageBlocks)
10469 {
10470 fragmentSSBOs = maxCombinedShaderStorageBlocks - vertexSSBOs;
10471 }
10472
10473 GLint vertexImages = maxVertexImageUniforms;
10474 GLint fragmentImages = maxFragmentImageUniforms;
10475 // Limit the sum of images in vertex and fragment shaders to maxCombinedImageUniforms.
10476 if (vertexImages + fragmentImages > maxCombinedImageUniforms)
10477 {
10478 vertexImages = maxCombinedImageUniforms - fragmentImages;
10479 }
10480
10481 GLint maxDrawBuffers;
10482 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
10483
10484 GLint maxCombinedShaderOutputResources;
10485 glGetIntegerv(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, &maxCombinedShaderOutputResources);
10486 ASSERT_GL_NO_ERROR();
10487
10488 ANGLE_SKIP_TEST_IF(vertexSSBOs + fragmentSSBOs + vertexImages + fragmentImages +
10489 maxDrawBuffers <=
10490 maxCombinedShaderOutputResources);
10491
10492 std::ostringstream vertexStream;
10493 vertexStream << "#version 310 es\n";
10494 for (int i = 0; i < vertexSSBOs; ++i)
10495 {
10496 vertexStream << "layout(shared, binding = " << i << ") buffer blockName" << i
10497 << "{\n"
10498 " float data;\n"
10499 "} ssbo"
10500 << i << ";\n";
10501 }
10502 vertexStream << "layout(r32f, binding = 0) uniform highp image2D imageArray[" << vertexImages
10503 << "];\n";
10504 vertexStream << "void main()\n"
10505 "{\n"
10506 " float val = 0.1;\n"
10507 " vec4 val2 = vec4(0.0);\n";
10508 for (int i = 0; i < vertexSSBOs; ++i)
10509 {
10510 vertexStream << " val += ssbo" << i << ".data; \n";
10511 }
10512 for (int i = 0; i < vertexImages; ++i)
10513 {
10514 vertexStream << " val2 += imageLoad(imageArray[" << i << "], ivec2(0, 0)); \n";
10515 }
10516 vertexStream << " gl_Position = vec4(val, val2);\n"
10517 "}\n";
10518
10519 std::ostringstream fragmentStream;
10520 fragmentStream << "#version 310 es\n" << "precision highp float;\n";
10521 for (int i = 0; i < fragmentSSBOs; ++i)
10522 {
10523 fragmentStream << "layout(shared, binding = " << i << ") buffer blockName" << i
10524 << "{\n"
10525 " float data;\n"
10526 "} ssbo"
10527 << i << ";\n";
10528 }
10529 fragmentStream << "layout(r32f, binding = 0) uniform highp image2D imageArray["
10530 << fragmentImages << "];\n";
10531 fragmentStream << "layout (location = 0) out vec4 foutput[" << maxDrawBuffers << "];\n";
10532
10533 fragmentStream << "void main()\n"
10534 "{\n"
10535 " float val = 0.1;\n"
10536 " vec4 val2 = vec4(0.0);\n";
10537 for (int i = 0; i < fragmentSSBOs; ++i)
10538 {
10539 fragmentStream << " val += ssbo" << i << ".data; \n";
10540 }
10541 for (int i = 0; i < fragmentImages; ++i)
10542 {
10543 fragmentStream << " val2 += imageLoad(imageArray[" << i << "], ivec2(0, 0)); \n";
10544 }
10545 for (int i = 0; i < maxDrawBuffers; ++i)
10546 {
10547 fragmentStream << " foutput[" << i << "] = vec4(val, val2);\n";
10548 }
10549 fragmentStream << "}\n";
10550
10551 GLuint program = CompileProgram(vertexStream.str().c_str(), fragmentStream.str().c_str());
10552 EXPECT_EQ(0u, program);
10553
10554 ASSERT_GL_NO_ERROR();
10555 }
10556
10557 // Test that assigning an assignment expression to a swizzled vector field in a user-defined
10558 // function works correctly.
TEST_P(GLSLTest_ES3,AssignToSwizzled)10559 TEST_P(GLSLTest_ES3, AssignToSwizzled)
10560 {
10561 constexpr char kFS[] = R"(#version 300 es
10562 precision highp float;
10563 out vec4 my_FragColor;
10564
10565 uniform float uzero;
10566
10567 vec3 fun(float s, float v)
10568 {
10569 vec3 r = vec3(0);
10570 if (s < 1.0) {
10571 r.x = r.y = r.z = v;
10572 return r;
10573 }
10574 return r;
10575 }
10576
10577 void main()
10578 {
10579 my_FragColor.a = 1.0;
10580 my_FragColor.rgb = fun(uzero, 1.0);
10581 })";
10582
10583 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
10584 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
10585 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
10586 }
10587
10588 // Similar to AssignToSwizzled, but uses other assignment operators than `=`.
TEST_P(GLSLTest_ES3,AssignToSwizzled2)10589 TEST_P(GLSLTest_ES3, AssignToSwizzled2)
10590 {
10591 constexpr char kFS[] = R"(#version 300 es
10592 precision highp float;
10593 out vec4 my_FragColor;
10594
10595 uniform float uzero;
10596
10597 vec3 fun(float s, float v)
10598 {
10599 vec3 r = vec3(0.125, 0.5, 0.);
10600 if (s < 1.0) {
10601 r.x /= r.y *= r.z += v;
10602 return r;
10603 }
10604 return r;
10605 }
10606
10607 void main()
10608 {
10609 my_FragColor.a = 1.0;
10610 my_FragColor.rgb = fun(uzero, 1.0);
10611 })";
10612
10613 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
10614 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
10615 EXPECT_PIXEL_NEAR(0, 0, 63, 127, 255, 255, 1);
10616 }
10617
10618 // Test that swizzled vector to bool cast works correctly.
TEST_P(GLSLTest_ES3,SwizzledToBoolCoercion)10619 TEST_P(GLSLTest_ES3, SwizzledToBoolCoercion)
10620 {
10621 constexpr char kFS[] = R"(#version 300 es
10622 precision highp float;
10623 out vec4 o;
10624 uniform vec2 u;
10625 void main()
10626 {
10627 bvec2 b = bvec2(u.yx);
10628 if (b.x&&!b.y)
10629 o = vec4(1.0);
10630 })";
10631 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
10632 glUseProgram(program);
10633 GLint uloc = glGetUniformLocation(program, "u");
10634 ASSERT_NE(uloc, -1);
10635 glUniform2f(uloc, 0, 1);
10636 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
10637 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
10638 }
10639
10640 // Test a fragment shader that returns inside if (that being the only branch that actually gets
10641 // executed). Regression test for http://anglebug.com/42261034
TEST_P(GLSLTest,IfElseIfAndReturn)10642 TEST_P(GLSLTest, IfElseIfAndReturn)
10643 {
10644 constexpr char kVS[] = R"(attribute vec4 a_position;
10645 varying vec2 vPos;
10646 void main()
10647 {
10648 gl_Position = a_position;
10649 vPos = a_position.xy;
10650 })";
10651
10652 constexpr char kFS[] = R"(precision mediump float;
10653 varying vec2 vPos;
10654 void main()
10655 {
10656 if (vPos.x < 1.0) // This colors the whole canvas green
10657 {
10658 gl_FragColor = vec4(0, 1, 0, 1);
10659 return;
10660 }
10661 else if (vPos.x < 1.1) // This should have no effect
10662 {
10663 gl_FragColor = vec4(1, 0, 0, 1);
10664 }
10665 })";
10666
10667 ANGLE_GL_PROGRAM(program, kVS, kFS);
10668 drawQuad(program, "a_position", 0.5f);
10669 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10670 }
10671
10672 // Test that if-else blocks whose contents get pruned due to compile-time constant conditions work.
TEST_P(GLSLTest,IfElsePrunedBlocks)10673 TEST_P(GLSLTest, IfElsePrunedBlocks)
10674 {
10675 constexpr char kFS[] = R"(precision mediump float;
10676 uniform float u;
10677 void main()
10678 {
10679 // if with only a pruned true block
10680 if (u > 0.0)
10681 if (false) discard;
10682
10683 // if with a pruned true block and a false block
10684 if (u > 0.0)
10685 {
10686 if (false) discard;
10687 }
10688 else
10689 ;
10690
10691 // if with a true block and a pruned false block
10692 if (u > 0.0)
10693 ;
10694 else
10695 if (false) discard;
10696
10697 // if with a pruned true block and a pruned false block
10698 if (u > 0.0)
10699 {
10700 if (false) discard;
10701 }
10702 else
10703 if (false) discard;
10704
10705 gl_FragColor = vec4(0, 1, 0, 1);
10706 })";
10707
10708 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
10709 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
10710 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10711 }
10712
10713 // Tests that PointCoord behaves the same betweeen a user FBO and the back buffer.
TEST_P(GLSLTest,PointCoordConsistency)10714 TEST_P(GLSLTest, PointCoordConsistency)
10715 {
10716 constexpr char kPointCoordVS[] = R"(attribute vec2 position;
10717 uniform vec2 viewportSize;
10718 void main()
10719 {
10720 gl_Position = vec4(position, 0, 1);
10721 gl_PointSize = viewportSize.x;
10722 })";
10723
10724 constexpr char kPointCoordFS[] = R"(void main()
10725 {
10726 gl_FragColor = vec4(gl_PointCoord.xy, 0, 1);
10727 })";
10728
10729 ANGLE_GL_PROGRAM(program, kPointCoordVS, kPointCoordFS);
10730 glUseProgram(program);
10731
10732 GLint uniLoc = glGetUniformLocation(program, "viewportSize");
10733 ASSERT_NE(-1, uniLoc);
10734 glUniform2f(uniLoc, static_cast<GLfloat>(getWindowWidth()),
10735 static_cast<GLfloat>(getWindowHeight()));
10736
10737 // Draw to backbuffer.
10738 glClear(GL_COLOR_BUFFER_BIT);
10739 glDrawArrays(GL_POINTS, 0, 1);
10740 ASSERT_GL_NO_ERROR();
10741
10742 std::vector<GLColor> backbufferData(getWindowWidth() * getWindowHeight());
10743 glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
10744 backbufferData.data());
10745
10746 GLTexture tex;
10747 glBindTexture(GL_TEXTURE_2D, tex);
10748 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
10749 GL_UNSIGNED_BYTE, nullptr);
10750
10751 GLFramebuffer fbo;
10752 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
10753 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
10754 ASSERT_GL_NO_ERROR();
10755 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
10756
10757 // Draw to user FBO.
10758 glClear(GL_COLOR_BUFFER_BIT);
10759 glDrawArrays(GL_POINTS, 0, 1);
10760 ASSERT_GL_NO_ERROR();
10761
10762 std::vector<GLColor> userFBOData(getWindowWidth() * getWindowHeight());
10763 glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
10764 userFBOData.data());
10765
10766 ASSERT_GL_NO_ERROR();
10767 ASSERT_EQ(userFBOData.size(), backbufferData.size());
10768 EXPECT_EQ(userFBOData, backbufferData);
10769 }
10770
SubrectEquals(const std::vector<GLColor> & bigArray,const std::vector<GLColor> & smallArray,int bigSize,int offset,int smallSize)10771 bool SubrectEquals(const std::vector<GLColor> &bigArray,
10772 const std::vector<GLColor> &smallArray,
10773 int bigSize,
10774 int offset,
10775 int smallSize)
10776 {
10777 int badPixels = 0;
10778 for (int y = 0; y < smallSize; y++)
10779 {
10780 for (int x = 0; x < smallSize; x++)
10781 {
10782 int bigOffset = (y + offset) * bigSize + x + offset;
10783 int smallOffset = y * smallSize + x;
10784 if (bigArray[bigOffset] != smallArray[smallOffset])
10785 badPixels++;
10786 }
10787 }
10788 return badPixels == 0;
10789 }
10790
10791 // Tests that FragCoord behaves the same betweeen a user FBO and the back buffer.
TEST_P(GLSLTest,FragCoordConsistency)10792 TEST_P(GLSLTest, FragCoordConsistency)
10793 {
10794 constexpr char kFragCoordShader[] = R"(uniform mediump vec2 viewportSize;
10795 void main()
10796 {
10797 gl_FragColor = vec4(gl_FragCoord.xy / viewportSize, 0, 1);
10798 })";
10799
10800 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragCoordShader);
10801 glUseProgram(program);
10802
10803 GLint uniLoc = glGetUniformLocation(program, "viewportSize");
10804 ASSERT_NE(-1, uniLoc);
10805 glUniform2f(uniLoc, static_cast<GLfloat>(getWindowWidth()),
10806 static_cast<GLfloat>(getWindowHeight()));
10807
10808 // Draw to backbuffer.
10809 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
10810 ASSERT_GL_NO_ERROR();
10811
10812 std::vector<GLColor> backbufferData(getWindowWidth() * getWindowHeight());
10813 glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
10814 backbufferData.data());
10815
10816 GLTexture tex;
10817 glBindTexture(GL_TEXTURE_2D, tex);
10818 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
10819 GL_UNSIGNED_BYTE, nullptr);
10820
10821 GLFramebuffer fbo;
10822 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
10823 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
10824 ASSERT_GL_NO_ERROR();
10825 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
10826
10827 // Draw to user FBO.
10828 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
10829 ASSERT_GL_NO_ERROR();
10830
10831 std::vector<GLColor> userFBOData(getWindowWidth() * getWindowHeight());
10832 glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
10833 userFBOData.data());
10834
10835 ASSERT_GL_NO_ERROR();
10836 ASSERT_EQ(userFBOData.size(), backbufferData.size());
10837 EXPECT_EQ(userFBOData, backbufferData)
10838 << "FragCoord should be the same to default and user FBO";
10839
10840 // Repeat the same test but with a smaller viewport.
10841 ASSERT_EQ(getWindowHeight(), getWindowWidth());
10842 const int kQuarterSize = getWindowWidth() >> 2;
10843 glViewport(kQuarterSize, kQuarterSize, kQuarterSize * 2, kQuarterSize * 2);
10844
10845 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
10846 glClear(GL_COLOR_BUFFER_BIT);
10847 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
10848
10849 std::vector<GLColor> userFBOViewportData(kQuarterSize * kQuarterSize * 4);
10850 glReadPixels(kQuarterSize, kQuarterSize, kQuarterSize * 2, kQuarterSize * 2, GL_RGBA,
10851 GL_UNSIGNED_BYTE, userFBOViewportData.data());
10852
10853 glBindFramebuffer(GL_FRAMEBUFFER, 0);
10854 glClear(GL_COLOR_BUFFER_BIT);
10855 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
10856
10857 std::vector<GLColor> defaultFBOViewportData(kQuarterSize * kQuarterSize * 4);
10858 glReadPixels(kQuarterSize, kQuarterSize, kQuarterSize * 2, kQuarterSize * 2, GL_RGBA,
10859 GL_UNSIGNED_BYTE, defaultFBOViewportData.data());
10860 ASSERT_GL_NO_ERROR();
10861 EXPECT_EQ(userFBOViewportData, defaultFBOViewportData)
10862 << "FragCoord should be the same to default and user FBO even with a custom viewport";
10863
10864 // Check that the subrectangles are the same between the viewport and non-viewport modes.
10865 EXPECT_TRUE(SubrectEquals(userFBOData, userFBOViewportData, getWindowWidth(), kQuarterSize,
10866 kQuarterSize * 2));
10867 EXPECT_TRUE(SubrectEquals(backbufferData, defaultFBOViewportData, getWindowWidth(),
10868 kQuarterSize, kQuarterSize * 2));
10869 }
10870
10871 // Ensure that using defined in a macro works in this simple case. This mirrors a dEQP test.
TEST_P(GLSLTest,DefinedInMacroSucceeds)10872 TEST_P(GLSLTest, DefinedInMacroSucceeds)
10873 {
10874 constexpr char kVS[] = R"(precision mediump float;
10875 attribute highp vec4 position;
10876 varying vec2 out0;
10877
10878 void main()
10879 {
10880 #define AAA defined(BBB)
10881
10882 #if !AAA
10883 out0 = vec2(0.0, 1.0);
10884 #else
10885 out0 = vec2(1.0, 0.0);
10886 #endif
10887 gl_Position = position;
10888 })";
10889
10890 constexpr char kFS[] = R"(precision mediump float;
10891 varying vec2 out0;
10892 void main()
10893 {
10894 gl_FragColor = vec4(out0, 0, 1);
10895 })";
10896
10897 ANGLE_GL_PROGRAM(program, kVS, kFS);
10898 drawQuad(program, "position", 0.5f);
10899 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10900 }
10901
10902 // Validate the defined operator is evaluated when the macro is called, not when defined.
TEST_P(GLSLTest,DefinedInMacroWithUndef)10903 TEST_P(GLSLTest, DefinedInMacroWithUndef)
10904 {
10905 constexpr char kVS[] = R"(precision mediump float;
10906 attribute highp vec4 position;
10907 varying vec2 out0;
10908
10909 void main()
10910 {
10911 #define BBB 1
10912 #define AAA defined(BBB)
10913 #undef BBB
10914
10915 #if AAA
10916 out0 = vec2(1.0, 0.0);
10917 #else
10918 out0 = vec2(0.0, 1.0);
10919 #endif
10920 gl_Position = position;
10921 })";
10922
10923 constexpr char kFS[] = R"(precision mediump float;
10924 varying vec2 out0;
10925 void main()
10926 {
10927 gl_FragColor = vec4(out0, 0, 1);
10928 })";
10929
10930 ANGLE_GL_PROGRAM(program, kVS, kFS);
10931 drawQuad(program, "position", 0.5f);
10932 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10933 }
10934
10935 // Validate the defined operator is evaluated when the macro is called, not when defined.
TEST_P(GLSLTest,DefinedAfterMacroUsage)10936 TEST_P(GLSLTest, DefinedAfterMacroUsage)
10937 {
10938 constexpr char kVS[] = R"(precision mediump float;
10939 attribute highp vec4 position;
10940 varying vec2 out0;
10941
10942 void main()
10943 {
10944 #define AAA defined(BBB)
10945 #define BBB 1
10946
10947 #if AAA
10948 out0 = vec2(0.0, 1.0);
10949 #else
10950 out0 = vec2(1.0, 0.0);
10951 #endif
10952 gl_Position = position;
10953 })";
10954
10955 constexpr char kFS[] = R"(precision mediump float;
10956 varying vec2 out0;
10957 void main()
10958 {
10959 gl_FragColor = vec4(out0, 0, 1);
10960 })";
10961
10962 ANGLE_GL_PROGRAM(program, kVS, kFS);
10963 drawQuad(program, "position", 0.5f);
10964 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10965 }
10966
10967 // Test generating "defined" by concatenation when a macro is called. This is not allowed.
TEST_P(GLSLTest,DefinedInMacroConcatenationNotAllowed)10968 TEST_P(GLSLTest, DefinedInMacroConcatenationNotAllowed)
10969 {
10970 constexpr char kVS[] = R"(precision mediump float;
10971 attribute highp vec4 position;
10972 varying vec2 out0;
10973
10974 void main()
10975 {
10976 #define BBB 1
10977 #define AAA(defi, ned) defi ## ned(BBB)
10978
10979 #if AAA(defi, ned)
10980 out0 = vec2(0.0, 1.0);
10981 #else
10982 out0 = vec2(1.0, 0.0);
10983 #endif
10984 gl_Position = position;
10985 })";
10986
10987 constexpr char kFS[] = R"(precision mediump float;
10988 varying vec2 out0;
10989 void main()
10990 {
10991 gl_FragColor = vec4(out0, 0, 1);
10992 })";
10993
10994 GLuint program = CompileProgram(kVS, kFS);
10995 EXPECT_EQ(0u, program);
10996 glDeleteProgram(program);
10997 }
10998
10999 // Test using defined in a macro parameter name. This is not allowed.
TEST_P(GLSLTest,DefinedAsParameterNameNotAllowed)11000 TEST_P(GLSLTest, DefinedAsParameterNameNotAllowed)
11001 {
11002 constexpr char kVS[] = R"(precision mediump float;
11003 attribute highp vec4 position;
11004 varying vec2 out0;
11005
11006 void main()
11007 {
11008 #define BBB 1
11009 #define AAA(defined) defined(BBB)
11010
11011 #if AAA(defined)
11012 out0 = vec2(0.0, 1.0);
11013 #else
11014 out0 = vec2(1.0, 0.0);
11015 #endif
11016 gl_Position = position;
11017 })";
11018
11019 constexpr char kFS[] = R"(precision mediump float;
11020 varying vec2 out0;
11021 void main()
11022 {
11023 gl_FragColor = vec4(out0, 0, 1);
11024 })";
11025
11026 GLuint program = CompileProgram(kVS, kFS);
11027 EXPECT_EQ(0u, program);
11028 glDeleteProgram(program);
11029 }
11030
11031 // Ensure that defined in a macro is no accepted in WebGL.
TEST_P(WebGLGLSLTest,DefinedInMacroFails)11032 TEST_P(WebGLGLSLTest, DefinedInMacroFails)
11033 {
11034 constexpr char kVS[] = R"(precision mediump float;
11035 attribute highp vec4 position;
11036 varying float out0;
11037
11038 void main()
11039 {
11040 #define AAA defined(BBB)
11041
11042 #if !AAA
11043 out0 = 1.0;
11044 #else
11045 out0 = 0.0;
11046 #endif
11047 gl_Position = dEQP_Position;
11048 })";
11049
11050 constexpr char kFS[] = R"(precision mediump float;
11051 varying float out0;
11052 void main()
11053 {
11054 gl_FragColor = vec4(out0, 0, 0, 1);
11055 })";
11056
11057 GLuint program = CompileProgram(kVS, kFS);
11058 EXPECT_EQ(0u, program);
11059 glDeleteProgram(program);
11060 }
11061
11062 // Simple test using a define macro in WebGL.
TEST_P(WebGLGLSLTest,DefinedGLESSymbol)11063 TEST_P(WebGLGLSLTest, DefinedGLESSymbol)
11064 {
11065 constexpr char kVS[] = R"(void main()
11066 {
11067 gl_Position = vec4(1, 0, 0, 1);
11068 })";
11069
11070 constexpr char kFS[] = R"(#if defined(GL_ES)
11071 precision mediump float;
11072 void main()
11073 {
11074 gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
11075 }
11076 #else
11077 foo
11078 #endif
11079 )";
11080
11081 ANGLE_GL_PROGRAM(program, kVS, kFS);
11082 }
11083
11084 // Test that inactive output variables compile ok in combination with initOutputVariables
11085 // (which is enabled on WebGL).
TEST_P(WebGL2GLSLTest,InactiveOutput)11086 TEST_P(WebGL2GLSLTest, InactiveOutput)
11087 {
11088 constexpr char kFS[] = R"(#version 300 es
11089 precision highp float;
11090 out vec4 _cassgl_2_;
11091 void main()
11092 {
11093 })";
11094
11095 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
11096 EXPECT_NE(shader, 0u);
11097 }
11098
11099 // Test that clamp applied on non-literal indices is correct on es 100 shaders.
TEST_P(GLSLTest,ValidIndexClampES100)11100 TEST_P(GLSLTest, ValidIndexClampES100)
11101 {
11102 // http://anglebug.com/42264558
11103 ANGLE_SKIP_TEST_IF(IsD3D9());
11104
11105 constexpr char kFS[] = R"(
11106 precision mediump float;
11107 uniform int u;
11108 uniform mat4 m[2];
11109 void main()
11110 {
11111 gl_FragColor = vec4(m[u][1].xyz, 1);
11112 }
11113 )";
11114
11115 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
11116 glUseProgram(program);
11117
11118 GLint uniformLocation = glGetUniformLocation(program, "u");
11119 ASSERT_NE(-1, uniformLocation);
11120
11121 GLint matrixLocation = glGetUniformLocation(program, "m");
11122 ASSERT_NE(matrixLocation, -1);
11123 const std::array<GLfloat, 32> mValue = {{0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f,
11124 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f,
11125 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
11126 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}};
11127 glUniformMatrix4fv(matrixLocation, 2, false, mValue.data());
11128
11129 glUniform1i(uniformLocation, 1);
11130 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
11131 EXPECT_GL_NO_ERROR();
11132
11133 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
11134 }
11135
11136 // Test that clamp applied on non-literal indices is correct on es 300 shaders.
TEST_P(GLSLTest_ES3,ValidIndexClampES300)11137 TEST_P(GLSLTest_ES3, ValidIndexClampES300)
11138 {
11139 constexpr char kFS[] = R"(#version 300 es
11140 precision mediump float;
11141 out vec4 color;
11142 uniform int u;
11143 mat4 m[4] = mat4[4](mat4(0.25), mat4(0.5), mat4(1), mat4(0.75));
11144 void main()
11145 {
11146 color = vec4(m[u][2].xyz, 1);
11147 }
11148 )";
11149
11150 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11151 glUseProgram(program);
11152
11153 GLint uniformLocation = glGetUniformLocation(program, "u");
11154 ASSERT_NE(-1, uniformLocation);
11155
11156 glUniform1i(uniformLocation, 2);
11157 EXPECT_GL_NO_ERROR();
11158 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
11159 EXPECT_GL_NO_ERROR();
11160
11161 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
11162 }
11163
11164 // Tests constant folding of non-square 'matrixCompMult'.
TEST_P(GLSLTest_ES3,NonSquareMatrixCompMult)11165 TEST_P(GLSLTest_ES3, NonSquareMatrixCompMult)
11166 {
11167 constexpr char kFS[] = R"(#version 300 es
11168 precision mediump float;
11169
11170 const mat4x2 matA = mat4x2(2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0);
11171 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);
11172
11173 out vec4 color;
11174
11175 void main()
11176 {
11177 mat4x2 result = matrixCompMult(matA, matB);
11178 vec2 vresult = result * vec4(1.0, 1.0, 1.0, 1.0);
11179 if (vresult == vec2(4.0, 4.0))
11180 {
11181 color = vec4(0.0, 1.0, 0.0, 1.0);
11182 }
11183 else
11184 {
11185 color = vec4(1.0, 0.0, 0.0, 1.0);
11186 }
11187 })";
11188
11189 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11190 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
11191 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
11192 }
11193
11194 // Test initializing an array with the same name of previously declared array
TEST_P(GLSLTest_ES3,InitSameNameArray)11195 TEST_P(GLSLTest_ES3, InitSameNameArray)
11196 {
11197 constexpr char kFS[] = R"(#version 300 es
11198 precision highp float;
11199 out vec4 my_FragColor;
11200
11201 void main()
11202 {
11203 float arr[2] = float[2](1.0, 1.0);
11204 {
11205 float arr[2] = arr;
11206 my_FragColor = vec4(0.0, arr[0], 0.0, arr[1]);
11207 }
11208 })";
11209
11210 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11211 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
11212 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
11213 }
11214
11215 // Tests using gl_FragData[0] instead of gl_FragColor.
TEST_P(GLSLTest,FragData)11216 TEST_P(GLSLTest, FragData)
11217 {
11218 constexpr char kFS[] = R"(void main() { gl_FragData[0] = vec4(1, 0, 0, 1); })";
11219 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
11220 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
11221 EXPECT_GL_NO_ERROR();
11222 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
11223 }
11224
11225 // Tests using gl_FragData[0] instead of gl_FragColor with GL_SAMPLE_ALPHA_TO_COVERAGE
11226 // Regression test for https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/5520
TEST_P(GLSLTest,FragData_AlphaToCoverage)11227 TEST_P(GLSLTest, FragData_AlphaToCoverage)
11228 {
11229 constexpr char kFS[] = R"(void main() { gl_FragData[0] = vec4(1, 0, 0, 1); })";
11230 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
11231 glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
11232 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
11233 EXPECT_GL_NO_ERROR();
11234 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
11235 }
11236
11237 // Test angle can handle big initial stack size with dynamic stack allocation.
TEST_P(GLSLTest,MemoryExhaustedTest)11238 TEST_P(GLSLTest, MemoryExhaustedTest)
11239 {
11240 GLuint program =
11241 CompileProgram(essl1_shaders::vs::Simple(), BuildBigInitialStackShader(36).c_str());
11242 EXPECT_NE(0u, program);
11243 }
11244
11245 // Test that inactive samplers in structs don't cause any errors.
TEST_P(GLSLTest,InactiveSamplersInStruct)11246 TEST_P(GLSLTest, InactiveSamplersInStruct)
11247 {
11248 constexpr char kVS[] = R"(attribute vec4 a_position;
11249 void main() {
11250 gl_Position = a_position;
11251 })";
11252
11253 constexpr char kFS[] = R"(precision highp float;
11254 struct S
11255 {
11256 vec4 v;
11257 sampler2D t[10];
11258 };
11259 uniform S s;
11260 void main() {
11261 gl_FragColor = s.v;
11262 })";
11263
11264 ANGLE_GL_PROGRAM(program, kVS, kFS);
11265
11266 drawQuad(program, "a_position", 0.5f);
11267 }
11268
11269 // Helper functions for MixedRowAndColumnMajorMatrices* tests
11270
11271 // Round up to alignment, assuming it's a power of 2
RoundUpPow2(uint32_t value,uint32_t alignment)11272 uint32_t RoundUpPow2(uint32_t value, uint32_t alignment)
11273 {
11274 return (value + alignment - 1) & ~(alignment - 1);
11275 }
11276
CreateOutputBuffer(GLBuffer * buffer,uint32_t binding)11277 void CreateOutputBuffer(GLBuffer *buffer, uint32_t binding)
11278 {
11279 unsigned int outputInitData = 0;
11280 glBindBuffer(GL_SHADER_STORAGE_BUFFER, *buffer);
11281 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
11282 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, binding, *buffer);
11283 EXPECT_GL_NO_ERROR();
11284 }
11285
11286 // Fill provided buffer with matrices based on the given dimensions. The buffer should be large
11287 // 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)11288 uint32_t FillBuffer(const std::pair<uint32_t, uint32_t> matrixDims[],
11289 const bool matrixIsColMajor[],
11290 size_t matrixCount,
11291 float data[],
11292 bool isStd430,
11293 bool isTransposed)
11294 {
11295 size_t offset = 0;
11296 for (size_t m = 0; m < matrixCount; ++m)
11297 {
11298 uint32_t cols = matrixDims[m].first;
11299 uint32_t rows = matrixDims[m].second;
11300 bool isColMajor = matrixIsColMajor[m] != isTransposed;
11301
11302 uint32_t arraySize = isColMajor ? cols : rows;
11303 uint32_t arrayElementComponents = isColMajor ? rows : cols;
11304 // Note: stride is generally 4 with std140, except for scalar and gvec2 types (which
11305 // MixedRowAndColumnMajorMatrices* tests don't use). With std430, small matrices can have
11306 // a stride of 2 between rows/columns.
11307 uint32_t stride = isStd430 ? RoundUpPow2(arrayElementComponents, 2) : 4;
11308
11309 offset = RoundUpPow2(offset, stride);
11310
11311 for (uint32_t i = 0; i < arraySize; ++i)
11312 {
11313 for (uint32_t c = 0; c < arrayElementComponents; ++c)
11314 {
11315 uint32_t row = isColMajor ? c : i;
11316 uint32_t col = isColMajor ? i : c;
11317
11318 data[offset + i * stride + c] = col * 4 + row;
11319 }
11320 }
11321
11322 offset += arraySize * stride;
11323 }
11324 return offset;
11325 }
11326
11327 // Initialize and bind the buffer.
11328 template <typename T>
InitBuffer(GLuint program,const char * name,GLuint buffer,uint32_t bindingIndex,const T data[],uint32_t dataSize,bool isUniform)11329 void InitBuffer(GLuint program,
11330 const char *name,
11331 GLuint buffer,
11332 uint32_t bindingIndex,
11333 const T data[],
11334 uint32_t dataSize,
11335 bool isUniform)
11336 {
11337 GLenum bindPoint = isUniform ? GL_UNIFORM_BUFFER : GL_SHADER_STORAGE_BUFFER;
11338
11339 glBindBufferBase(bindPoint, bindingIndex, buffer);
11340 glBufferData(bindPoint, dataSize * sizeof(*data), data, GL_STATIC_DRAW);
11341
11342 if (isUniform)
11343 {
11344 GLint blockIndex = glGetUniformBlockIndex(program, name);
11345 glUniformBlockBinding(program, blockIndex, bindingIndex);
11346 }
11347 }
11348
11349 // Verify that buffer data is written by the shader as expected.
11350 template <typename T>
VerifyBuffer(GLuint buffer,const T data[],uint32_t dataSize)11351 bool VerifyBuffer(GLuint buffer, const T data[], uint32_t dataSize)
11352 {
11353 uint32_t sizeInBytes = dataSize * sizeof(*data);
11354
11355 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
11356
11357 glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
11358
11359 const T *ptr = reinterpret_cast<const T *>(
11360 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeInBytes, GL_MAP_READ_BIT));
11361
11362 bool isCorrect = memcmp(ptr, data, sizeInBytes) == 0;
11363 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
11364
11365 return isCorrect;
11366 }
11367
11368 // Verify that the success output of the shader is as expected.
VerifySuccess(GLuint buffer)11369 bool VerifySuccess(GLuint buffer)
11370 {
11371 uint32_t success = 1;
11372 return VerifyBuffer(buffer, reinterpret_cast<const float *>(&success), 1);
11373 }
11374
11375 // Test reading from UBOs and SSBOs and writing to SSBOs with mixed row- and colum-major layouts in
11376 // both std140 and std430 layouts. Tests many combinations of std140 vs std430, struct being used
11377 // as row- or column-major in different UBOs, reading from UBOs and SSBOs and writing to SSBOs,
11378 // nested structs, matrix arrays, inout parameters etc.
11379 //
11380 // Some very specific corner cases that are not covered here are tested in the subsequent tests.
TEST_P(GLSLTest_ES31,MixedRowAndColumnMajorMatrices)11381 TEST_P(GLSLTest_ES31, MixedRowAndColumnMajorMatrices)
11382 {
11383 GLint maxComputeShaderStorageBlocks;
11384 glGetIntegerv(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, &maxComputeShaderStorageBlocks);
11385
11386 // The test uses 9 SSBOs. Skip if not that many are supported.
11387 ANGLE_SKIP_TEST_IF(maxComputeShaderStorageBlocks < 9);
11388
11389 // Fails on Nvidia because having |Matrices| qualified as row-major in one UBO makes the other
11390 // UBO also see it as row-major despite explicit column-major qualifier.
11391 // http://anglebug.com/42262474
11392 ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGL());
11393
11394 // Fails on mesa because in the first UBO which is qualified as column-major, |Matrices| is
11395 // read column-major despite explicit row-major qualifier. http://anglebug.com/42262481
11396 ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsOpenGL());
11397
11398 // Fails on windows AMD on GL: http://anglebug.com/42262482
11399 ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL() && IsAMD());
11400
11401 // Fails to compile the shader on Android. http://anglebug.com/42262483
11402 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
11403
11404 // Fails on assertion in translation to D3D. http://anglebug.com/42262486
11405 ANGLE_SKIP_TEST_IF(IsD3D11());
11406
11407 // Fails on SSBO validation on Android/Vulkan. http://anglebug.com/42262485
11408 ANGLE_SKIP_TEST_IF(IsAndroid() && IsVulkan());
11409
11410 // Fails input verification as well as std140 SSBO validation. http://anglebug.com/42262489
11411 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());
11412
11413 // Fails on ARM on Vulkan. http://anglebug.com/42263107
11414 ANGLE_SKIP_TEST_IF(IsARM() && IsVulkan());
11415
11416 constexpr char kCS[] = R"(#version 310 es
11417 precision highp float;
11418 layout(local_size_x=1) in;
11419
11420 struct Inner
11421 {
11422 mat3x4 m3c4r;
11423 mat4x3 m4c3r;
11424 };
11425
11426 struct Matrices
11427 {
11428 mat2 m2c2r;
11429 mat2x3 m2c3r[2];
11430 mat3x2 m3c2r;
11431 Inner inner;
11432 };
11433
11434 // For simplicity, the layouts are either of:
11435 // - col-major mat4, row-major rest
11436 // - row-major mat4, col-major rest
11437 //
11438 // The former is tagged with c, the latter with r.
11439 layout(std140, column_major) uniform Ubo140c
11440 {
11441 mat4 m4c4r;
11442 layout(row_major) Matrices m;
11443 } ubo140cIn;
11444
11445 layout(std140, row_major) uniform Ubo140r
11446 {
11447 mat4 m4c4r;
11448 layout(column_major) Matrices m;
11449 } ubo140rIn;
11450
11451 layout(std140, row_major, binding = 0) buffer Ssbo140c
11452 {
11453 layout(column_major) mat4 m4c4r;
11454 Matrices m;
11455 } ssbo140cIn;
11456
11457 layout(std140, column_major, binding = 1) buffer Ssbo140r
11458 {
11459 layout(row_major) mat4 m4c4r;
11460 Matrices m;
11461 } ssbo140rIn;
11462
11463 layout(std430, column_major, binding = 2) buffer Ssbo430c
11464 {
11465 mat4 m4c4r;
11466 layout(row_major) Matrices m;
11467 } ssbo430cIn;
11468
11469 layout(std430, row_major, binding = 3) buffer Ssbo430r
11470 {
11471 mat4 m4c4r;
11472 layout(column_major) Matrices m;
11473 } ssbo430rIn;
11474
11475 layout(std140, row_major, binding = 4) buffer Ssbo140cOut
11476 {
11477 layout(column_major) mat4 m4c4r;
11478 Matrices m;
11479 } ssbo140cOut;
11480
11481 layout(std140, column_major, binding = 5) buffer Ssbo140rOut
11482 {
11483 layout(row_major) mat4 m4c4r;
11484 Matrices m;
11485 } ssbo140rOut;
11486
11487 layout(std430, column_major, binding = 6) buffer Ssbo430cOut
11488 {
11489 mat4 m4c4r;
11490 layout(row_major) Matrices m;
11491 } ssbo430cOut;
11492
11493 layout(std430, row_major, binding = 7) buffer Ssbo430rOut
11494 {
11495 mat4 m4c4r;
11496 layout(column_major) Matrices m;
11497 } ssbo430rOut;
11498
11499 layout(std140, binding = 8) buffer Result
11500 {
11501 uint success;
11502 } resultOut;
11503
11504 #define EXPECT(result, expression, value) if ((expression) != value) { result = false; }
11505 #define EXPECTV(result, expression, value) if (any(notEqual(expression, value))) { result = false; }
11506
11507 #define VERIFY_IN(result, mat, cols, rows) \
11508 EXPECT(result, mat[0].x, 0.0); \
11509 EXPECT(result, mat[0][1], 1.0); \
11510 EXPECTV(result, mat[0].xy, vec2(0, 1)); \
11511 EXPECTV(result, mat[1].xy, vec2(4, 5)); \
11512 for (int c = 0; c < cols; ++c) \
11513 { \
11514 for (int r = 0; r < rows; ++r) \
11515 { \
11516 EXPECT(result, mat[c][r], float(c * 4 + r)); \
11517 } \
11518 }
11519
11520 #define COPY(matIn, matOut, cols, rows) \
11521 matOut = matOut + matIn; \
11522 /* random operations for testing */ \
11523 matOut[0].x += matIn[0].x + matIn[1].x; \
11524 matOut[0].x -= matIn[1].x; \
11525 matOut[0][1] += matIn[0][1]; \
11526 matOut[1] += matIn[1]; \
11527 matOut[1].xy -= matIn[1].xy; \
11528 /* undo the above to get back matIn */ \
11529 matOut[0].x -= matIn[0].x; \
11530 matOut[0][1] -= matIn[0][1]; \
11531 matOut[1] -= matIn[1]; \
11532 matOut[1].xy += matIn[1].xy;
11533
11534 bool verifyMatrices(in Matrices m)
11535 {
11536 bool result = true;
11537 VERIFY_IN(result, m.m2c2r, 2, 2);
11538 VERIFY_IN(result, m.m2c3r[0], 2, 3);
11539 VERIFY_IN(result, m.m2c3r[1], 2, 3);
11540 VERIFY_IN(result, m.m3c2r, 3, 2);
11541 VERIFY_IN(result, m.inner.m3c4r, 3, 4);
11542 VERIFY_IN(result, m.inner.m4c3r, 4, 3);
11543 return result;
11544 }
11545
11546 mat4 copyMat4(in mat4 m)
11547 {
11548 return m;
11549 }
11550
11551 void copyMatrices(in Matrices mIn, inout Matrices mOut)
11552 {
11553 COPY(mIn.m2c2r, mOut.m2c2r, 2, 2);
11554 COPY(mIn.m2c3r[0], mOut.m2c3r[0], 2, 3);
11555 COPY(mIn.m2c3r[1], mOut.m2c3r[1], 2, 3);
11556 COPY(mIn.m3c2r, mOut.m3c2r, 3, 2);
11557 COPY(mIn.inner.m3c4r, mOut.inner.m3c4r, 3, 4);
11558 COPY(mIn.inner.m4c3r, mOut.inner.m4c3r, 4, 3);
11559 }
11560
11561 void main()
11562 {
11563 bool result = true;
11564
11565 VERIFY_IN(result, ubo140cIn.m4c4r, 4, 4);
11566 VERIFY_IN(result, ubo140cIn.m.m2c3r[0], 2, 3);
11567 EXPECT(result, verifyMatrices(ubo140cIn.m), true);
11568
11569 VERIFY_IN(result, ubo140rIn.m4c4r, 4, 4);
11570 VERIFY_IN(result, ubo140rIn.m.m2c2r, 2, 2);
11571 EXPECT(result, verifyMatrices(ubo140rIn.m), true);
11572
11573 VERIFY_IN(result, ssbo140cIn.m4c4r, 4, 4);
11574 VERIFY_IN(result, ssbo140cIn.m.m3c2r, 3, 2);
11575 EXPECT(result, verifyMatrices(ssbo140cIn.m), true);
11576
11577 VERIFY_IN(result, ssbo140rIn.m4c4r, 4, 4);
11578 VERIFY_IN(result, ssbo140rIn.m.inner.m4c3r, 4, 3);
11579 EXPECT(result, verifyMatrices(ssbo140rIn.m), true);
11580
11581 VERIFY_IN(result, ssbo430cIn.m4c4r, 4, 4);
11582 VERIFY_IN(result, ssbo430cIn.m.m2c3r[1], 2, 3);
11583 EXPECT(result, verifyMatrices(ssbo430cIn.m), true);
11584
11585 VERIFY_IN(result, ssbo430rIn.m4c4r, 4, 4);
11586 VERIFY_IN(result, ssbo430rIn.m.inner.m3c4r, 3, 4);
11587 EXPECT(result, verifyMatrices(ssbo430rIn.m), true);
11588
11589 // Only assign to SSBO from a single invocation.
11590 if (gl_GlobalInvocationID.x == 0u)
11591 {
11592 ssbo140cOut.m4c4r = copyMat4(ssbo140cIn.m4c4r);
11593 copyMatrices(ssbo430cIn.m, ssbo140cOut.m);
11594 ssbo140cOut.m.m2c3r[1] = mat2x3(0);
11595 COPY(ssbo430cIn.m.m2c3r[1], ssbo140cOut.m.m2c3r[1], 2, 3);
11596
11597 ssbo140rOut.m4c4r = copyMat4(ssbo140rIn.m4c4r);
11598 copyMatrices(ssbo430rIn.m, ssbo140rOut.m);
11599 ssbo140rOut.m.inner.m3c4r = mat3x4(0);
11600 COPY(ssbo430rIn.m.inner.m3c4r, ssbo140rOut.m.inner.m3c4r, 3, 4);
11601
11602 ssbo430cOut.m4c4r = copyMat4(ssbo430cIn.m4c4r);
11603 copyMatrices(ssbo140cIn.m, ssbo430cOut.m);
11604 ssbo430cOut.m.m3c2r = mat3x2(0);
11605 COPY(ssbo430cIn.m.m3c2r, ssbo430cOut.m.m3c2r, 3, 2);
11606
11607 ssbo430rOut.m4c4r = copyMat4(ssbo430rIn.m4c4r);
11608 copyMatrices(ssbo140rIn.m, ssbo430rOut.m);
11609 ssbo430rOut.m.inner.m4c3r = mat4x3(0);
11610 COPY(ssbo430rIn.m.inner.m4c3r, ssbo430rOut.m.inner.m4c3r, 4, 3);
11611
11612 resultOut.success = uint(result);
11613 }
11614 })";
11615
11616 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
11617 EXPECT_GL_NO_ERROR();
11618
11619 constexpr size_t kMatrixCount = 7;
11620 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
11621 {4, 4}, {2, 2}, {2, 3}, {2, 3}, {3, 2}, {3, 4}, {4, 3},
11622 };
11623 constexpr bool kMatrixIsColMajor[kMatrixCount] = {
11624 true, false, false, false, false, false, false,
11625 };
11626
11627 float dataStd140ColMajor[kMatrixCount * 4 * 4] = {};
11628 float dataStd140RowMajor[kMatrixCount * 4 * 4] = {};
11629 float dataStd430ColMajor[kMatrixCount * 4 * 4] = {};
11630 float dataStd430RowMajor[kMatrixCount * 4 * 4] = {};
11631 float dataZeros[kMatrixCount * 4 * 4] = {};
11632
11633 const uint32_t sizeStd140ColMajor =
11634 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, dataStd140ColMajor, false, false);
11635 const uint32_t sizeStd140RowMajor =
11636 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, dataStd140RowMajor, false, true);
11637 const uint32_t sizeStd430ColMajor =
11638 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, dataStd430ColMajor, true, false);
11639 const uint32_t sizeStd430RowMajor =
11640 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, dataStd430RowMajor, true, true);
11641
11642 GLBuffer uboStd140ColMajor, uboStd140RowMajor;
11643 GLBuffer ssboStd140ColMajor, ssboStd140RowMajor;
11644 GLBuffer ssboStd430ColMajor, ssboStd430RowMajor;
11645 GLBuffer ssboStd140ColMajorOut, ssboStd140RowMajorOut;
11646 GLBuffer ssboStd430ColMajorOut, ssboStd430RowMajorOut;
11647
11648 InitBuffer(program, "Ubo140c", uboStd140ColMajor, 0, dataStd140ColMajor, sizeStd140ColMajor,
11649 true);
11650 InitBuffer(program, "Ubo140r", uboStd140RowMajor, 1, dataStd140RowMajor, sizeStd140RowMajor,
11651 true);
11652 InitBuffer(program, "Ssbo140c", ssboStd140ColMajor, 0, dataStd140ColMajor, sizeStd140ColMajor,
11653 false);
11654 InitBuffer(program, "Ssbo140r", ssboStd140RowMajor, 1, dataStd140RowMajor, sizeStd140RowMajor,
11655 false);
11656 InitBuffer(program, "Ssbo430c", ssboStd430ColMajor, 2, dataStd430ColMajor, sizeStd430ColMajor,
11657 false);
11658 InitBuffer(program, "Ssbo430r", ssboStd430RowMajor, 3, dataStd430RowMajor, sizeStd430RowMajor,
11659 false);
11660 InitBuffer(program, "Ssbo140cOut", ssboStd140ColMajorOut, 4, dataZeros, sizeStd140ColMajor,
11661 false);
11662 InitBuffer(program, "Ssbo140rOut", ssboStd140RowMajorOut, 5, dataZeros, sizeStd140RowMajor,
11663 false);
11664 InitBuffer(program, "Ssbo430cOut", ssboStd430ColMajorOut, 6, dataZeros, sizeStd430ColMajor,
11665 false);
11666 InitBuffer(program, "Ssbo430rOut", ssboStd430RowMajorOut, 7, dataZeros, sizeStd430RowMajor,
11667 false);
11668 EXPECT_GL_NO_ERROR();
11669
11670 GLBuffer outputBuffer;
11671 CreateOutputBuffer(&outputBuffer, 8);
11672
11673 glUseProgram(program);
11674 glDispatchCompute(1, 1, 1);
11675 EXPECT_GL_NO_ERROR();
11676 EXPECT_TRUE(VerifySuccess(outputBuffer));
11677
11678 EXPECT_TRUE(VerifyBuffer(ssboStd140ColMajorOut, dataStd140ColMajor, sizeStd140ColMajor));
11679 EXPECT_TRUE(VerifyBuffer(ssboStd140RowMajorOut, dataStd140RowMajor, sizeStd140RowMajor));
11680 EXPECT_TRUE(VerifyBuffer(ssboStd430ColMajorOut, dataStd430ColMajor, sizeStd430ColMajor));
11681 EXPECT_TRUE(VerifyBuffer(ssboStd430RowMajorOut, dataStd430RowMajor, sizeStd430RowMajor));
11682 }
11683
11684 // Test that array UBOs are transformed correctly.
TEST_P(GLSLTest_ES3,RowMajorMatrix_ReadMat4Test)11685 TEST_P(GLSLTest_ES3, RowMajorMatrix_ReadMat4Test)
11686 {
11687 constexpr char kFS[] = R"(#version 300 es
11688 precision highp float;
11689 out vec4 outColor;
11690
11691 layout(std140, row_major) uniform Ubo
11692 {
11693 mat4 m1;
11694 };
11695
11696 void main()
11697 {
11698 outColor = m1[3] / 255.0;
11699 })";
11700
11701 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11702 EXPECT_GL_NO_ERROR();
11703
11704 constexpr size_t kMatrixCount = 1;
11705 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
11706 {4, 4},
11707 };
11708 constexpr bool kMatrixIsColMajor[kMatrixCount] = {
11709 false,
11710 };
11711
11712 float data[kMatrixCount * 4 * 4] = {};
11713
11714 const uint32_t size =
11715 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
11716
11717 GLBuffer ubos;
11718
11719 InitBuffer(program, "Ubo", ubos, 0, data, size, true);
11720
11721 EXPECT_GL_NO_ERROR();
11722
11723 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
11724 EXPECT_PIXEL_NEAR(0, 0, 12, 13, 14, 15, 0);
11725 }
11726
11727 // Test that array UBOs are transformed correctly.
TEST_P(GLSLTest_ES3,RowMajorMatrix_ReadMat2x3Test)11728 TEST_P(GLSLTest_ES3, RowMajorMatrix_ReadMat2x3Test)
11729 {
11730 constexpr char kFS[] = R"(#version 300 es
11731 precision highp float;
11732 out vec4 outColor;
11733
11734 layout(std140, row_major) uniform Ubo
11735 {
11736 mat2x3 m1;
11737 };
11738
11739 void main()
11740 {
11741 outColor = vec4(m1[1], 0) / 255.0;
11742 })";
11743
11744 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11745 EXPECT_GL_NO_ERROR();
11746
11747 constexpr size_t kMatrixCount = 1;
11748 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
11749 {2, 3},
11750 };
11751 constexpr bool kMatrixIsColMajor[kMatrixCount] = {
11752 false,
11753 };
11754
11755 float data[kMatrixCount * 3 * 4] = {};
11756
11757 const uint32_t size =
11758 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
11759
11760 GLBuffer ubos;
11761
11762 InitBuffer(program, "Ubo", ubos, 0, data, size, true);
11763
11764 EXPECT_GL_NO_ERROR();
11765
11766 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
11767 EXPECT_PIXEL_NEAR(0, 0, 4, 5, 6, 0, 0);
11768 }
11769
TEST_P(GLSLTest_ES3,RowMajorMatrix_ReadMat3x2Test)11770 TEST_P(GLSLTest_ES3, RowMajorMatrix_ReadMat3x2Test)
11771 {
11772 constexpr char kFS[] = R"(#version 300 es
11773 precision highp float;
11774 out vec4 outColor;
11775
11776 layout(std140, row_major) uniform Ubo
11777 {
11778 mat3x2 m1;
11779 };
11780
11781 void main()
11782 {
11783 outColor = vec4(m1[2], 0, 0) / 255.0;
11784 })";
11785
11786 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11787 EXPECT_GL_NO_ERROR();
11788
11789 constexpr size_t kMatrixCount = 1;
11790 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
11791 {3, 2},
11792 };
11793 constexpr bool kMatrixIsColMajor[kMatrixCount] = {
11794 false,
11795 };
11796
11797 float data[kMatrixCount * 2 * 4] = {};
11798
11799 const uint32_t size =
11800 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
11801
11802 GLBuffer ubos;
11803
11804 InitBuffer(program, "Ubo", ubos, 0, data, size, true);
11805
11806 EXPECT_GL_NO_ERROR();
11807
11808 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
11809 EXPECT_PIXEL_NEAR(0, 0, 8, 9, 0, 0, 0);
11810 }
11811
TEST_P(GLSLTest_ES3,RowMajorMatrix_NestedExpression)11812 TEST_P(GLSLTest_ES3, RowMajorMatrix_NestedExpression)
11813 {
11814 // Many OpenGL drivers seem to fail this
11815 ANGLE_SKIP_TEST_IF((IsLinux() || IsMac()) && IsOpenGL());
11816
11817 constexpr char kFS[] = R"(#version 300 es
11818 precision mediump float;
11819
11820 uniform Ubo {
11821 layout(row_major) mat4 u_mat[3];
11822 layout(row_major) mat4 u_ndx[3];
11823 } stuff;
11824
11825 precision highp float;
11826 out vec4 outColor;
11827
11828 void main() {
11829 outColor = stuff.u_mat[int(stuff.u_ndx[1][1][3])][2] / 255.0;
11830 }
11831 )";
11832
11833 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11834 EXPECT_GL_NO_ERROR();
11835
11836 typedef float vec4[4];
11837 typedef vec4 mat4[4];
11838
11839 constexpr size_t kMatrixCount = 6;
11840 mat4 data[] = {
11841 {
11842 {0, 1, 2, 3}, //
11843 {4, 5, 6, 7}, //
11844 {8, 9, 10, 11}, //
11845 {12, 13, 14, 15}, //
11846 },
11847 {
11848 // +-- we should be looking up this column
11849 // V
11850 {0, 4, 8, 12}, //
11851 {1, 5, 9, 13}, //
11852 {2, 6, 10, 14}, //
11853 {3, 7, 11, 15}, //
11854 },
11855 {
11856 {0, 2, 4, 6}, //
11857 {8, 10, 12, 14}, //
11858 {16, 18, 20, 22}, //
11859 {24, 26, 28, 30}, //
11860 },
11861 {
11862 {0, 0, 0, 0}, //
11863 {0, 0, 0, 0}, //
11864 {0, 0, 0, 0}, //
11865 {0, 0, 0, 0}, //
11866 },
11867 {
11868 {0, 0, 0, 0}, //
11869 {0, 0, 0, 2}, //
11870 {0, 0, 0, 0}, //
11871 {0, 1, 0, 0},
11872 // ^
11873 // +-- we should be using this element
11874 },
11875 {
11876 {0, 0, 0, 0}, //
11877 {0, 0, 0, 0}, //
11878 {0, 0, 0, 0}, //
11879 {0, 0, 0, 0}, //
11880 },
11881 };
11882
11883 GLBuffer ubos;
11884 InitBuffer(program, "Ubo", ubos, 0, data, kMatrixCount, true);
11885 EXPECT_GL_NO_ERROR();
11886
11887 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
11888 EXPECT_PIXEL_NEAR(0, 0, 8, 9, 10, 11, 0);
11889 }
11890
11891 // Test that array UBOs are transformed correctly.
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ArrayBufferDeclaration)11892 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ArrayBufferDeclaration)
11893 {
11894 // Fails to compile the shader on Android: http://anglebug.com/42262483
11895 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
11896
11897 // http://anglebug.com/42262481
11898 ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsOpenGL());
11899
11900 // Fails on Mac on Intel and AMD: http://anglebug.com/42262487
11901 ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL() && (IsIntel() || IsAMD()));
11902
11903 // Fails on windows AMD on GL: http://anglebug.com/42262482
11904 ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL() && IsAMD());
11905
11906 // Fails on D3D due to mistranslation: http://anglebug.com/42262486
11907 ANGLE_SKIP_TEST_IF(IsD3D11());
11908
11909 constexpr char kFS[] = R"(#version 300 es
11910 precision highp float;
11911 out vec4 outColor;
11912
11913 layout(std140, column_major) uniform Ubo
11914 {
11915 mat4 m1;
11916 layout(row_major) mat4 m2;
11917 } ubo[3];
11918
11919 #define EXPECT(result, expression, value) if ((expression) != value) { result = false; }
11920
11921 #define VERIFY_IN(result, mat, cols, rows) \
11922 for (int c = 0; c < cols; ++c) \
11923 { \
11924 for (int r = 0; r < rows; ++r) \
11925 { \
11926 EXPECT(result, mat[c][r], float(c * 4 + r)); \
11927 } \
11928 }
11929
11930 void main()
11931 {
11932 bool result = true;
11933
11934 VERIFY_IN(result, ubo[0].m1, 4, 4);
11935 VERIFY_IN(result, ubo[0].m2, 4, 4);
11936
11937 VERIFY_IN(result, ubo[1].m1, 4, 4);
11938 VERIFY_IN(result, ubo[1].m2, 4, 4);
11939
11940 VERIFY_IN(result, ubo[2].m1, 4, 4);
11941 VERIFY_IN(result, ubo[2].m2, 4, 4);
11942
11943 outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
11944 })";
11945
11946 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11947 EXPECT_GL_NO_ERROR();
11948
11949 constexpr size_t kMatrixCount = 2;
11950 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
11951 {4, 4},
11952 {4, 4},
11953 };
11954 constexpr bool kMatrixIsColMajor[kMatrixCount] = {
11955 true,
11956 false,
11957 };
11958
11959 float data[kMatrixCount * 4 * 4] = {};
11960
11961 const uint32_t size =
11962 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
11963
11964 GLBuffer ubos[3];
11965
11966 InitBuffer(program, "Ubo[0]", ubos[0], 0, data, size, true);
11967 InitBuffer(program, "Ubo[1]", ubos[1], 0, data, size, true);
11968 InitBuffer(program, "Ubo[2]", ubos[2], 0, data, size, true);
11969
11970 EXPECT_GL_NO_ERROR();
11971
11972 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
11973 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
11974 }
11975
11976 // Test that side effects when transforming read operations are preserved.
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ReadSideEffect)11977 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ReadSideEffect)
11978 {
11979 // Fails on Mac on Intel and AMD: http://anglebug.com/42262487
11980 ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL() && (IsIntel() || IsAMD()));
11981
11982 // Fails on D3D due to mistranslation: http://anglebug.com/42262486
11983 ANGLE_SKIP_TEST_IF(IsD3D11());
11984
11985 constexpr char kFS[] = R"(#version 300 es
11986 precision highp float;
11987 out vec4 outColor;
11988
11989 struct S
11990 {
11991 mat2x3 m2[3];
11992 };
11993
11994 layout(std140, column_major) uniform Ubo
11995 {
11996 mat4 m1;
11997 layout(row_major) S s[2];
11998 } ubo;
11999
12000 #define EXPECT(result, expression, value) if ((expression) != value) { result = false; }
12001
12002 #define VERIFY_IN(result, mat, cols, rows) \
12003 for (int c = 0; c < cols; ++c) \
12004 { \
12005 for (int r = 0; r < rows; ++r) \
12006 { \
12007 EXPECT(result, mat[c][r], float(c * 4 + r)); \
12008 } \
12009 }
12010
12011 bool verify2x3(mat2x3 mat)
12012 {
12013 bool result = true;
12014
12015 for (int c = 0; c < 2; ++c)
12016 {
12017 for (int r = 0; r < 3; ++r)
12018 {
12019 EXPECT(result, mat[c][r], float(c * 4 + r));
12020 }
12021 }
12022
12023 return result;
12024 }
12025
12026 void main()
12027 {
12028 bool result = true;
12029
12030 int sideEffect = 0;
12031 VERIFY_IN(result, ubo.m1, 4, 4);
12032 EXPECT(result, verify2x3(ubo.s[0].m2[0]), true);
12033 EXPECT(result, verify2x3(ubo.s[0].m2[sideEffect += 1]), true);
12034 EXPECT(result, verify2x3(ubo.s[0].m2[sideEffect += 1]), true);
12035
12036 EXPECT(result, sideEffect, 2);
12037
12038 EXPECT(result, verify2x3(ubo.s[sideEffect = 1].m2[0]), true);
12039 EXPECT(result, verify2x3(ubo.s[1].m2[(sideEffect = 4) - 3]), true);
12040 EXPECT(result, verify2x3(ubo.s[1].m2[sideEffect - 2]), true);
12041
12042 EXPECT(result, sideEffect, 4);
12043
12044 outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12045 })";
12046
12047 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
12048 EXPECT_GL_NO_ERROR();
12049
12050 constexpr size_t kMatrixCount = 7;
12051 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
12052 {4, 4}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3},
12053 };
12054 constexpr bool kMatrixIsColMajor[kMatrixCount] = {
12055 true, false, false, false, false, false, false,
12056 };
12057
12058 float data[kMatrixCount * 4 * 4] = {};
12059
12060 const uint32_t size =
12061 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
12062
12063 GLBuffer ubo;
12064 InitBuffer(program, "Ubo", ubo, 0, data, size, true);
12065
12066 EXPECT_GL_NO_ERROR();
12067
12068 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
12069 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
12070 }
12071
12072 // Test that side effects respect the order of logical expression operands.
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ReadSideEffectOrder)12073 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ReadSideEffectOrder)
12074 {
12075 // http://anglebug.com/42262481
12076 ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsOpenGL());
12077
12078 // IntermTraverser::insertStatementsInParentBlock that's used to move side effects does not
12079 // respect the order of evaluation of logical expressions. http://anglebug.com/42262472.
12080 ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
12081
12082 constexpr char kFS[] = R"(#version 300 es
12083 precision highp float;
12084 out vec4 outColor;
12085
12086 layout(std140, column_major) uniform Ubo
12087 {
12088 mat4 m1;
12089 layout(row_major) mat4 m2[2];
12090 } ubo;
12091
12092 void main()
12093 {
12094 bool result = true;
12095
12096 int x = 0;
12097 if (x == 0 && ubo.m2[x = 1][1][1] == 5.0)
12098 {
12099 result = true;
12100 }
12101 else
12102 {
12103 result = false;
12104 }
12105
12106 outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12107 })";
12108
12109 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
12110 EXPECT_GL_NO_ERROR();
12111
12112 constexpr size_t kMatrixCount = 3;
12113 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
12114 {4, 4},
12115 {4, 4},
12116 {4, 4},
12117 };
12118 constexpr bool kMatrixIsColMajor[kMatrixCount] = {true, false, false};
12119
12120 float data[kMatrixCount * 4 * 4] = {};
12121
12122 const uint32_t size =
12123 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
12124
12125 GLBuffer ubo;
12126 InitBuffer(program, "Ubo", ubo, 0, data, size, true);
12127
12128 EXPECT_GL_NO_ERROR();
12129
12130 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
12131 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
12132 }
12133
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ReadSideEffectOrderSurroundedByLoop)12134 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ReadSideEffectOrderSurroundedByLoop)
12135 {
12136 // http://anglebug.com/42262481
12137 ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsOpenGL());
12138
12139 // IntermTraverser::insertStatementsInParentBlock that's used to move side effects does not
12140 // respect the order of evaluation of logical expressions. http://anglebug.com/42262472.
12141 ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
12142
12143 constexpr char kFS[] = R"(#version 300 es
12144 precision highp float;
12145 out vec4 outColor;
12146
12147 layout(std140, column_major) uniform Ubo
12148 {
12149 mat4 m1;
12150 layout(row_major) mat4 m2[2];
12151 } ubo;
12152
12153 void main()
12154 {
12155 bool result = false;
12156
12157 for(int x = 0; x < 1; ++x)
12158 {
12159 if (x == 0 && ubo.m2[x = 1][1][1] == 5.0) {
12160 result = true;
12161 }
12162 }
12163 outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12164 })";
12165
12166 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
12167 EXPECT_GL_NO_ERROR();
12168
12169 constexpr size_t kMatrixCount = 3;
12170 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
12171 {4, 4},
12172 {4, 4},
12173 {4, 4},
12174 };
12175 constexpr bool kMatrixIsColMajor[kMatrixCount] = {true, false, false};
12176
12177 float data[kMatrixCount * 4 * 4] = {};
12178
12179 const uint32_t size =
12180 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
12181
12182 GLBuffer ubo;
12183 InitBuffer(program, "Ubo", ubo, 0, data, size, true);
12184
12185 EXPECT_GL_NO_ERROR();
12186
12187 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
12188 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
12189 }
12190
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ReadSideEffectOrderInALoop)12191 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ReadSideEffectOrderInALoop)
12192 {
12193 // http://anglebug.com/42262481
12194 ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsOpenGL());
12195
12196 // IntermTraverser::insertStatementsInParentBlock that's used to move side effects does not
12197 // respect the order of evaluation of logical expressions. http://anglebug.com/42262472.
12198 ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
12199
12200 constexpr char kFS[] = R"(#version 300 es
12201 precision highp float;
12202 out vec4 outColor;
12203
12204 layout(std140, column_major) uniform Ubo
12205 {
12206 mat4 m1;
12207 layout(row_major) mat4 m2[2];
12208 } ubo;
12209
12210 void main()
12211 {
12212 bool result = false;
12213
12214 for(int x = 0; x == 0 && ubo.m2[x = 1][1][1] == 5.0;)
12215 {
12216 result = true;
12217 }
12218 outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12219 })";
12220
12221 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
12222 EXPECT_GL_NO_ERROR();
12223
12224 constexpr size_t kMatrixCount = 3;
12225 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
12226 {4, 4},
12227 {4, 4},
12228 {4, 4},
12229 };
12230 constexpr bool kMatrixIsColMajor[kMatrixCount] = {true, false, false};
12231
12232 float data[kMatrixCount * 4 * 4] = {};
12233
12234 const uint32_t size =
12235 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
12236
12237 GLBuffer ubo;
12238 InitBuffer(program, "Ubo", ubo, 0, data, size, true);
12239
12240 EXPECT_GL_NO_ERROR();
12241
12242 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
12243 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
12244 }
12245
12246 // Test that side effects respect short-circuit.
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ReadSideEffectShortCircuit)12247 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ReadSideEffectShortCircuit)
12248 {
12249 // Fails on Android: http://anglebug.com/42262483
12250 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
12251
12252 // IntermTraverser::insertStatementsInParentBlock that's used to move side effects does not
12253 // respect the order of evaluation of logical expressions. http://anglebug.com/42262472.
12254 ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
12255
12256 constexpr char kFS[] = R"(#version 300 es
12257 precision highp float;
12258 out vec4 outColor;
12259
12260 layout(std140, column_major) uniform Ubo
12261 {
12262 mat4 m1;
12263 layout(row_major) mat4 m2[2];
12264 } ubo;
12265
12266 void main()
12267 {
12268 bool result = true;
12269
12270 int x = 0;
12271 if (x == 1 && ubo.m2[x = 1][1][1] == 5.0)
12272 {
12273 // First x == 1 should prevent the side effect of the second expression (x = 1) from
12274 // being executed. If x = 1 is run before the if, the condition of the if would be true,
12275 // which is a failure.
12276 result = false;
12277 }
12278 if (x == 1)
12279 {
12280 result = false;
12281 }
12282
12283 outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12284 })";
12285
12286 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
12287 EXPECT_GL_NO_ERROR();
12288
12289 constexpr size_t kMatrixCount = 3;
12290 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
12291 {4, 4},
12292 {4, 4},
12293 {4, 4},
12294 };
12295 constexpr bool kMatrixIsColMajor[kMatrixCount] = {true, false, false};
12296
12297 float data[kMatrixCount * 4 * 4] = {};
12298
12299 const uint32_t size =
12300 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
12301
12302 GLBuffer ubo;
12303 InitBuffer(program, "Ubo", ubo, 0, data, size, true);
12304
12305 EXPECT_GL_NO_ERROR();
12306
12307 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
12308 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
12309 }
12310
12311 // Test that indexing swizzles out of bounds fails
TEST_P(GLSLTest_ES3,OutOfBoundsIndexingOfSwizzle)12312 TEST_P(GLSLTest_ES3, OutOfBoundsIndexingOfSwizzle)
12313 {
12314 constexpr char kFS[] = R"(#version 300 es
12315 precision mediump float;
12316 out vec4 colorOut;
12317 uniform vec3 colorIn;
12318
12319 void main()
12320 {
12321 colorOut = vec4(colorIn.yx[2], 0, 0, 1);
12322 })";
12323
12324 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
12325 EXPECT_EQ(0u, shader);
12326 }
12327
12328 // Test that indexing l-value swizzles work
TEST_P(GLSLTest_ES3,IndexingOfSwizzledLValuesShouldWork)12329 TEST_P(GLSLTest_ES3, IndexingOfSwizzledLValuesShouldWork)
12330 {
12331 constexpr char kFS[] = R"(#version 300 es
12332 precision mediump float;
12333 out vec4 oColor;
12334
12335 bool do_test() {
12336 highp vec3 expected = vec3(3.0, 2.0, 1.0);
12337 highp vec3 vec;
12338
12339 vec.yzx[2] = 3.0;
12340 vec.yzx[1] = 1.0;
12341 vec.yzx[0] = 2.0;
12342
12343 return vec == expected;
12344 }
12345
12346 void main()
12347 {
12348 oColor = vec4(do_test(), 0, 0, 1);
12349 })";
12350
12351 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
12352 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
12353 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
12354 ASSERT_GL_NO_ERROR();
12355 }
12356
12357 // Test that indexing r-value swizzles work
TEST_P(GLSLTest_ES3,IndexingOfSwizzledRValuesShouldWork)12358 TEST_P(GLSLTest_ES3, IndexingOfSwizzledRValuesShouldWork)
12359 {
12360 constexpr char kFS[] = R"(#version 300 es
12361 precision mediump float;
12362 out vec4 oColor;
12363
12364 bool do_test() {
12365 highp vec3 expected = vec3(3.0, 2.0, 1.0);
12366 highp vec3 vecA = vec3(1.0, 3.0, 2.0);
12367 highp vec3 vecB;
12368
12369 vecB.x = vecA.zxy[2];
12370 vecB.y = vecA.zxy[0];
12371 vecB.z = vecA.zxy[1];
12372
12373 return vecB == expected;
12374 }
12375
12376 void main()
12377 {
12378 oColor = vec4(do_test(), 0, 0, 1);
12379 })";
12380
12381 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
12382 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
12383 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
12384 ASSERT_GL_NO_ERROR();
12385 }
12386
12387 // Test that dynamic indexing of swizzled l-values should work.
12388 // A simple porting of sdk/tests/conformance2/glsl3/vector-dynamic-indexing-swizzled-lvalue.html
TEST_P(GLSLTest_ES3,DynamicIndexingOfSwizzledLValuesShouldWork)12389 TEST_P(GLSLTest_ES3, DynamicIndexingOfSwizzledLValuesShouldWork)
12390 {
12391 // The shader first assigns v.x to v.z (1.0)
12392 // Then v.y to v.y (2.0)
12393 // Then v.z to v.x (1.0)
12394 constexpr char kFS[] = R"(#version 300 es
12395 precision highp float;
12396 out vec4 my_FragColor;
12397 void main() {
12398 vec3 v = vec3(1.0, 2.0, 3.0);
12399 for (int i = 0; i < 3; i++) {
12400 v.zyx[i] = v[i];
12401 }
12402 my_FragColor = distance(v, vec3(1.0, 2.0, 1.0)) < 0.01 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12403 })";
12404
12405 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
12406 EXPECT_GL_NO_ERROR();
12407 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
12408 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
12409 }
12410
12411 // Another test for dynamic indexing of swizzled l-values.
TEST_P(GLSLTest_ES3,DynamicIndexingOfSwizzledLValuesShouldWork2)12412 TEST_P(GLSLTest_ES3, DynamicIndexingOfSwizzledLValuesShouldWork2)
12413 {
12414 constexpr char kFS[] = R"(#version 300 es
12415 precision mediump float;
12416 out vec4 oColor;
12417
12418 bool do_test() {
12419 highp vec3 expected = vec3(3.0, 2.0, 1.0);
12420 highp vec3 vec;
12421
12422 for (int i = 0; i < 3; ++i)
12423 {
12424 vec.zyx[i] = float(1 + i);
12425 }
12426
12427 return vec == expected;
12428 }
12429
12430 void main()
12431 {
12432 oColor = vec4(do_test(), 0, 0, 1);
12433 })";
12434
12435 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
12436 EXPECT_GL_NO_ERROR();
12437 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
12438 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
12439 }
12440
12441 // Test that dead code after discard, return, continue and branch are pruned.
TEST_P(GLSLTest_ES3,DeadCodeIsPruned)12442 TEST_P(GLSLTest_ES3, DeadCodeIsPruned)
12443 {
12444 constexpr char kFS[] = R"(#version 300 es
12445 precision mediump float;
12446 out vec4 color;
12447
12448 vec4 f(vec4 c)
12449 {
12450 return c;
12451 // dead code
12452 c = vec4(0, 0, 1, 1);
12453 return c;
12454 }
12455
12456 void main()
12457 {
12458 vec4 result = vec4(0, 0.5, 0, 1);
12459 int var = int(result.y * 2.2);
12460
12461 {
12462 if (result.x > 1.0)
12463 {
12464 discard;
12465 // dead code
12466 result = vec4(1, 0, 0, 1);
12467 }
12468 for (int i = 0; i < 3; ++i)
12469 {
12470 if (i < 2)
12471 {
12472 result = f(result);
12473 continue;
12474 // dead code
12475 result = vec4(1, 0, 1, 1);
12476 }
12477 result = f(result);
12478 break;
12479 // dead code
12480 result = vec4(1, 0, 1, 0);
12481 }
12482 while (true)
12483 {
12484 if (result.x > -1.0)
12485 {
12486 {
12487 result = f(result);
12488 {
12489 break;
12490 // dead code
12491 result = vec4(1, 0, 0, 0);
12492 }
12493 // dead code
12494 for (int j = 0; j < 3; ++j)
12495 {
12496 if (j > 1) continue;
12497 result = vec4(0, 0, 1, 0);
12498 color = vec4(0.5, 0, 0.5, 0.5);
12499 return;
12500 }
12501 }
12502 // dead code
12503 result = vec4(0.5, 0, 0, 0);
12504 }
12505 }
12506 switch (var)
12507 {
12508 case 2:
12509 return;
12510 // dead code
12511 color = vec4(0.25, 0, 0.25, 0.25);
12512 case 1:
12513 {
12514 // Make sure this path is not pruned due to the return in the previous case.
12515 result.y += 0.5;
12516 break;
12517 // dead code
12518 color = vec4(0.25, 0, 0, 0);
12519 }
12520 // dead code
12521 color = vec4(0, 0, 0.25, 0);
12522 break;
12523 default:
12524 break;
12525 }
12526
12527 color = result;
12528 return;
12529 // dead code
12530 color = vec4(0, 0, 0.5, 0);
12531 }
12532 // dead code
12533 color = vec4(0, 0, 0, 0.5);
12534 })";
12535
12536 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
12537
12538 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
12539 EXPECT_GL_NO_ERROR();
12540
12541 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
12542 }
12543
12544 // Regression test based on fuzzer issue. If a case has statements that are pruned, and those
12545 // pruned statements in turn have branches, and another case follows, a prior implementation of
12546 // dead-code elimination doubly pruned some statements.
TEST_P(GLSLTest_ES3,DeadCodeBranchInPrunedStatementsInCaseBeforeAnotherCase)12547 TEST_P(GLSLTest_ES3, DeadCodeBranchInPrunedStatementsInCaseBeforeAnotherCase)
12548 {
12549 constexpr char kFS[] = R"(#version 300 es
12550 precision mediump float;
12551 out vec4 color;
12552 void main()
12553 {
12554 color = vec4(0, 1, 0, 1);
12555 switch(0)
12556 {
12557 case 0:
12558 break;
12559 break;
12560 color = vec4(1, 0, 0, 1); // The bug was pruning this statement twice
12561 default:
12562 color = vec4(0, 0, 1, 1);
12563 break;
12564 }
12565 })";
12566
12567 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
12568
12569 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
12570 EXPECT_GL_NO_ERROR();
12571
12572 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
12573 }
12574
12575 // Test shader with all resources (default uniform, UBO, SSBO, image, sampler and atomic counter) to
12576 // make sure they are all linked ok. The front-end sorts these resources and traverses the list of
12577 // "uniforms" to find the range for each resource. A bug there was causing some resource ranges to
12578 // be empty in the presence of other resources.
TEST_P(GLSLTest_ES31,MixOfAllResources)12579 TEST_P(GLSLTest_ES31, MixOfAllResources)
12580 {
12581 // http://anglebug.com/42263641
12582 ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
12583
12584 constexpr char kComputeShader[] = R"(#version 310 es
12585 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
12586 layout(binding = 1, std430) buffer Output {
12587 uint ubo_value;
12588 uint default_value;
12589 uint sampler_value;
12590 uint ac_value;
12591 uint image_value;
12592 } outbuf;
12593 uniform Input {
12594 uint input_value;
12595 } inbuf;
12596 uniform uint default_uniform;
12597 uniform sampler2D smplr;
12598 layout(binding=0) uniform atomic_uint ac;
12599 layout(r32ui) uniform highp readonly uimage2D image;
12600
12601 void main(void)
12602 {
12603 outbuf.ubo_value = inbuf.input_value;
12604 outbuf.default_value = default_uniform;
12605 outbuf.sampler_value = uint(texture(smplr, vec2(0.5, 0.5)).x * 255.0);
12606 outbuf.ac_value = atomicCounterIncrement(ac);
12607 outbuf.image_value = imageLoad(image, ivec2(0, 0)).x;
12608 }
12609 )";
12610 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
12611 EXPECT_GL_NO_ERROR();
12612
12613 glUseProgram(program);
12614
12615 unsigned int inputData = 89u;
12616 GLBuffer inputBuffer;
12617 glBindBuffer(GL_UNIFORM_BUFFER, inputBuffer);
12618 glBufferData(GL_UNIFORM_BUFFER, sizeof(inputData), &inputData, GL_STATIC_DRAW);
12619 GLuint inputBufferIndex = glGetUniformBlockIndex(program, "Input");
12620 ASSERT_NE(inputBufferIndex, GL_INVALID_INDEX);
12621 glUniformBlockBinding(program, inputBufferIndex, 0);
12622 glBindBufferBase(GL_UNIFORM_BUFFER, 0, inputBuffer);
12623
12624 unsigned int outputInitData[5] = {0x12345678u, 0x09ABCDEFu, 0x56789ABCu, 0x0DEF1234u,
12625 0x13579BDFu};
12626 GLBuffer outputBuffer;
12627 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
12628 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), outputInitData, GL_STATIC_DRAW);
12629 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
12630 EXPECT_GL_NO_ERROR();
12631
12632 unsigned int uniformData = 456u;
12633 GLint uniformLocation = glGetUniformLocation(program, "default_uniform");
12634 ASSERT_NE(uniformLocation, -1);
12635 glUniform1ui(uniformLocation, uniformData);
12636
12637 unsigned int acData = 2u;
12638 GLBuffer atomicCounterBuffer;
12639 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
12640 glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(acData), &acData, GL_STATIC_DRAW);
12641 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
12642 EXPECT_GL_NO_ERROR();
12643
12644 unsigned int imageData = 33u;
12645 GLTexture image;
12646 glBindTexture(GL_TEXTURE_2D, image);
12647 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
12648 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &imageData);
12649 glBindImageTexture(0, image, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
12650 EXPECT_GL_NO_ERROR();
12651
12652 GLColor textureData(127, 18, 189, 211);
12653 GLTexture texture;
12654 glBindTexture(GL_TEXTURE_2D, texture);
12655 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &textureData);
12656 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12657 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12658 ASSERT_GL_NO_ERROR();
12659
12660 glDispatchCompute(1, 1, 1);
12661 EXPECT_GL_NO_ERROR();
12662
12663 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
12664
12665 // read back
12666 const GLuint *ptr = reinterpret_cast<const GLuint *>(
12667 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
12668 EXPECT_EQ(ptr[0], inputData);
12669 EXPECT_EQ(ptr[1], uniformData);
12670 EXPECT_NEAR(ptr[2], textureData.R, 1.0);
12671 EXPECT_EQ(ptr[3], acData);
12672 EXPECT_EQ(ptr[4], imageData);
12673
12674 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
12675 }
12676
12677 // Test that sending mixture of resources to functions works.
TEST_P(GLSLTest_ES31,MixOfResourcesAsFunctionArgs)12678 TEST_P(GLSLTest_ES31, MixOfResourcesAsFunctionArgs)
12679 {
12680 // http://anglebug.com/42264082
12681 ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
12682
12683 // anglebug.com/42262476 - no sampler array params on Android
12684 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
12685
12686 constexpr char kComputeShader[] = R"(#version 310 es
12687 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
12688
12689 layout(binding = 1, std430) buffer Output {
12690 uint success;
12691 } outbuf;
12692
12693 uniform uint initialAcValue;
12694 uniform sampler2D smplr[2][3];
12695 layout(binding=0) uniform atomic_uint ac;
12696
12697 bool sampler1DAndAtomicCounter(uvec3 sExpect, in sampler2D s[3], in atomic_uint a, uint aExpect)
12698 {
12699 uvec3 sResult = uvec3(uint(texture(s[0], vec2(0.5, 0.5)).x * 255.0),
12700 uint(texture(s[1], vec2(0.5, 0.5)).x * 255.0),
12701 uint(texture(s[2], vec2(0.5, 0.5)).x * 255.0));
12702 uint aResult = atomicCounterIncrement(a);
12703
12704 return sExpect == sResult && aExpect == aResult;
12705 }
12706
12707 bool sampler2DAndAtomicCounter(in sampler2D s[2][3], uint aInitial, in atomic_uint a)
12708 {
12709 bool success = true;
12710 success = sampler1DAndAtomicCounter(uvec3(0, 127, 255), s[0], a, aInitial) && success;
12711 success = sampler1DAndAtomicCounter(uvec3(31, 63, 191), s[1], a, aInitial + 1u) && success;
12712 return success;
12713 }
12714
12715 void main(void)
12716 {
12717 outbuf.success = uint(sampler2DAndAtomicCounter(smplr, initialAcValue, ac));
12718 }
12719 )";
12720 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
12721 EXPECT_GL_NO_ERROR();
12722
12723 glUseProgram(program);
12724
12725 unsigned int outputInitData = 0x12345678u;
12726 GLBuffer outputBuffer;
12727 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
12728 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
12729 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
12730 EXPECT_GL_NO_ERROR();
12731
12732 unsigned int acData = 2u;
12733 GLint uniformLocation = glGetUniformLocation(program, "initialAcValue");
12734 ASSERT_NE(uniformLocation, -1);
12735 glUniform1ui(uniformLocation, acData);
12736
12737 GLBuffer atomicCounterBuffer;
12738 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
12739 glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(acData), &acData, GL_STATIC_DRAW);
12740 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
12741 EXPECT_GL_NO_ERROR();
12742
12743 const std::array<GLColor, 6> kTextureData = {
12744 GLColor(0, 0, 0, 0), GLColor(127, 0, 0, 0), GLColor(255, 0, 0, 0),
12745 GLColor(31, 0, 0, 0), GLColor(63, 0, 0, 0), GLColor(191, 0, 0, 0),
12746 };
12747 GLTexture textures[2][3];
12748
12749 for (int dim1 = 0; dim1 < 2; ++dim1)
12750 {
12751 for (int dim2 = 0; dim2 < 3; ++dim2)
12752 {
12753 int textureUnit = dim1 * 3 + dim2;
12754 glActiveTexture(GL_TEXTURE0 + textureUnit);
12755 glBindTexture(GL_TEXTURE_2D, textures[dim1][dim2]);
12756 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
12757 &kTextureData[textureUnit]);
12758 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12759 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12760
12761 std::stringstream uniformName;
12762 uniformName << "smplr[" << dim1 << "][" << dim2 << "]";
12763 GLint samplerLocation = glGetUniformLocation(program, uniformName.str().c_str());
12764 EXPECT_NE(samplerLocation, -1);
12765 glUniform1i(samplerLocation, textureUnit);
12766 }
12767 }
12768 ASSERT_GL_NO_ERROR();
12769
12770 glDispatchCompute(1, 1, 1);
12771 EXPECT_GL_NO_ERROR();
12772
12773 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
12774
12775 // read back
12776 const GLuint *ptr = reinterpret_cast<const GLuint *>(
12777 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
12778 EXPECT_EQ(ptr[0], 1u);
12779
12780 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
12781 }
12782
12783 // Test that array of array of samplers used as function parameter with an index that has a
12784 // side-effect works.
TEST_P(GLSLTest_ES31,ArrayOfArrayOfSamplerAsFunctionParameterIndexedWithSideEffect)12785 TEST_P(GLSLTest_ES31, ArrayOfArrayOfSamplerAsFunctionParameterIndexedWithSideEffect)
12786 {
12787 // http://anglebug.com/42264082
12788 ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
12789
12790 // anglebug.com/42262476 - no sampler array params on Android
12791 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
12792
12793 // Skip if EXT_gpu_shader5 is not enabled.
12794 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
12795
12796 constexpr char kComputeShader[] = R"(#version 310 es
12797 #extension GL_EXT_gpu_shader5 : require
12798
12799 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
12800
12801 layout(binding = 1, std430) buffer Output {
12802 uint success;
12803 } outbuf;
12804
12805 uniform sampler2D smplr[2][3];
12806 layout(binding=0) uniform atomic_uint ac;
12807
12808 bool sampler1DAndAtomicCounter(uvec3 sExpect, in sampler2D s[3], in atomic_uint a, uint aExpect)
12809 {
12810 uvec3 sResult = uvec3(uint(texture(s[0], vec2(0.5, 0.5)).x * 255.0),
12811 uint(texture(s[1], vec2(0.5, 0.5)).x * 255.0),
12812 uint(texture(s[2], vec2(0.5, 0.5)).x * 255.0));
12813 uint aResult = atomicCounter(a);
12814
12815 return sExpect == sResult && aExpect == aResult;
12816 }
12817
12818 bool sampler2DAndAtomicCounter(in sampler2D s[2][3], uint aInitial, in atomic_uint a)
12819 {
12820 bool success = true;
12821 success = sampler1DAndAtomicCounter(uvec3(0, 127, 255),
12822 s[atomicCounterIncrement(ac)], a, aInitial + 1u) && success;
12823 success = sampler1DAndAtomicCounter(uvec3(31, 63, 191),
12824 s[atomicCounterIncrement(ac)], a, aInitial + 2u) && success;
12825 return success;
12826 }
12827
12828 void main(void)
12829 {
12830 outbuf.success = uint(sampler2DAndAtomicCounter(smplr, 0u, ac));
12831 }
12832 )";
12833 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
12834 EXPECT_GL_NO_ERROR();
12835
12836 glUseProgram(program);
12837
12838 unsigned int outputInitData = 0x12345678u;
12839 GLBuffer outputBuffer;
12840 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
12841 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
12842 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
12843 EXPECT_GL_NO_ERROR();
12844
12845 unsigned int acData = 0u;
12846 GLBuffer atomicCounterBuffer;
12847 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
12848 glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(acData), &acData, GL_STATIC_DRAW);
12849 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
12850 EXPECT_GL_NO_ERROR();
12851
12852 const std::array<GLColor, 6> kTextureData = {
12853 GLColor(0, 0, 0, 0), GLColor(127, 0, 0, 0), GLColor(255, 0, 0, 0),
12854 GLColor(31, 0, 0, 0), GLColor(63, 0, 0, 0), GLColor(191, 0, 0, 0),
12855 };
12856 GLTexture textures[2][3];
12857
12858 for (int dim1 = 0; dim1 < 2; ++dim1)
12859 {
12860 for (int dim2 = 0; dim2 < 3; ++dim2)
12861 {
12862 int textureUnit = dim1 * 3 + dim2;
12863 glActiveTexture(GL_TEXTURE0 + textureUnit);
12864 glBindTexture(GL_TEXTURE_2D, textures[dim1][dim2]);
12865 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
12866 &kTextureData[textureUnit]);
12867 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12868 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12869
12870 std::stringstream uniformName;
12871 uniformName << "smplr[" << dim1 << "][" << dim2 << "]";
12872 GLint samplerLocation = glGetUniformLocation(program, uniformName.str().c_str());
12873 EXPECT_NE(samplerLocation, -1);
12874 glUniform1i(samplerLocation, textureUnit);
12875 }
12876 }
12877 ASSERT_GL_NO_ERROR();
12878
12879 glDispatchCompute(1, 1, 1);
12880 EXPECT_GL_NO_ERROR();
12881
12882 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
12883
12884 // read back
12885 const GLuint *ptr = reinterpret_cast<const GLuint *>(
12886 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
12887 EXPECT_EQ(ptr[0], 1u);
12888
12889 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
12890 }
12891
testArrayOfArrayOfSamplerDynamicIndex(const APIExtensionVersion usedExtension)12892 void GLSLTest_ES31::testArrayOfArrayOfSamplerDynamicIndex(const APIExtensionVersion usedExtension)
12893 {
12894 ASSERT(usedExtension == APIExtensionVersion::EXT || usedExtension == APIExtensionVersion::OES);
12895
12896 int maxTextureImageUnits = 0;
12897 glGetIntegerv(GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
12898 ANGLE_SKIP_TEST_IF(maxTextureImageUnits < 24);
12899
12900 // anglebug.com/42262476 - no sampler array params on Android
12901 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
12902
12903 // http://anglebug.com/42264082
12904 ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
12905
12906 std::string computeShader;
12907 constexpr char kGLSLVersion[] = R"(#version 310 es
12908 )";
12909 constexpr char kGPUShaderEXT[] = R"(#extension GL_EXT_gpu_shader5 : require
12910 )";
12911 constexpr char kGPUShaderOES[] = R"(#extension GL_OES_gpu_shader5 : require
12912 )";
12913
12914 computeShader.append(kGLSLVersion);
12915 if (usedExtension == APIExtensionVersion::EXT)
12916 {
12917 computeShader.append(kGPUShaderEXT);
12918 }
12919 else
12920 {
12921 computeShader.append(kGPUShaderOES);
12922 }
12923
12924 constexpr char kComputeShaderBody[] = R"(
12925 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
12926
12927 layout(binding = 1, std430) buffer Output {
12928 uint success;
12929 } outbuf;
12930
12931 uniform sampler2D smplr[2][3][4];
12932 layout(binding=0) uniform atomic_uint ac;
12933
12934 bool sampler1DAndAtomicCounter(uvec4 sExpect, in sampler2D s[4], in atomic_uint a, uint aExpect)
12935 {
12936 uvec4 sResult = uvec4(uint(texture(s[0], vec2(0.5, 0.5)).x * 255.0),
12937 uint(texture(s[1], vec2(0.5, 0.5)).x * 255.0),
12938 uint(texture(s[2], vec2(0.5, 0.5)).x * 255.0),
12939 uint(texture(s[3], vec2(0.5, 0.5)).x * 255.0));
12940 uint aResult = atomicCounter(a);
12941
12942 return sExpect == sResult && aExpect == aResult;
12943 }
12944
12945 bool sampler3DAndAtomicCounter(in sampler2D s[2][3][4], uint aInitial, in atomic_uint a)
12946 {
12947 bool success = true;
12948 // [0][0]
12949 success = sampler1DAndAtomicCounter(uvec4(0, 8, 16, 24),
12950 s[atomicCounterIncrement(ac)][0], a, aInitial + 1u) && success;
12951 // [1][0]
12952 success = sampler1DAndAtomicCounter(uvec4(96, 104, 112, 120),
12953 s[atomicCounterIncrement(ac)][0], a, aInitial + 2u) && success;
12954 // [0][1]
12955 success = sampler1DAndAtomicCounter(uvec4(32, 40, 48, 56),
12956 s[0][atomicCounterIncrement(ac) - 1u], a, aInitial + 3u) && success;
12957 // [0][2]
12958 success = sampler1DAndAtomicCounter(uvec4(64, 72, 80, 88),
12959 s[0][atomicCounterIncrement(ac) - 1u], a, aInitial + 4u) && success;
12960 // [1][1]
12961 success = sampler1DAndAtomicCounter(uvec4(128, 136, 144, 152),
12962 s[1][atomicCounterIncrement(ac) - 3u], a, aInitial + 5u) && success;
12963 // [1][2]
12964 uint acValue = atomicCounterIncrement(ac); // Returns 5
12965 success = sampler1DAndAtomicCounter(uvec4(160, 168, 176, 184),
12966 s[acValue - 4u][atomicCounterIncrement(ac) - 4u], a, aInitial + 7u) && success;
12967
12968 return success;
12969 }
12970
12971 void main(void)
12972 {
12973 outbuf.success = uint(sampler3DAndAtomicCounter(smplr, 0u, ac));
12974 }
12975 )";
12976 computeShader.append(kComputeShaderBody);
12977
12978 ANGLE_GL_COMPUTE_PROGRAM(program, computeShader.c_str());
12979 EXPECT_GL_NO_ERROR();
12980
12981 glUseProgram(program);
12982
12983 unsigned int outputInitData = 0x12345678u;
12984 GLBuffer outputBuffer;
12985 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
12986 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
12987 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
12988 EXPECT_GL_NO_ERROR();
12989
12990 unsigned int acData = 0u;
12991 GLBuffer atomicCounterBuffer;
12992 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
12993 glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(acData), &acData, GL_STATIC_DRAW);
12994 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
12995 EXPECT_GL_NO_ERROR();
12996
12997 const std::array<GLColor, 24> kTextureData = {
12998 GLColor(0, 0, 0, 0), GLColor(8, 0, 0, 0), GLColor(16, 0, 0, 0), GLColor(24, 0, 0, 0),
12999 GLColor(32, 0, 0, 0), GLColor(40, 0, 0, 0), GLColor(48, 0, 0, 0), GLColor(56, 0, 0, 0),
13000 GLColor(64, 0, 0, 0), GLColor(72, 0, 0, 0), GLColor(80, 0, 0, 0), GLColor(88, 0, 0, 0),
13001 GLColor(96, 0, 0, 0), GLColor(104, 0, 0, 0), GLColor(112, 0, 0, 0), GLColor(120, 0, 0, 0),
13002 GLColor(128, 0, 0, 0), GLColor(136, 0, 0, 0), GLColor(144, 0, 0, 0), GLColor(152, 0, 0, 0),
13003 GLColor(160, 0, 0, 0), GLColor(168, 0, 0, 0), GLColor(176, 0, 0, 0), GLColor(184, 0, 0, 0),
13004 };
13005 GLTexture textures[2][3][4];
13006
13007 for (int dim1 = 0; dim1 < 2; ++dim1)
13008 {
13009 for (int dim2 = 0; dim2 < 3; ++dim2)
13010 {
13011 for (int dim3 = 0; dim3 < 4; ++dim3)
13012 {
13013 int textureUnit = (dim1 * 3 + dim2) * 4 + dim3;
13014 glActiveTexture(GL_TEXTURE0 + textureUnit);
13015 glBindTexture(GL_TEXTURE_2D, textures[dim1][dim2][dim3]);
13016 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
13017 &kTextureData[textureUnit]);
13018 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
13019 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
13020
13021 std::stringstream uniformName;
13022 uniformName << "smplr[" << dim1 << "][" << dim2 << "][" << dim3 << "]";
13023 GLint samplerLocation = glGetUniformLocation(program, uniformName.str().c_str());
13024 EXPECT_NE(samplerLocation, -1);
13025 glUniform1i(samplerLocation, textureUnit);
13026 }
13027 }
13028 }
13029 ASSERT_GL_NO_ERROR();
13030
13031 glDispatchCompute(1, 1, 1);
13032 EXPECT_GL_NO_ERROR();
13033
13034 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
13035
13036 // read back
13037 const GLuint *ptr = reinterpret_cast<const GLuint *>(
13038 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
13039 EXPECT_EQ(ptr[0], 1u);
13040
13041 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
13042 }
13043
13044 // Test that array of array of samplers can be indexed correctly with dynamic indices.
TEST_P(GLSLTest_ES31,ArrayOfArrayOfSamplerDynamicIndexEXT)13045 TEST_P(GLSLTest_ES31, ArrayOfArrayOfSamplerDynamicIndexEXT)
13046 {
13047 // Skip if EXT_gpu_shader5 is not enabled.
13048 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
13049 testArrayOfArrayOfSamplerDynamicIndex(APIExtensionVersion::EXT);
13050 }
13051
13052 // Test that array of array of samplers can be indexed correctly with dynamic indices.
TEST_P(GLSLTest_ES31,ArrayOfArrayOfSamplerDynamicIndexOES)13053 TEST_P(GLSLTest_ES31, ArrayOfArrayOfSamplerDynamicIndexOES)
13054 {
13055 // Skip if OES_gpu_shader5 is not enabled.
13056 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_gpu_shader5"));
13057 testArrayOfArrayOfSamplerDynamicIndex(APIExtensionVersion::OES);
13058 }
13059
13060 // Test that array of array of samplers can be indexed correctly with dynamic indices. Uses
13061 // samplers in structs.
TEST_P(GLSLTest_ES31,ArrayOfArrayOfSamplerInStructDynamicIndex)13062 TEST_P(GLSLTest_ES31, ArrayOfArrayOfSamplerInStructDynamicIndex)
13063 {
13064 // Skip if EXT_gpu_shader5 is not enabled.
13065 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
13066
13067 int maxTextureImageUnits = 0;
13068 glGetIntegerv(GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
13069 ANGLE_SKIP_TEST_IF(maxTextureImageUnits < 24);
13070
13071 // http://anglebug.com/42263641
13072 ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
13073
13074 // anglebug.com/42262476 - no sampler array params on Android
13075 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
13076
13077 // http://anglebug.com/42264082
13078 ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
13079
13080 constexpr char kComputeShader[] = R"(#version 310 es
13081 #extension GL_EXT_gpu_shader5 : require
13082
13083 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
13084
13085 layout(binding = 1, std430) buffer Output {
13086 uint success;
13087 } outbuf;
13088
13089 struct I
13090 {
13091 uint index;
13092 };
13093
13094 struct S
13095 {
13096 sampler2D smplr[4];
13097 I nested;
13098 };
13099
13100 struct T
13101 {
13102 S nested[3];
13103 uint tIndex;
13104 };
13105
13106 uniform T u[2];
13107
13108 uint getValue(in sampler2D s)
13109 {
13110 return uint(texture(s, vec2(0.5, 0.5)).x * 255.0);
13111 }
13112
13113 bool sampler1DTest(uvec4 sExpect, in sampler2D s[4])
13114 {
13115 uvec4 sResult = uvec4(getValue(s[0]), getValue(s[1]),
13116 getValue(s[2]), getValue(s[3]));
13117
13118 return sExpect == sResult;
13119 }
13120
13121 bool samplerTest(T t, uint N)
13122 {
13123 // u[N].tIndex == 0 + N*4
13124 // u[N].nested[0].nested.index == 1 + N*4
13125 // u[N].nested[1].nested.index == 2 + N*4
13126 // u[N].nested[2].nested.index == 3 + N*4
13127
13128 uvec4 colorOffset = N * 3u * 4u * uvec4(8);
13129
13130 bool success = true;
13131 // [N][0]
13132 success = sampler1DTest(uvec4(0, 8, 16, 24) + colorOffset,
13133 t.nested[t.nested[0].nested.index - t.tIndex - 1u].smplr) && success;
13134 // [N][1]
13135 success = sampler1DTest(uvec4(32, 40, 48, 56) + colorOffset,
13136 t.nested[t.nested[1].nested.index - t.tIndex - 1u].smplr) && success;
13137 // [N][2]
13138 success = sampler1DTest(uvec4(64, 72, 80, 88) + colorOffset,
13139 t.nested[t.nested[2].nested.index - t.tIndex - 1u].smplr) && success;
13140
13141 return success;
13142 }
13143
13144 bool uniformTest(T t, uint N)
13145 {
13146 // Also verify that expressions that involve structs-with-samplers are correct when not
13147 // referecing the sampler.
13148
13149 bool success = true;
13150 success = (t.nested[0].nested.index - t.tIndex == 1u) && success;
13151 success = (t.nested[1].nested.index - t.tIndex == 2u) && success;
13152 success = (t.nested[2].nested.index - t.tIndex == 3u) && success;
13153
13154 success = (t.nested[t.nested[0].nested.index - t.tIndex - 1u].nested.index - t.tIndex == 1u)
13155 && success;
13156 success = (t.nested[t.nested[0].nested.index - t.tIndex ].nested.index - t.tIndex == 2u)
13157 && success;
13158 success = (t.nested[t.nested[0].nested.index - t.tIndex + 1u].nested.index - t.tIndex == 3u)
13159 && success;
13160
13161 success = (t.nested[
13162 t.nested[
13163 t.nested[2].nested.index - t.tIndex - 1u // 2
13164 ].nested.index - t.tIndex - 2u // 1
13165 ].nested.index - t.tIndex // 2
13166 == 2u) && success;
13167
13168 return success;
13169 }
13170
13171 void main(void)
13172 {
13173 bool success = samplerTest(u[0], 0u) && samplerTest(u[1], 1u)
13174 && uniformTest(u[0], 0u) && uniformTest(u[1], 1u);
13175 outbuf.success = uint(success);
13176 }
13177 )";
13178 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
13179 EXPECT_GL_NO_ERROR();
13180
13181 glUseProgram(program);
13182
13183 unsigned int outputInitData = 0x12345678u;
13184 GLBuffer outputBuffer;
13185 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
13186 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
13187 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
13188 EXPECT_GL_NO_ERROR();
13189
13190 const std::array<GLColor, 24> kTextureData = {
13191 GLColor(0, 0, 0, 0), GLColor(8, 0, 0, 0), GLColor(16, 0, 0, 0), GLColor(24, 0, 0, 0),
13192 GLColor(32, 0, 0, 0), GLColor(40, 0, 0, 0), GLColor(48, 0, 0, 0), GLColor(56, 0, 0, 0),
13193 GLColor(64, 0, 0, 0), GLColor(72, 0, 0, 0), GLColor(80, 0, 0, 0), GLColor(88, 0, 0, 0),
13194 GLColor(96, 0, 0, 0), GLColor(104, 0, 0, 0), GLColor(112, 0, 0, 0), GLColor(120, 0, 0, 0),
13195 GLColor(128, 0, 0, 0), GLColor(136, 0, 0, 0), GLColor(144, 0, 0, 0), GLColor(152, 0, 0, 0),
13196 GLColor(160, 0, 0, 0), GLColor(168, 0, 0, 0), GLColor(176, 0, 0, 0), GLColor(184, 0, 0, 0),
13197 };
13198 GLTexture textures[2][3][4];
13199
13200 for (int dim1 = 0; dim1 < 2; ++dim1)
13201 {
13202 for (int dim2 = 0; dim2 < 3; ++dim2)
13203 {
13204 for (int dim3 = 0; dim3 < 4; ++dim3)
13205 {
13206 int textureUnit = (dim1 * 3 + dim2) * 4 + dim3;
13207 glActiveTexture(GL_TEXTURE0 + textureUnit);
13208 glBindTexture(GL_TEXTURE_2D, textures[dim1][dim2][dim3]);
13209 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
13210 &kTextureData[textureUnit]);
13211 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
13212 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
13213
13214 std::stringstream uniformName;
13215 uniformName << "u[" << dim1 << "].nested[" << dim2 << "].smplr[" << dim3 << "]";
13216 GLint samplerLocation = glGetUniformLocation(program, uniformName.str().c_str());
13217 EXPECT_NE(samplerLocation, -1);
13218 glUniform1i(samplerLocation, textureUnit);
13219 }
13220
13221 std::stringstream uniformName;
13222 uniformName << "u[" << dim1 << "].nested[" << dim2 << "].nested.index";
13223 GLint nestedIndexLocation = glGetUniformLocation(program, uniformName.str().c_str());
13224 EXPECT_NE(nestedIndexLocation, -1);
13225 glUniform1ui(nestedIndexLocation, dim1 * 4 + dim2 + 1);
13226 }
13227
13228 std::stringstream uniformName;
13229 uniformName << "u[" << dim1 << "].tIndex";
13230 GLint indexLocation = glGetUniformLocation(program, uniformName.str().c_str());
13231 EXPECT_NE(indexLocation, -1);
13232 glUniform1ui(indexLocation, dim1 * 4);
13233 }
13234 ASSERT_GL_NO_ERROR();
13235
13236 glDispatchCompute(1, 1, 1);
13237 EXPECT_GL_NO_ERROR();
13238
13239 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
13240
13241 // read back
13242 const GLuint *ptr = reinterpret_cast<const GLuint *>(
13243 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
13244 EXPECT_EQ(ptr[0], 1u);
13245
13246 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
13247 }
13248
13249 // Test that array of array of samplers work when indexed with an expression that's derived from an
13250 // array of array of samplers.
TEST_P(GLSLTest_ES31,ArrayOfArrayOfSamplerIndexedWithArrayOfArrayOfSamplers)13251 TEST_P(GLSLTest_ES31, ArrayOfArrayOfSamplerIndexedWithArrayOfArrayOfSamplers)
13252 {
13253 // Skip if EXT_gpu_shader5 is not enabled.
13254 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
13255
13256 // anglebug.com/42262476 - no sampler array params on Android
13257 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
13258
13259 constexpr char kComputeShader[] = R"(#version 310 es
13260 #extension GL_EXT_gpu_shader5 : require
13261
13262 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
13263
13264 layout(binding = 1, std430) buffer Output {
13265 uint success;
13266 } outbuf;
13267
13268 uniform sampler2D smplr[2][3];
13269
13270 uint getValue(in sampler2D s)
13271 {
13272 return uint(texture(s, vec2(0.5, 0.5)).x * 255.0);
13273 }
13274
13275 bool runTest(in sampler2D s[2][3])
13276 {
13277 // s[0][0] should contain 2
13278 // s[0][1] should contain 0
13279 // s[0][2] should contain 1
13280 // s[1][0] should contain 1
13281 // s[1][1] should contain 2
13282 // s[1][2] should contain 0
13283
13284 uint result = getValue(
13285 s[
13286 getValue(
13287 s[
13288 getValue(s[0][1]) // 0
13289 ][
13290 getValue(s[0][0]) // 2
13291 ]
13292 ) // s[0][2] -> 1
13293 ][
13294 getValue(
13295 s[
13296 getValue(s[1][0]) // 1
13297 ][
13298 getValue(s[1][1]) // 2
13299 ]
13300 ) // s[1][2] -> 0
13301 ]
13302 ); // s[1][0] -> 1
13303
13304 return result == 1u;
13305 }
13306
13307 void main(void)
13308 {
13309 outbuf.success = uint(runTest(smplr));
13310 }
13311 )";
13312 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
13313 EXPECT_GL_NO_ERROR();
13314
13315 glUseProgram(program);
13316
13317 unsigned int outputInitData = 0x12345678u;
13318 GLBuffer outputBuffer;
13319 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
13320 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
13321 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
13322 EXPECT_GL_NO_ERROR();
13323
13324 const std::array<GLColor, 6> kTextureData = {
13325 GLColor(2, 0, 0, 0), GLColor(0, 0, 0, 0), GLColor(1, 0, 0, 0),
13326 GLColor(1, 0, 0, 0), GLColor(2, 0, 0, 0), GLColor(0, 0, 0, 0),
13327 };
13328 GLTexture textures[2][3];
13329
13330 for (int dim1 = 0; dim1 < 2; ++dim1)
13331 {
13332 for (int dim2 = 0; dim2 < 3; ++dim2)
13333 {
13334 int textureUnit = dim1 * 3 + dim2;
13335 glActiveTexture(GL_TEXTURE0 + textureUnit);
13336 glBindTexture(GL_TEXTURE_2D, textures[dim1][dim2]);
13337 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
13338 &kTextureData[textureUnit]);
13339 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
13340 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
13341
13342 std::stringstream uniformName;
13343 uniformName << "smplr[" << dim1 << "][" << dim2 << "]";
13344 GLint samplerLocation = glGetUniformLocation(program, uniformName.str().c_str());
13345 EXPECT_NE(samplerLocation, -1);
13346 glUniform1i(samplerLocation, textureUnit);
13347 }
13348 }
13349 ASSERT_GL_NO_ERROR();
13350
13351 glDispatchCompute(1, 1, 1);
13352 EXPECT_GL_NO_ERROR();
13353
13354 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
13355
13356 // read back
13357 const GLuint *ptr = reinterpret_cast<const GLuint *>(
13358 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
13359 EXPECT_EQ(ptr[0], 1u);
13360
13361 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
13362 }
13363
13364 // Test that multiple nested assignments are handled correctly.
TEST_P(GLSLTest_ES31,MixedRowAndColumnMajorMatrices_WriteSideEffect)13365 TEST_P(GLSLTest_ES31, MixedRowAndColumnMajorMatrices_WriteSideEffect)
13366 {
13367 // http://anglebug.com/42262475
13368 ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGL());
13369
13370 // Fails on windows AMD on GL: http://anglebug.com/42262482
13371 ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL() && IsAMD());
13372 // http://anglebug.com/42263924
13373 ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
13374
13375 // Fails on D3D due to mistranslation: http://anglebug.com/42262486
13376 ANGLE_SKIP_TEST_IF(IsD3D11());
13377
13378 constexpr char kCS[] = R"(#version 310 es
13379 precision highp float;
13380 layout(local_size_x=1) in;
13381
13382 layout(std140, column_major) uniform Ubo
13383 {
13384 mat4 m1;
13385 layout(row_major) mat4 m2;
13386 } ubo;
13387
13388 layout(std140, row_major, binding = 0) buffer Ssbo
13389 {
13390 layout(column_major) mat4 m1;
13391 mat4 m2;
13392 } ssbo;
13393
13394 layout(std140, binding = 1) buffer Result
13395 {
13396 uint success;
13397 } resultOut;
13398
13399 void main()
13400 {
13401 bool result = true;
13402
13403 // Only assign to SSBO from a single invocation.
13404 if (gl_GlobalInvocationID.x == 0u)
13405 {
13406 if ((ssbo.m2 = ssbo.m1 = ubo.m1) != ubo.m2)
13407 {
13408 result = false;
13409 }
13410
13411 resultOut.success = uint(result);
13412 }
13413 })";
13414
13415 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
13416 EXPECT_GL_NO_ERROR();
13417
13418 constexpr size_t kMatrixCount = 2;
13419 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
13420 {4, 4},
13421 {4, 4},
13422 };
13423 constexpr bool kMatrixIsColMajor[kMatrixCount] = {
13424 true,
13425 false,
13426 };
13427
13428 float data[kMatrixCount * 4 * 4] = {};
13429 float zeros[kMatrixCount * 4 * 4] = {};
13430
13431 const uint32_t size =
13432 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
13433
13434 GLBuffer ubo, ssbo;
13435
13436 InitBuffer(program, "Ubo", ubo, 0, data, size, true);
13437 InitBuffer(program, "Ssbo", ssbo, 0, zeros, size, false);
13438 EXPECT_GL_NO_ERROR();
13439
13440 GLBuffer outputBuffer;
13441 CreateOutputBuffer(&outputBuffer, 1);
13442
13443 glUseProgram(program);
13444 glDispatchCompute(1, 1, 1);
13445 EXPECT_GL_NO_ERROR();
13446 EXPECT_TRUE(VerifySuccess(outputBuffer));
13447
13448 EXPECT_TRUE(VerifyBuffer(ssbo, data, size));
13449 }
13450
13451 // Test that assignments to array of array of matrices are handled correctly.
TEST_P(GLSLTest_ES31,MixedRowAndColumnMajorMatrices_WriteArrayOfArray)13452 TEST_P(GLSLTest_ES31, MixedRowAndColumnMajorMatrices_WriteArrayOfArray)
13453 {
13454 // Fails on windows AMD on GL: http://anglebug.com/42262482
13455 ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL() && IsAMD());
13456 // http://anglebug.com/42263924
13457 ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
13458
13459 // Fails on D3D due to mistranslation: http://anglebug.com/42262486
13460 ANGLE_SKIP_TEST_IF(IsD3D11());
13461
13462 // Fails compiling shader on Android/Vulkan. http://anglebug.com/42262919
13463 ANGLE_SKIP_TEST_IF(IsAndroid() && IsVulkan());
13464
13465 // Fails on ARM on Vulkan. http://anglebug.com/42263107
13466 ANGLE_SKIP_TEST_IF(IsARM() && IsVulkan());
13467
13468 constexpr char kCS[] = R"(#version 310 es
13469 precision highp float;
13470 layout(local_size_x=1) in;
13471
13472 layout(std140, column_major) uniform Ubo
13473 {
13474 mat4 m1;
13475 layout(row_major) mat4 m2[2][3];
13476 } ubo;
13477
13478 layout(std140, row_major, binding = 0) buffer Ssbo
13479 {
13480 layout(column_major) mat4 m1;
13481 mat4 m2[2][3];
13482 } ssbo;
13483
13484 layout(std140, binding = 1) buffer Result
13485 {
13486 uint success;
13487 } resultOut;
13488
13489 void main()
13490 {
13491 bool result = true;
13492
13493 // Only assign to SSBO from a single invocation.
13494 if (gl_GlobalInvocationID.x == 0u)
13495 {
13496 ssbo.m1 = ubo.m1;
13497 ssbo.m2 = ubo.m2;
13498
13499 resultOut.success = uint(result);
13500 }
13501 })";
13502
13503 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
13504 EXPECT_GL_NO_ERROR();
13505
13506 constexpr size_t kMatrixCount = 7;
13507 constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
13508 {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4},
13509 };
13510 constexpr bool kMatrixIsColMajor[kMatrixCount] = {
13511 true, false, false, false, false, false, false,
13512 };
13513
13514 float data[kMatrixCount * 4 * 4] = {};
13515 float zeros[kMatrixCount * 4 * 4] = {};
13516
13517 const uint32_t size =
13518 FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
13519
13520 GLBuffer ubo, ssbo;
13521
13522 InitBuffer(program, "Ubo", ubo, 0, data, size, true);
13523 InitBuffer(program, "Ssbo", ssbo, 0, zeros, size, false);
13524 EXPECT_GL_NO_ERROR();
13525
13526 GLBuffer outputBuffer;
13527 CreateOutputBuffer(&outputBuffer, 1);
13528
13529 glUseProgram(program);
13530 glDispatchCompute(1, 1, 1);
13531 EXPECT_GL_NO_ERROR();
13532 EXPECT_TRUE(VerifySuccess(outputBuffer));
13533
13534 EXPECT_TRUE(VerifyBuffer(ssbo, data, size));
13535 }
13536
13537 // Verify that types used differently (in different block storages, differently qualified etc) work
13538 // when copied around.
TEST_P(GLSLTest_ES31,TypesUsedInDifferentBlockStorages)13539 TEST_P(GLSLTest_ES31, TypesUsedInDifferentBlockStorages)
13540 {
13541 constexpr char kCS[] = R"(#version 310 es
13542 precision highp float;
13543 layout(local_size_x=1) in;
13544
13545 struct Inner
13546 {
13547 mat3x2 m;
13548 float f[3];
13549 uvec2 u[2][4];
13550 ivec3 i;
13551 mat2x3 m2[3][2];
13552 };
13553
13554 struct Outer
13555 {
13556 Inner i[2];
13557 };
13558
13559 layout(std140, column_major) uniform Ubo140c
13560 {
13561 mat2 m;
13562 layout(row_major) Outer o;
13563 } ubo140cIn;
13564
13565 layout(std430, row_major, binding = 0) buffer Ubo430r
13566 {
13567 mat2 m;
13568 layout(column_major) Outer o;
13569 } ubo430rIn;
13570
13571 layout(std140, column_major, binding = 1) buffer Ssbo140c
13572 {
13573 layout(row_major) mat2 m[2];
13574 Outer o;
13575 layout(row_major) Inner i;
13576 } ssbo140cOut;
13577
13578 layout(std430, row_major, binding = 2) buffer Ssbo430r
13579 {
13580 layout(column_major) mat2 m[2];
13581 Outer o;
13582 layout(column_major) Inner i;
13583 } ssbo430rOut;
13584
13585 void writeArgToStd140(uvec2 u[2][4], int innerIndex)
13586 {
13587 ssbo140cOut.o.i[innerIndex].u = u;
13588 }
13589
13590 void writeBlockArgToStd140(Inner i, int innerIndex)
13591 {
13592 ssbo140cOut.o.i[innerIndex] = i;
13593 }
13594
13595 mat2x3[3][2] readFromStd140(int innerIndex)
13596 {
13597 return ubo140cIn.o.i[0].m2;
13598 }
13599
13600 Inner readBlockFromStd430(int innerIndex)
13601 {
13602 return ubo430rIn.o.i[innerIndex];
13603 }
13604
13605 void copyFromStd140(out Inner i)
13606 {
13607 i = ubo140cIn.o.i[1];
13608 }
13609
13610 void main(){
13611 // Directly copy from one layout to another.
13612 ssbo140cOut.m[0] = ubo140cIn.m;
13613 ssbo140cOut.m[1] = ubo430rIn.m;
13614 ssbo140cOut.o.i[0].m = ubo140cIn.o.i[0].m;
13615 ssbo140cOut.o.i[0].f = ubo140cIn.o.i[0].f;
13616 ssbo140cOut.o.i[0].i = ubo140cIn.o.i[0].i;
13617
13618 // Read from block and pass to function.
13619 writeArgToStd140(ubo140cIn.o.i[0].u, 0);
13620 writeBlockArgToStd140(ubo430rIn.o.i[0], 1);
13621
13622 // Have function return value read from block.
13623 ssbo140cOut.o.i[0].m2 = readFromStd140(0);
13624
13625 // Have function fill in value as out parameter.
13626 copyFromStd140(ssbo140cOut.i);
13627
13628 // Initialize local variable.
13629 mat2 mStd140 = ubo140cIn.m;
13630
13631 // Copy to variable, through multiple assignments.
13632 mat2 mStd430, temp;
13633 mStd430 = temp = ubo430rIn.m;
13634
13635 // Copy from local variable
13636 ssbo430rOut.m[0] = mStd140;
13637 ssbo430rOut.m[1] = mStd430;
13638
13639 // Construct from struct.
13640 Inner iStd140 = ubo140cIn.o.i[1];
13641 Outer oStd140 = Outer(Inner[2](iStd140, ubo430rIn.o.i[1]));
13642
13643 // Copy struct from local variable.
13644 ssbo430rOut.o = oStd140;
13645
13646 // Construct from arrays
13647 Inner iStd430 = Inner(ubo430rIn.o.i[1].m,
13648 ubo430rIn.o.i[1].f,
13649 ubo430rIn.o.i[1].u,
13650 ubo430rIn.o.i[1].i,
13651 ubo430rIn.o.i[1].m2);
13652 ssbo430rOut.i = iStd430;
13653 })";
13654
13655 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
13656 EXPECT_GL_NO_ERROR();
13657
13658 // Test data, laid out with padding (0) based on std140/std430 rules.
13659 // clang-format off
13660 const std::vector<float> ubo140cData = {
13661 // m (mat2, column-major)
13662 1, 2, 0, 0, 3, 4, 0, 0,
13663
13664 // o.i[0].m (mat3x2, row-major)
13665 5, 7, 9, 0, 6, 8, 10, 0,
13666 // o.i[0].f (float[3])
13667 12, 0, 0, 0, 13, 0, 0, 0, 14, 0, 0, 0,
13668 // o.i[0].u (uvec2[2][4])
13669 15, 16, 0, 0, 17, 18, 0, 0, 19, 20, 0, 0, 21, 22, 0, 0,
13670 23, 24, 0, 0, 25, 26, 0, 0, 27, 28, 0, 0, 29, 30, 0, 0,
13671 // o.i[0].i (ivec3)
13672 31, 32, 33, 0,
13673 // o.i[0].m2 (mat2x3[3][2], row-major)
13674 34, 37, 0, 0, 35, 38, 0, 0, 36, 39, 0, 0,
13675 40, 43, 0, 0, 41, 44, 0, 0, 42, 45, 0, 0,
13676 46, 49, 0, 0, 47, 50, 0, 0, 48, 51, 0, 0,
13677 52, 55, 0, 0, 53, 56, 0, 0, 54, 57, 0, 0,
13678 58, 61, 0, 0, 59, 62, 0, 0, 60, 63, 0, 0,
13679 64, 67, 0, 0, 65, 68, 0, 0, 66, 69, 0, 0,
13680
13681 // o.i[1].m (mat3x2, row-major)
13682 70, 72, 74, 0, 71, 73, 75, 0,
13683 // o.i[1].f (float[3])
13684 77, 0, 0, 0, 78, 0, 0, 0, 79, 0, 0, 0,
13685 // o.i[1].u (uvec2[2][4])
13686 80, 81, 0, 0, 82, 83, 0, 0, 84, 85, 0, 0, 86, 87, 0, 0,
13687 88, 89, 0, 0, 90, 91, 0, 0, 92, 93, 0, 0, 94, 95, 0, 0,
13688 // o.i[1].i (ivec3)
13689 96, 97, 98, 0,
13690 // o.i[1].m2 (mat2x3[3][2], row-major)
13691 99, 102, 0, 0, 100, 103, 0, 0, 101, 104, 0, 0,
13692 105, 108, 0, 0, 106, 109, 0, 0, 107, 110, 0, 0,
13693 111, 114, 0, 0, 112, 115, 0, 0, 113, 116, 0, 0,
13694 117, 120, 0, 0, 118, 121, 0, 0, 119, 122, 0, 0,
13695 123, 126, 0, 0, 124, 127, 0, 0, 125, 128, 0, 0,
13696 129, 132, 0, 0, 130, 133, 0, 0, 131, 134, 0, 0,
13697 };
13698 const std::vector<float> ubo430rData = {
13699 // m (mat2, row-major)
13700 135, 137, 136, 138,
13701
13702 // o.i[0].m (mat3x2, column-major)
13703 139, 140, 141, 142, 143, 144,
13704 // o.i[0].f (float[3])
13705 146, 147, 148, 0,
13706 // o.i[0].u (uvec2[2][4])
13707 149, 150, 151, 152, 153, 154, 155, 156,
13708 157, 158, 159, 160, 161, 162, 163, 164, 0, 0,
13709 // o.i[0].i (ivec3)
13710 165, 166, 167, 0,
13711 // o.i[0].m2 (mat2x3[3][2], column-major)
13712 168, 169, 170, 0, 171, 172, 173, 0,
13713 174, 175, 176, 0, 177, 178, 179, 0,
13714 180, 181, 182, 0, 183, 184, 185, 0,
13715 186, 187, 188, 0, 189, 190, 191, 0,
13716 192, 193, 194, 0, 195, 196, 197, 0,
13717 198, 199, 200, 0, 201, 202, 203, 0,
13718
13719 // o.i[1].m (mat3x2, column-major)
13720 204, 205, 206, 207, 208, 209,
13721 // o.i[1].f (float[3])
13722 211, 212, 213, 0,
13723 // o.i[1].u (uvec2[2][4])
13724 214, 215, 216, 217, 218, 219, 220, 221,
13725 222, 223, 224, 225, 226, 227, 228, 229, 0, 0,
13726 // o.i[1].i (ivec3)
13727 230, 231, 232, 0,
13728 // o.i[1].m2 (mat2x3[3][2], column-major)
13729 233, 234, 235, 0, 236, 237, 238, 0,
13730 239, 240, 241, 0, 242, 243, 244, 0,
13731 245, 246, 247, 0, 248, 249, 250, 0,
13732 251, 252, 253, 0, 254, 255, 256, 0,
13733 257, 258, 259, 0, 260, 261, 262, 0,
13734 263, 264, 265, 0, 266, 267, 268, 0,
13735 };
13736 const std::vector<float> ssbo140cExpect = {
13737 // m (mat2[2], row-major), m[0] copied from ubo140cIn.m, m[1] from ubo430rIn.m
13738 1, 3, 0, 0, 2, 4, 0, 0,
13739 135, 137, 0, 0, 136, 138, 0, 0,
13740
13741 // o.i[0].m (mat3x2, column-major), copied from ubo140cIn.o.i[0].m
13742 5, 6, 0, 0, 7, 8, 0, 0, 9, 10, 0, 0,
13743 // o.i[0].f (float[3]), copied from ubo140cIn.o.i[0].f
13744 12, 0, 0, 0, 13, 0, 0, 0, 14, 0, 0, 0,
13745 // o.i[0].u (uvec2[2][4]), copied from ubo140cIn.o.i[0].u
13746 15, 16, 0, 0, 17, 18, 0, 0, 19, 20, 0, 0, 21, 22, 0, 0,
13747 23, 24, 0, 0, 25, 26, 0, 0, 27, 28, 0, 0, 29, 30, 0, 0,
13748 // o.i[0].i (ivec3), copied from ubo140cIn.o.i[0].i
13749 31, 32, 33, 0,
13750 // o.i[0].m2 (mat2x3[3][2], column-major), copied from ubo140cIn.o.i[0].m2
13751 34, 35, 36, 0, 37, 38, 39, 0,
13752 40, 41, 42, 0, 43, 44, 45, 0,
13753 46, 47, 48, 0, 49, 50, 51, 0,
13754 52, 53, 54, 0, 55, 56, 57, 0,
13755 58, 59, 60, 0, 61, 62, 63, 0,
13756 64, 65, 66, 0, 67, 68, 69, 0,
13757
13758 // o.i[1].m (mat3x2, column-major), copied from ubo430rIn.o.i[0].m
13759 139, 140, 0, 0, 141, 142, 0, 0, 143, 144, 0, 0,
13760 // o.i[1].f (float[3]), copied from ubo430rIn.o.i[0].f
13761 146, 0, 0, 0, 147, 0, 0, 0, 148, 0, 0, 0,
13762 // o.i[1].u (uvec2[2][4]), copied from ubo430rIn.o.i[0].u
13763 149, 150, 0, 0, 151, 152, 0, 0, 153, 154, 0, 0, 155, 156, 0, 0,
13764 157, 158, 0, 0, 159, 160, 0, 0, 161, 162, 0, 0, 163, 164, 0, 0,
13765 // o.i[1].i (ivec3), copied from ubo430rIn.o.i[0].i
13766 165, 166, 167, 0,
13767 // o.i[1].m2 (mat2x3[3][2], column-major), copied from ubo430rIn.o.i[0].m2
13768 168, 169, 170, 0, 171, 172, 173, 0,
13769 174, 175, 176, 0, 177, 178, 179, 0,
13770 180, 181, 182, 0, 183, 184, 185, 0,
13771 186, 187, 188, 0, 189, 190, 191, 0,
13772 192, 193, 194, 0, 195, 196, 197, 0,
13773 198, 199, 200, 0, 201, 202, 203, 0,
13774
13775 // i.m (mat3x2, row-major), copied from ubo140cIn.o.i[1].m
13776 70, 72, 74, 0, 71, 73, 75, 0,
13777 // i.f (float[3]), copied from ubo140cIn.o.i[1].f
13778 77, 0, 0, 0, 78, 0, 0, 0, 79, 0, 0, 0,
13779 // i.u (uvec2[2][4]), copied from ubo430rIn.o.i[1].u
13780 80, 81, 0, 0, 82, 83, 0, 0, 84, 85, 0, 0, 86, 87, 0, 0,
13781 88, 89, 0, 0, 90, 91, 0, 0, 92, 93, 0, 0, 94, 95, 0, 0,
13782 // i.i (ivec3), copied from ubo140cIn.o.i[1].i
13783 96, 97, 98, 0,
13784 // i.m2 (mat2x3[3][2], row-major), copied from ubo140cIn.o.i[1].m2
13785 99, 102, 0, 0, 100, 103, 0, 0, 101, 104, 0, 0,
13786 105, 108, 0, 0, 106, 109, 0, 0, 107, 110, 0, 0,
13787 111, 114, 0, 0, 112, 115, 0, 0, 113, 116, 0, 0,
13788 117, 120, 0, 0, 118, 121, 0, 0, 119, 122, 0, 0,
13789 123, 126, 0, 0, 124, 127, 0, 0, 125, 128, 0, 0,
13790 129, 132, 0, 0, 130, 133, 0, 0, 131, 134, 0, 0,
13791 };
13792 const std::vector<float> ssbo430rExpect = {
13793 // m (mat2[2], column-major), m[0] copied from ubo140cIn.m, m[1] from ubo430rIn.m
13794 1, 2, 3, 4,
13795 135, 136, 137, 138,
13796
13797 // o.i[0].m (mat3x2, row-major), copied from ubo140cIn.o.i[1].m
13798 70, 72, 74, 0, 71, 73, 75, 0,
13799 // o.i[0].f (float[3]), copied from ubo140cIn.o.i[1].f
13800 77, 78, 79, 0,
13801 // o.i[0].u (uvec2[2][4]), copied from ubo140cIn.o.i[1].u
13802 80, 81, 82, 83, 84, 85, 86, 87,
13803 88, 89, 90, 91, 92, 93, 94, 95,
13804 // o.i[0].i (ivec3), copied from ubo140cIn.o.i[1].i
13805 96, 97, 98, 0,
13806 // o.i[0].m2 (mat2x3[3][2], row-major), copied from ubo140cIn.o.i[1].m2
13807 99, 102, 100, 103, 101, 104,
13808 105, 108, 106, 109, 107, 110,
13809 111, 114, 112, 115, 113, 116,
13810 117, 120, 118, 121, 119, 122,
13811 123, 126, 124, 127, 125, 128,
13812 129, 132, 130, 133, 131, 134,
13813
13814 // o.i[1].m (mat3x2, row-major), copied from ubo430rIn.o.i[1].m
13815 204, 206, 208, 0, 205, 207, 209, 0,
13816 // o.i[1].f (float[3]), copied from ubo430rIn.o.i[1].f
13817 211, 212, 213, 0,
13818 // o.i[1].u (uvec2[2][4]), copied from ubo430rIn.o.i[1].u
13819 214, 215, 216, 217, 218, 219, 220, 221,
13820 222, 223, 224, 225, 226, 227, 228, 229,
13821 // o.i[1].i (ivec3), copied from ubo430rIn.o.i[1].i
13822 230, 231, 232, 0,
13823 // o.i[1].m2 (mat2x3[3][2], row-major), copied from ubo430rIn.o.i[1].m2
13824 233, 236, 234, 237, 235, 238,
13825 239, 242, 240, 243, 241, 244,
13826 245, 248, 246, 249, 247, 250,
13827 251, 254, 252, 255, 253, 256,
13828 257, 260, 258, 261, 259, 262,
13829 263, 266, 264, 267, 265, 268,
13830
13831 // i.m (mat3x2, column-major), copied from ubo430rIn.o.i[1].m
13832 204, 205, 206, 207, 208, 209,
13833 // i.f (float[3]), copied from ubo430rIn.o.i[1].f
13834 211, 212, 213, 0,
13835 // i.u (uvec2[2][4]), copied from ubo430rIn.o.i[1].u
13836 214, 215, 216, 217, 218, 219, 220, 221,
13837 222, 223, 224, 225, 226, 227, 228, 229, 0, 0,
13838 // i.i (ivec3), copied from ubo430rIn.o.i[1].i
13839 230, 231, 232, 0,
13840 // i.m2 (mat2x3[3][2], column-major), copied from ubo430rIn.o.i[1].m2
13841 233, 234, 235, 0, 236, 237, 238, 0,
13842 239, 240, 241, 0, 242, 243, 244, 0,
13843 245, 246, 247, 0, 248, 249, 250, 0,
13844 251, 252, 253, 0, 254, 255, 256, 0,
13845 257, 258, 259, 0, 260, 261, 262, 0,
13846 263, 264, 265, 0, 266, 267, 268, 0,
13847 };
13848 const std::vector<float> zeros(std::max(ssbo140cExpect.size(), ssbo430rExpect.size()), 0);
13849 // clang-format on
13850
13851 GLBuffer uboStd140ColMajor, uboStd430RowMajor;
13852 GLBuffer ssboStd140ColMajor, ssboStd430RowMajor;
13853
13854 InitBuffer(program, "Ubo140c", uboStd140ColMajor, 0, ubo140cData.data(),
13855 static_cast<uint32_t>(ubo140cData.size()), true);
13856 InitBuffer(program, "Ubo430r", uboStd430RowMajor, 0, ubo430rData.data(),
13857 static_cast<uint32_t>(ubo430rData.size()), false);
13858 InitBuffer(program, "Ssbo140c", ssboStd140ColMajor, 1, zeros.data(),
13859 static_cast<uint32_t>(ssbo140cExpect.size()), false);
13860 InitBuffer(program, "Ssbo430r", ssboStd430RowMajor, 2, zeros.data(),
13861 static_cast<uint32_t>(ssbo430rExpect.size()), false);
13862 EXPECT_GL_NO_ERROR();
13863
13864 glUseProgram(program);
13865 glDispatchCompute(1, 1, 1);
13866 EXPECT_GL_NO_ERROR();
13867
13868 EXPECT_TRUE(VerifyBuffer(ssboStd140ColMajor, ssbo140cExpect.data(),
13869 static_cast<uint32_t>(ssbo140cExpect.size())));
13870 EXPECT_TRUE(VerifyBuffer(ssboStd430RowMajor, ssbo430rExpect.data(),
13871 static_cast<uint32_t>(ssbo430rExpect.size())));
13872 }
13873
13874 // Verify that bool in interface blocks work.
TEST_P(GLSLTest_ES31,BoolInInterfaceBlocks)13875 TEST_P(GLSLTest_ES31, BoolInInterfaceBlocks)
13876 {
13877 constexpr char kCS[] = R"(#version 310 es
13878 precision highp float;
13879 layout(local_size_x=1) in;
13880
13881 struct Inner
13882 {
13883 bool b;
13884 bvec2 b2;
13885 bvec3 b3;
13886 bvec4 b4;
13887 bool ba[5];
13888 bvec2 b2a[2][3];
13889 };
13890
13891 struct Outer
13892 {
13893 Inner i[2];
13894 };
13895
13896 layout(std140) uniform Ubo140
13897 {
13898 Outer o;
13899 };
13900
13901 layout(std430, binding = 0) buffer Ubo430
13902 {
13903 Outer o;
13904 } ubo430In;
13905
13906 layout(std140, binding = 1) buffer Ssbo140
13907 {
13908 bool valid;
13909 Inner i;
13910 } ssbo140Out;
13911
13912 layout(std430, binding = 2) buffer Ssbo430
13913 {
13914 bool valid;
13915 Inner i;
13916 };
13917
13918 void writeArgToStd430(bool ba[5])
13919 {
13920 i.ba = ba;
13921 }
13922
13923 bool[5] readFromStd430(uint innerIndex)
13924 {
13925 return ubo430In.o.i[innerIndex].ba;
13926 }
13927
13928 void copyFromStd430(out bvec2 b2a[2][3])
13929 {
13930 b2a = ubo430In.o.i[0].b2a;
13931 }
13932
13933 bool destroyContent(inout Inner iOut)
13934 {
13935 iOut.b = true;
13936 iOut.b2 = bvec2(true);
13937 iOut.b3 = bvec3(true);
13938 iOut.b4 = bvec4(true);
13939 iOut.ba = bool[5](true, true, true, true, true);
13940 bvec2 true3[3] = bvec2[3](iOut.b2, iOut.b2, iOut.b2);
13941 iOut.b2a = bvec2[2][3](true3, true3);
13942 return true;
13943 }
13944
13945 void main(){
13946 // Directly copy from one layout to another.
13947 i.b = o.i[0].b;
13948 i.b2 = o.i[0].b2;
13949 i.b2a = o.i[0].b2a;
13950
13951 // Copy to temp with swizzle.
13952 bvec4 t1 = o.i[0].b3.yxzy;
13953 bvec4 t2 = o.i[0].b4.xxyy;
13954 bvec4 t3 = o.i[0].b4.zzww;
13955
13956 // Copy from temp with swizzle.
13957 i.b3 = t1.ywz;
13958 i.b4.yz = bvec2(t2.z, t3.y);
13959 i.b4.wx = bvec2(t3.w, t2.x);
13960
13961 // Copy by passing argument to function.
13962 writeArgToStd430(o.i[0].ba);
13963
13964 // Copy by return value.
13965 ssbo140Out.i.ba = readFromStd430(0u);
13966
13967 // Copy by out parameter.
13968 copyFromStd430(ssbo140Out.i.b2a);
13969
13970 // Logical operations
13971 uvec4 t4 = ubo430In.o.i[0].b ? uvec4(0) : uvec4(1);
13972 ssbo140Out.i.b = all(equal(t4, uvec4(1))) && (ubo430In.o.i[0].b ? false : true);
13973 ssbo140Out.i.b2 = not(ubo430In.o.i[0].b2);
13974 ssbo140Out.i.b3 = bvec3(all(ubo430In.o.i[0].b3), any(ubo430In.o.i[0].b3), any(ubo430In.o.i[0].b3.yx));
13975 ssbo140Out.i.b4 = equal(ubo430In.o.i[0].b4, bvec4(true, false, true, false));
13976
13977 ssbo140Out.valid = true;
13978 ssbo140Out.valid = ssbo140Out.valid && all(equal(bvec3(o.i[1].b, o.i[1].b2), o.i[1].b3));
13979 ssbo140Out.valid = ssbo140Out.valid &&
13980 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])));
13981 ssbo140Out.valid = ssbo140Out.valid && uint(o.i[1].ba[4]) == 1u;
13982 for (int x = 0; x < o.i[1].b2a.length(); ++x)
13983 {
13984 for (int y = 0; y < o.i[1].b2a[x].length(); ++y)
13985 {
13986 ssbo140Out.valid = ssbo140Out.valid && all(equal(uvec2(o.i[1].b2a[x][y]), uvec2(x % 2, y % 2)));
13987 }
13988 }
13989
13990 valid = o.i[1] == ubo430In.o.i[1];
13991
13992 // Make sure short-circuiting behavior is correct.
13993 bool falseVar = !valid && destroyContent(i);
13994 if (falseVar && destroyContent(ssbo140Out.i))
13995 {
13996 valid = false;
13997 }
13998
13999 if (valid || o.i[uint((i.ba = bool[5](true, true, true, true, true))[1])].b)
14000 {
14001 }
14002 else
14003 {
14004 ssbo140Out.valid = false;
14005 }
14006 })";
14007
14008 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
14009 EXPECT_GL_NO_ERROR();
14010
14011 // Test data, laid out with padding (0) based on std140/std430 rules.
14012 // clang-format off
14013 const std::vector<uint32_t> ubo140Data = {
14014 // o.i[0].b (bool)
14015 true, 0,
14016 // o.i[0].b2 (bvec2)
14017 true, false,
14018 // o.i[0].b3 (bvec3)
14019 true, true, false, 0,
14020 // o.i[0].b4 (bvec4)
14021 false, true, false, true,
14022 // o.i[0].ba (bool[5])
14023 true, 0, 0, 0,
14024 false, 0, 0, 0,
14025 false, 0, 0, 0,
14026 true, 0, 0, 0,
14027 true, 0, 0, 0,
14028 // o.i[0].b2a (bool[2][3])
14029 false, true, 0, 0, true, true, 0, 0, true, false, 0, 0,
14030 true, false, 0, 0, false, false, 0, 0, true, true, 0, 0,
14031
14032 // o.i[1].b (bool)
14033 false, 0,
14034 // o.i[1].b2 (bvec2)
14035 true, true,
14036 // o.i[1].b3 (bvec3), expected to be equal to (b, b2)
14037 false, true, true, 0,
14038 // o.i[1].b4 (bvec4)
14039 true, false, true, true,
14040 // o.i[1].ba (bool[5]), expected to be equal to (not(b4), 1)
14041 false, 0, 0, 0,
14042 true, 0, 0, 0,
14043 false, 0, 0, 0,
14044 false, 0, 0, 0,
14045 true, 0, 0, 0,
14046 // o.i[1].b2a (bvec2[2][3]), [x][y] expected to equal (x%2,y%2)
14047 false, false, 0, 0, false, true, 0, 0, false, false, 0, 0,
14048 true, false, 0, 0, true, true, 0, 0, true, false, 0, 0,
14049 };
14050 const std::vector<uint32_t> ubo430Data = {
14051 // o.i[0].b (bool)
14052 false, 0,
14053 // o.i[0].b2 (bvec2)
14054 true, true,
14055 // o.i[0].b3 (bvec3)
14056 false, false, true, 0,
14057 // o.i[0].b4 (bvec4)
14058 true, false, true, true,
14059 // o.i[0].ba (bool[5])
14060 false, false, false, true, false, 0,
14061 // o.i[0].b2a (bool[2][3])
14062 true, false, true, false, true, true,
14063 false, true, true, true, false, false, 0, 0,
14064
14065 // o.i[1] expected to be equal to ubo140In.o.i[1]
14066 // o.i[1].b (bool)
14067 false, 0,
14068 // o.i[1].b2 (bvec2)
14069 true, true,
14070 // o.i[1].b3 (bvec3)
14071 false, true, true, 0,
14072 // o.i[1].b4 (bvec4)
14073 true, false, true, true,
14074 // o.i[1].ba (bool[5])
14075 false, true, false, false, true, 0,
14076 // o.i[1].b2a (bvec2[2][3])
14077 false, false, false, true, false, false,
14078 true, false, true, true, true, false,
14079 };
14080 const std::vector<uint32_t> ssbo140Expect = {
14081 // valid, expected to be true
14082 true, 0, 0, 0,
14083
14084 // i.b (bool), ubo430In.o.i[0].b ? false : true
14085 true, 0,
14086 // i.b2 (bvec2), not(ubo430In.o.i[0].b2)
14087 false, false,
14088 // i.b3 (bvec3), all(ubo430In.o.i[0].b3), any(...b3), any(...b3.yx)
14089 false, true, false, 0,
14090 // i.b4 (bvec4), ubo430In.o.i[0].b4 == (true, false, true, false)
14091 true, true, true, false,
14092 // i.ba (bool[5]), copied from ubo430In.o.i[0].ba
14093 false, 0, 0, 0,
14094 false, 0, 0, 0,
14095 false, 0, 0, 0,
14096 true, 0, 0, 0,
14097 false, 0, 0, 0,
14098 // i.b2a (bool[2][3]), copied from ubo430In.o.i[0].b2a
14099 true, false, 0, 0, true, false, 0, 0, true, true, 0, 0,
14100 false, true, 0, 0, true, true, 0, 0, false, false, 0, 0,
14101 };
14102 const std::vector<uint32_t> ssbo430Expect = {
14103 // valid, expected to be true
14104 true, 0, 0, 0,
14105
14106 // o.i[0].b (bool), copied from (Ubo140::)o.i[0].b
14107 true, 0,
14108 // o.i[0].b2 (bvec2), copied from (Ubo140::)o.i[0].b2
14109 true, false,
14110 // o.i[0].b3 (bvec3), copied from (Ubo140::)o.i[0].b3
14111 true, true, false, 0,
14112 // o.i[0].b4 (bvec4), copied from (Ubo140::)o.i[0].b4
14113 false, true, false, true,
14114 // o.i[0].ba (bool[5]), copied from (Ubo140::)o.i[0].ba
14115 true, false, false, true, true, 0,
14116 // o.i[0].b2a (bool[2][3]), copied from (Ubo140::)o.i[0].b2a
14117 false, true, true, true, true, false,
14118 true, false, false, false, true, true, 0, 0,
14119 };
14120 const std::vector<uint32_t> zeros(std::max(ssbo140Expect.size(), ssbo430Expect.size()), 0);
14121 // clang-format on
14122
14123 GLBuffer uboStd140, uboStd430;
14124 GLBuffer ssboStd140, ssboStd430;
14125
14126 InitBuffer(program, "Ubo140", uboStd140, 0, ubo140Data.data(),
14127 static_cast<uint32_t>(ubo140Data.size()), true);
14128 InitBuffer(program, "Ubo430", uboStd430, 0, ubo430Data.data(),
14129 static_cast<uint32_t>(ubo430Data.size()), false);
14130 InitBuffer(program, "Ssbo140", ssboStd140, 1, zeros.data(),
14131 static_cast<uint32_t>(ssbo140Expect.size()), false);
14132 InitBuffer(program, "Ssbo430", ssboStd430, 2, zeros.data(),
14133 static_cast<uint32_t>(ssbo430Expect.size()), false);
14134 EXPECT_GL_NO_ERROR();
14135
14136 glUseProgram(program);
14137 glDispatchCompute(1, 1, 1);
14138 EXPECT_GL_NO_ERROR();
14139
14140 EXPECT_TRUE(VerifyBuffer(ssboStd140, ssbo140Expect.data(),
14141 static_cast<uint32_t>(ssbo140Expect.size())));
14142 EXPECT_TRUE(VerifyBuffer(ssboStd430, ssbo430Expect.data(),
14143 static_cast<uint32_t>(ssbo430Expect.size())));
14144 }
14145
14146 // Verify that ternary operator works when the operands are matrices used in different block
14147 // storage.
TEST_P(GLSLTest_ES31,TernaryOnMatricesInDifferentBlockStorages)14148 TEST_P(GLSLTest_ES31, TernaryOnMatricesInDifferentBlockStorages)
14149 {
14150 constexpr char kCS[] = R"(#version 310 es
14151 precision highp float;
14152 layout(local_size_x=1) in;
14153
14154 layout(std140, column_major) uniform Ubo140c
14155 {
14156 uint u;
14157 layout(row_major) mat3x2 m;
14158 } ubo140cIn;
14159
14160 layout(std430, row_major, binding = 0) buffer Ubo430r
14161 {
14162 uint u;
14163 layout(column_major) mat3x2 m;
14164 } ubo430rIn;
14165
14166 layout(std140, column_major, binding = 1) buffer Ssbo140c
14167 {
14168 uint u;
14169 mat3x2 m;
14170 } ssbo140cIn;
14171
14172 layout(std430, row_major, binding = 2) buffer Ssbo430r
14173 {
14174 mat3x2 m1;
14175 mat3x2 m2;
14176 } ssbo430rOut;
14177
14178 void main(){
14179 ssbo430rOut.m1 = ubo140cIn.u > ubo430rIn.u ? ubo140cIn.m : ubo430rIn.m;
14180 ssbo430rOut.m2 = ssbo140cIn.u > ubo140cIn.u ? ssbo140cIn.m : ubo140cIn.m;
14181
14182 mat3x2 m = mat3x2(0);
14183
14184 ssbo430rOut.m1 = ubo140cIn.u == 0u ? m : ssbo430rOut.m1;
14185 })";
14186
14187 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
14188 EXPECT_GL_NO_ERROR();
14189
14190 // Test data, laid out with padding (0) based on std140/std430 rules.
14191 // clang-format off
14192 const std::vector<float> ubo140cData = {
14193 // u (uint)
14194 1, 0, 0, 0,
14195
14196 // m (mat3x2, row-major)
14197 5, 7, 9, 0, 6, 8, 10, 0,
14198 };
14199 const std::vector<float> ubo430rData = {
14200 // u (uint)
14201 135, 0,
14202
14203 // m (mat3x2, column-major)
14204 139, 140, 141, 142, 143, 144,
14205 };
14206 const std::vector<float> ssbo140cData = {
14207 // u (uint)
14208 204, 0, 0, 0,
14209
14210 // m (mat3x2, column-major)
14211 205, 206, 0, 0, 207, 208, 0, 0, 209, 210, 0, 0,
14212 };
14213 const std::vector<float> ssbo430rExpect = {
14214 // m1 (mat3x2, row-major), copied from ubo430rIn.m
14215 139, 141, 143, 0, 140, 142, 144, 0,
14216
14217 // m2 (mat3x2, row-major), copied from ssbo140cIn.m
14218 205, 207, 209, 0, 206, 208, 210, 0,
14219 };
14220 const std::vector<float> zeros(ssbo430rExpect.size(), 0);
14221 // clang-format on
14222
14223 GLBuffer uboStd140ColMajor, uboStd430RowMajor;
14224 GLBuffer ssboStd140ColMajor, ssboStd430RowMajor;
14225
14226 InitBuffer(program, "Ubo140c", uboStd140ColMajor, 0, ubo140cData.data(),
14227 static_cast<uint32_t>(ubo140cData.size()), true);
14228 InitBuffer(program, "Ubo430r", uboStd430RowMajor, 0, ubo430rData.data(),
14229 static_cast<uint32_t>(ubo430rData.size()), false);
14230 InitBuffer(program, "Ssbo140c", ssboStd140ColMajor, 1, ssbo140cData.data(),
14231 static_cast<uint32_t>(ssbo140cData.size()), false);
14232 InitBuffer(program, "Ssbo430r", ssboStd430RowMajor, 2, zeros.data(),
14233 static_cast<uint32_t>(ssbo430rExpect.size()), false);
14234 EXPECT_GL_NO_ERROR();
14235
14236 glUseProgram(program);
14237 glDispatchCompute(1, 1, 1);
14238 EXPECT_GL_NO_ERROR();
14239
14240 EXPECT_TRUE(VerifyBuffer(ssboStd430RowMajor, ssbo430rExpect.data(),
14241 static_cast<uint32_t>(ssbo430rExpect.size())));
14242 }
14243
14244 // Verify that ternary operator works when the operands are structs used in different block
14245 // storage.
TEST_P(GLSLTest_ES31,TernaryOnStructsInDifferentBlockStorages)14246 TEST_P(GLSLTest_ES31, TernaryOnStructsInDifferentBlockStorages)
14247 {
14248 constexpr char kCS[] = R"(#version 310 es
14249 precision highp float;
14250 layout(local_size_x=1) in;
14251
14252 struct S
14253 {
14254 mat3x2 m[2];
14255 };
14256
14257 layout(std140, column_major) uniform Ubo140c
14258 {
14259 uint u;
14260 layout(row_major) S s;
14261 } ubo140cIn;
14262
14263 layout(std430, row_major, binding = 0) buffer Ubo430r
14264 {
14265 uint u;
14266 layout(column_major) S s;
14267 } ubo430rIn;
14268
14269 layout(std140, column_major, binding = 1) buffer Ssbo140c
14270 {
14271 uint u;
14272 S s;
14273 } ssbo140cIn;
14274
14275 layout(std430, row_major, binding = 2) buffer Ssbo430r
14276 {
14277 S s1;
14278 S s2;
14279 } ssbo430rOut;
14280
14281 void main(){
14282 ssbo430rOut.s1 = ubo140cIn.u > ubo430rIn.u ? ubo140cIn.s : ubo430rIn.s;
14283 ssbo430rOut.s2 = ssbo140cIn.u > ubo140cIn.u ? ssbo140cIn.s : ubo140cIn.s;
14284
14285 S s;
14286 s.m[0] = mat3x2(0);
14287 s.m[1] = mat3x2(0);
14288
14289 ssbo430rOut.s1 = ubo140cIn.u == 0u ? s : ssbo430rOut.s1;
14290 })";
14291
14292 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
14293 EXPECT_GL_NO_ERROR();
14294
14295 // Test data, laid out with padding (0) based on std140/std430 rules.
14296 // clang-format off
14297 const std::vector<float> ubo140cData = {
14298 // u (uint)
14299 1, 0, 0, 0,
14300
14301 // s.m[0] (mat3x2, row-major)
14302 5, 7, 9, 0, 6, 8, 10, 0,
14303 // s.m[1] (mat3x2, row-major)
14304 25, 27, 29, 0, 26, 28, 30, 0,
14305 };
14306 const std::vector<float> ubo430rData = {
14307 // u (uint)
14308 135, 0,
14309
14310 // s.m[0] (mat3x2, column-major)
14311 139, 140, 141, 142, 143, 144,
14312 // s.m[1] (mat3x2, column-major)
14313 189, 190, 191, 192, 193, 194,
14314 };
14315 const std::vector<float> ssbo140cData = {
14316 // u (uint)
14317 204, 0, 0, 0,
14318
14319 // s.m[0] (mat3x2, column-major)
14320 205, 206, 0, 0, 207, 208, 0, 0, 209, 210, 0, 0,
14321 // s.m[1] (mat3x2, column-major)
14322 245, 246, 0, 0, 247, 248, 0, 0, 249, 250, 0, 0,
14323 };
14324 const std::vector<float> ssbo430rExpect = {
14325 // s1.m[0] (mat3x2, row-major), copied from ubo430rIn.s.m[0]
14326 139, 141, 143, 0, 140, 142, 144, 0,
14327 // s1.m[1] (mat3x2, row-major), copied from ubo430rIn.s.m[0]
14328 189, 191, 193, 0, 190, 192, 194, 0,
14329
14330 // s2.m[0] (mat3x2, row-major), copied from ssbo140cIn.m
14331 205, 207, 209, 0, 206, 208, 210, 0,
14332 // s2.m[1] (mat3x2, row-major), copied from ssbo140cIn.m
14333 245, 247, 249, 0, 246, 248, 250, 0,
14334 };
14335 const std::vector<float> zeros(ssbo430rExpect.size(), 0);
14336 // clang-format on
14337
14338 GLBuffer uboStd140ColMajor, uboStd430RowMajor;
14339 GLBuffer ssboStd140ColMajor, ssboStd430RowMajor;
14340
14341 InitBuffer(program, "Ubo140c", uboStd140ColMajor, 0, ubo140cData.data(),
14342 static_cast<uint32_t>(ubo140cData.size()), true);
14343 InitBuffer(program, "Ubo430r", uboStd430RowMajor, 0, ubo430rData.data(),
14344 static_cast<uint32_t>(ubo430rData.size()), false);
14345 InitBuffer(program, "Ssbo140c", ssboStd140ColMajor, 1, ssbo140cData.data(),
14346 static_cast<uint32_t>(ssbo140cData.size()), false);
14347 InitBuffer(program, "Ssbo430r", ssboStd430RowMajor, 2, zeros.data(),
14348 static_cast<uint32_t>(ssbo430rExpect.size()), false);
14349 EXPECT_GL_NO_ERROR();
14350
14351 glUseProgram(program);
14352 glDispatchCompute(1, 1, 1);
14353 EXPECT_GL_NO_ERROR();
14354
14355 EXPECT_TRUE(VerifyBuffer(ssboStd430RowMajor, ssbo430rExpect.data(),
14356 static_cast<uint32_t>(ssbo430rExpect.size())));
14357 }
14358
14359 // Verify that uint in interface block cast to bool works.
TEST_P(GLSLTest_ES3,UintCastToBoolFromInterfaceBlocks)14360 TEST_P(GLSLTest_ES3, UintCastToBoolFromInterfaceBlocks)
14361 {
14362 constexpr char kFS[] = R"(#version 300 es
14363 precision mediump float;
14364
14365 uniform uvec4 uv4;
14366 uniform uvec2 uv2;
14367 uniform uint u1;
14368 uniform uint u2;
14369
14370 out vec4 colorOut;
14371
14372 void main()
14373 {
14374 bvec4 bv4 = bvec4(uv4);
14375 bvec2 bv2 = bvec2(uv2);
14376 bool b1 = bool(u1);
14377 bool b2 = bool(u2);
14378
14379 vec4 vv4 = mix(vec4(0), vec4(0.4), bv4);
14380 vec2 vv2 = mix(vec2(0), vec2(0.7), bv2);
14381 float v1 = b1 ? 1.0 : 0.0;
14382 float v2 = b2 ? 0.0 : 1.0;
14383
14384 colorOut = vec4(vv4.x - vv4.y + vv4.z + vv4.w,
14385 (vv2.y - vv2.x) * 1.5,
14386 v1,
14387 v2);
14388 })";
14389
14390 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
14391 EXPECT_GL_NO_ERROR();
14392
14393 glUseProgram(program);
14394 GLint uv4 = glGetUniformLocation(program, "uv4");
14395 GLint uv2 = glGetUniformLocation(program, "uv2");
14396 GLint u1 = glGetUniformLocation(program, "u1");
14397 GLint u2 = glGetUniformLocation(program, "u2");
14398 ASSERT_NE(uv4, -1);
14399 ASSERT_NE(uv2, -1);
14400 ASSERT_NE(u1, -1);
14401 ASSERT_NE(u2, -1);
14402
14403 glUniform4ui(uv4, 123, 0, 9, 8297312);
14404 glUniform2ui(uv2, 0, 90812);
14405 glUniform1ui(u1, 8979421);
14406 glUniform1ui(u2, 0);
14407
14408 glClearColor(0, 0, 0, 0);
14409 glClear(GL_COLOR_BUFFER_BIT);
14410
14411 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
14412 EXPECT_GL_NO_ERROR();
14413
14414 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
14415 }
14416
14417 // Test that the precise keyword is not reserved before ES3.1.
TEST_P(GLSLTest_ES3,PreciseNotReserved)14418 TEST_P(GLSLTest_ES3, PreciseNotReserved)
14419 {
14420 // Skip in ES3.1+ as the precise keyword is reserved/core.
14421 ANGLE_SKIP_TEST_IF(getClientMajorVersion() > 3 ||
14422 (getClientMajorVersion() == 3 && getClientMinorVersion() >= 1));
14423
14424 constexpr char kFS[] = R"(#version 300 es
14425 precision mediump float;
14426 in float precise;
14427 out vec4 my_FragColor;
14428 void main() { my_FragColor = vec4(precise, 0, 0, 1.0); })";
14429
14430 constexpr char kVS[] = R"(#version 300 es
14431 in vec4 a_position;
14432 out float precise;
14433 void main() { precise = a_position.x; gl_Position = a_position; })";
14434
14435 GLuint program = CompileProgram(kVS, kFS);
14436 EXPECT_NE(0u, program);
14437 }
14438
14439 // Test that the precise keyword is reserved on ES3.0 without GL_EXT_gpu_shader5.
TEST_P(GLSLTest_ES31,PreciseReservedWithoutExtension)14440 TEST_P(GLSLTest_ES31, PreciseReservedWithoutExtension)
14441 {
14442 // Skip if EXT_gpu_shader5 is enabled.
14443 ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
14444 // Skip in ES3.2+ as the precise keyword is core.
14445 ANGLE_SKIP_TEST_IF(getClientMajorVersion() > 3 ||
14446 (getClientMajorVersion() == 3 && getClientMinorVersion() >= 2));
14447
14448 constexpr char kFS[] = R"(#version 310 es
14449 precision mediump float;
14450 in float v_varying;
14451 out vec4 my_FragColor;
14452 void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); })";
14453
14454 constexpr char kVS[] = R"(#version 310 es
14455 in vec4 a_position;
14456 precise out float v_varying;
14457 void main() { v_varying = a_position.x; gl_Position = a_position; })";
14458
14459 // Should fail, as precise is a reserved keyword when the extension is not enabled.
14460 GLuint program = CompileProgram(kVS, kFS);
14461 EXPECT_EQ(0u, program);
14462 }
14463
14464 // Regression test for a bug with precise in combination with constructor, swizzle and dynamic
14465 // index.
TEST_P(GLSLTest_ES31,PreciseVsVectorConstructorSwizzleAndIndex)14466 TEST_P(GLSLTest_ES31, PreciseVsVectorConstructorSwizzleAndIndex)
14467 {
14468 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
14469
14470 constexpr char kVS[] = R"(#version 310 es
14471 #extension GL_EXT_gpu_shader5 : require
14472
14473 uniform highp float u;
14474
14475 void main()
14476 {
14477 precise float p = vec4(u, u, u, u).xyz[int(u)];
14478 gl_Position = vec4(p);
14479 })";
14480
14481 constexpr char kFS[] = R"(#version 310 es
14482 precision mediump float;
14483 out vec4 oColor;
14484 void main()
14485 {
14486 oColor = vec4(1.0);
14487 })";
14488
14489 ANGLE_GL_PROGRAM(program, kVS, kFS);
14490 }
14491
14492 // Regression test for a bug with precise in combination with matrix constructor and column index.
TEST_P(GLSLTest_ES31,PreciseVsMatrixConstructorAndIndex)14493 TEST_P(GLSLTest_ES31, PreciseVsMatrixConstructorAndIndex)
14494 {
14495 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
14496
14497 constexpr char kVS[] = R"(#version 310 es
14498 #extension GL_EXT_gpu_shader5 : require
14499
14500 uniform highp vec4 u;
14501
14502 void main()
14503 {
14504 precise vec4 p = mat4(u,vec4(0),vec4(0),vec4(0))[0];
14505 gl_Position = p;
14506 })";
14507
14508 constexpr char kFS[] = R"(#version 310 es
14509 precision mediump float;
14510 out vec4 oColor;
14511 void main()
14512 {
14513 oColor = vec4(1.0);
14514 })";
14515
14516 ANGLE_GL_PROGRAM(program, kVS, kFS);
14517 }
14518
14519 // Regression test for a bug with precise in combination with struct constructor and field
14520 // selection.
TEST_P(GLSLTest_ES31,PreciseVsStructConstructorAndFieldSelection)14521 TEST_P(GLSLTest_ES31, PreciseVsStructConstructorAndFieldSelection)
14522 {
14523 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
14524
14525 constexpr char kVS[] = R"(#version 310 es
14526 #extension GL_EXT_gpu_shader5 : require
14527
14528 struct S
14529 {
14530 float a;
14531 float b;
14532 };
14533
14534 uniform highp float u;
14535
14536 void main()
14537 {
14538 precise float p = S(u, u).b;
14539 gl_Position = vec4(p);
14540 })";
14541
14542 constexpr char kFS[] = R"(#version 310 es
14543 precision mediump float;
14544 out vec4 oColor;
14545 void main()
14546 {
14547 oColor = vec4(1.0);
14548 })";
14549
14550 ANGLE_GL_PROGRAM(program, kVS, kFS);
14551 }
14552
14553 // Test that reusing the same variable name for different uses across stages links fine. The SPIR-V
14554 // transformation should ignore all names for non-shader-interface variables and not get confused by
14555 // them.
TEST_P(GLSLTest_ES31,VariableNameReuseAcrossStages)14556 TEST_P(GLSLTest_ES31, VariableNameReuseAcrossStages)
14557 {
14558 constexpr char kVS[] = R"(#version 310 es
14559 precision mediump float;
14560 uniform highp vec4 a;
14561 in highp vec4 b;
14562 in highp vec4 c;
14563 in highp vec4 d;
14564 out highp vec4 e;
14565
14566 vec4 f(vec4 a)
14567 {
14568 return a;
14569 }
14570
14571 vec4 g(vec4 f)
14572 {
14573 return f + f;
14574 }
14575
14576 void main() {
14577 e = f(b) + a;
14578 gl_Position = g(c) + f(d);
14579 }
14580 )";
14581
14582 constexpr char kFS[] = R"(#version 310 es
14583 precision mediump float;
14584 in highp vec4 e;
14585 uniform sampler2D f;
14586 layout(rgba8) uniform highp readonly image2D g;
14587 uniform A
14588 {
14589 vec4 x;
14590 } c;
14591 layout(std140, binding=0) buffer B
14592 {
14593 vec4 x;
14594 } d[2];
14595 out vec4 col;
14596
14597 vec4 h(vec4 c)
14598 {
14599 return texture(f, c.xy) + imageLoad(g, ivec2(c.zw));
14600 }
14601
14602 vec4 i(vec4 x, vec4 y)
14603 {
14604 return vec4(x.xy, y.zw);
14605 }
14606
14607 void main() {
14608 col = h(e) + i(c.x, d[0].x) + d[1].x;
14609 }
14610 )";
14611
14612 GLuint program = CompileProgram(kVS, kFS);
14613 EXPECT_NE(0u, program);
14614 }
14615
14616 // Test that reusing the same uniform variable name for different uses across stages links fine.
TEST_P(GLSLTest_ES31,UniformVariableNameReuseAcrossStages)14617 TEST_P(GLSLTest_ES31, UniformVariableNameReuseAcrossStages)
14618 {
14619 constexpr char kVS[] = R"(#version 310 es
14620 precision mediump float;
14621 in highp vec4 variableWithSameName;
14622
14623 void main() {
14624 gl_Position = variableWithSameName;
14625 }
14626 )";
14627
14628 constexpr char kFS[] = R"(#version 310 es
14629 precision mediump float;
14630 uniform vec4 variableWithSameName;
14631 out vec4 col;
14632
14633 void main() {
14634 col = vec4(variableWithSameName);
14635 }
14636 )";
14637
14638 GLuint program = CompileProgram(kVS, kFS);
14639 EXPECT_NE(0u, program);
14640 }
14641
14642 // Verify that precision match validation of uniforms is performed only if they are statically used
TEST_P(GLSLTest_ES31,UniformPrecisionMatchValidation)14643 TEST_P(GLSLTest_ES31, UniformPrecisionMatchValidation)
14644 {
14645 // Nvidia driver bug: http://anglebug.com/42263793
14646 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsWindows() && IsNVIDIA());
14647
14648 constexpr char kVSUnused[] = R"(#version 300 es
14649 precision highp float;
14650 uniform highp vec4 positionIn;
14651
14652 void main()
14653 {
14654 gl_Position = vec4(1, 0, 0, 1);
14655 })";
14656
14657 constexpr char kVSStaticUse[] = R"(#version 300 es
14658 precision highp float;
14659 uniform highp vec4 positionIn;
14660
14661 void main()
14662 {
14663 gl_Position = positionIn;
14664 })";
14665
14666 constexpr char kFSUnused[] = R"(#version 300 es
14667 precision highp float;
14668 uniform highp vec4 positionIn;
14669 out vec4 my_FragColor;
14670
14671 void main()
14672 {
14673 my_FragColor = vec4(1, 0, 0, 1);
14674 })";
14675
14676 constexpr char kFSStaticUse[] = R"(#version 300 es
14677 precision highp float;
14678 uniform mediump vec4 positionIn;
14679 out vec4 my_FragColor;
14680
14681 void main()
14682 {
14683 my_FragColor = vec4(1, 0, 0, positionIn.z);
14684 })";
14685
14686 GLuint program = 0;
14687
14688 program = CompileProgram(kVSUnused, kFSUnused);
14689 EXPECT_NE(0u, program);
14690
14691 program = CompileProgram(kVSUnused, kFSStaticUse);
14692 EXPECT_NE(0u, program);
14693
14694 program = CompileProgram(kVSStaticUse, kFSUnused);
14695 EXPECT_NE(0u, program);
14696
14697 program = CompileProgram(kVSStaticUse, kFSStaticUse);
14698 EXPECT_EQ(0u, program);
14699 }
14700
14701 // Validate that link fails when two instanceless interface blocks with different block names but
14702 // same field names are present.
TEST_P(GLSLTest_ES31,AmbiguousInstancelessInterfaceBlockFields)14703 TEST_P(GLSLTest_ES31, AmbiguousInstancelessInterfaceBlockFields)
14704 {
14705 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14706
14707 constexpr char kVS[] = R"(#version 310 es
14708 in highp vec4 position;
14709 layout(binding = 0) buffer BlockA { mediump float a; };
14710 void main()
14711 {
14712 a = 0.0;
14713 gl_Position = position;
14714 })";
14715
14716 constexpr char kFS[] = R"(#version 310 es
14717 precision mediump float;
14718 layout(location = 0) out mediump vec4 color;
14719 uniform BlockB { float a; };
14720 void main()
14721 {
14722 color = vec4(a, a, a, 1.0);
14723 })";
14724
14725 GLuint program = CompileProgram(kVS, kFS);
14726 EXPECT_EQ(0u, program);
14727 }
14728
14729 // Verify I/O block array locations
TEST_P(GLSLTest_ES31,IOBlockLocations)14730 TEST_P(GLSLTest_ES31, IOBlockLocations)
14731 {
14732 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14733 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
14734
14735 constexpr char kVS[] = R"(#version 310 es
14736 #extension GL_EXT_shader_io_blocks : require
14737
14738 in highp vec4 position;
14739
14740 layout(location = 0) out vec4 aOut;
14741
14742 layout(location = 6) out VSBlock
14743 {
14744 vec4 b; // location 6
14745 vec4 c; // location 7
14746 layout(location = 1) vec4 d;
14747 vec4 e; // location 2
14748 vec4 f[2]; // locations 3 and 4
14749 } blockOut;
14750
14751 layout(location = 5) out vec4 gOut;
14752
14753 void main()
14754 {
14755 aOut = vec4(0.03, 0.06, 0.09, 0.12);
14756 blockOut.b = vec4(0.15, 0.18, 0.21, 0.24);
14757 blockOut.c = vec4(0.27, 0.30, 0.33, 0.36);
14758 blockOut.d = vec4(0.39, 0.42, 0.45, 0.48);
14759 blockOut.e = vec4(0.51, 0.54, 0.57, 0.6);
14760 blockOut.f[0] = vec4(0.63, 0.66, 0.66, 0.69);
14761 blockOut.f[1] = vec4(0.72, 0.75, 0.78, 0.81);
14762 gOut = vec4(0.84, 0.87, 0.9, 0.93);
14763 gl_Position = position;
14764 })";
14765
14766 constexpr char kGS[] = R"(#version 310 es
14767 #extension GL_EXT_geometry_shader : require
14768 layout (triangles) in;
14769 layout (triangle_strip, max_vertices = 3) out;
14770
14771 // Input varyings
14772 layout(location = 0) in vec4 aIn[];
14773
14774 layout(location = 6) in VSBlock
14775 {
14776 vec4 b;
14777 vec4 c;
14778 layout(location = 1) vec4 d;
14779 vec4 e;
14780 vec4 f[2];
14781 } blockIn[];
14782
14783 layout(location = 5) in vec4 gIn[];
14784
14785 // Output varyings
14786 layout(location = 1) out vec4 aOut;
14787
14788 layout(location = 0) out GSBlock
14789 {
14790 vec4 b; // location 0
14791 layout(location = 3) vec4 c;
14792 layout(location = 7) vec4 d;
14793 layout(location = 5) vec4 e[2];
14794 layout(location = 4) vec4 f;
14795 } blockOut;
14796
14797 layout(location = 2) out vec4 gOut;
14798
14799 void main()
14800 {
14801 int n;
14802 for (n = 0; n < gl_in.length(); n++)
14803 {
14804 gl_Position = gl_in[n].gl_Position;
14805
14806 aOut = aIn[n];
14807 blockOut.b = blockIn[n].b;
14808 blockOut.c = blockIn[n].c;
14809 blockOut.d = blockIn[n].d;
14810 blockOut.e[0] = blockIn[n].e;
14811 blockOut.e[1] = blockIn[n].f[0];
14812 blockOut.f = blockIn[n].f[1];
14813 gOut = gIn[n];
14814
14815 EmitVertex();
14816 }
14817 EndPrimitive();
14818 })";
14819
14820 constexpr char kFS[] = R"(#version 310 es
14821 #extension GL_EXT_shader_io_blocks : require
14822 precision mediump float;
14823
14824 layout(location = 0) out mediump vec4 color;
14825
14826 layout(location = 1) in vec4 aIn;
14827
14828 layout(location = 0) in GSBlock
14829 {
14830 vec4 b;
14831 layout(location = 3) vec4 c;
14832 layout(location = 7) vec4 d;
14833 layout(location = 5) vec4 e[2];
14834 layout(location = 4) vec4 f;
14835 } blockIn;
14836
14837 layout(location = 2) in vec4 gIn;
14838
14839 bool isEq(vec4 a, vec4 b) { return all(lessThan(abs(a-b), vec4(0.001))); }
14840
14841 void main()
14842 {
14843 bool passR = isEq(aIn, vec4(0.03, 0.06, 0.09, 0.12));
14844 bool passG = isEq(blockIn.b, vec4(0.15, 0.18, 0.21, 0.24)) &&
14845 isEq(blockIn.c, vec4(0.27, 0.30, 0.33, 0.36)) &&
14846 isEq(blockIn.d, vec4(0.39, 0.42, 0.45, 0.48)) &&
14847 isEq(blockIn.e[0], vec4(0.51, 0.54, 0.57, 0.6)) &&
14848 isEq(blockIn.e[1], vec4(0.63, 0.66, 0.66, 0.69)) &&
14849 isEq(blockIn.f, vec4(0.72, 0.75, 0.78, 0.81));
14850 bool passB = isEq(gIn, vec4(0.84, 0.87, 0.9, 0.93));
14851
14852 color = vec4(passR, passG, passB, 1.0);
14853 })";
14854
14855 ANGLE_GL_PROGRAM_WITH_GS(program, kVS, kGS, kFS);
14856 EXPECT_GL_NO_ERROR();
14857
14858 GLTexture color;
14859 glBindTexture(GL_TEXTURE_2D, color);
14860 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
14861
14862 GLFramebuffer fbo;
14863 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
14864 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
14865
14866 drawQuad(program, "position", 0);
14867
14868 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
14869 }
14870
14871 // Test using builtins that can only be redefined with gl_PerVertex
TEST_P(GLSLTest_ES31,PerVertexRedefinition)14872 TEST_P(GLSLTest_ES31, PerVertexRedefinition)
14873 {
14874 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
14875 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_clip_cull_distance"));
14876
14877 constexpr char kVS[] = R"(#version 310 es
14878 void main()
14879 {
14880 gl_Position = vec4(1.0, 0.0, 0.0, 1.0);
14881 })";
14882
14883 constexpr char kGS[] = R"(#version 310 es
14884 #extension GL_EXT_geometry_shader : require
14885 #extension GL_EXT_clip_cull_distance : require
14886
14887 layout(lines_adjacency, invocations = 3) in;
14888 layout(points, max_vertices = 16) out;
14889
14890 out gl_PerVertex {
14891 vec4 gl_Position;
14892 float gl_ClipDistance[4];
14893 float gl_CullDistance[4];
14894 };
14895
14896 void main()
14897 {
14898 for (int n = 0; n < 16; ++n)
14899 {
14900 gl_Position = vec4(n, 0.0, 0.0, 1.0);
14901 EmitVertex();
14902 }
14903
14904 EndPrimitive();
14905 })";
14906
14907 constexpr char kFS[] = R"(#version 310 es
14908 precision highp float;
14909
14910 out vec4 result;
14911
14912 void main()
14913 {
14914 result = vec4(1.0);
14915 })";
14916
14917 ANGLE_GL_PROGRAM_WITH_GS(program, kVS, kGS, kFS);
14918 EXPECT_GL_NO_ERROR();
14919 }
14920
14921 // Negative test using builtins that can only be used when redefining gl_PerVertex
TEST_P(GLSLTest_ES31,PerVertexNegativeTest)14922 TEST_P(GLSLTest_ES31, PerVertexNegativeTest)
14923 {
14924 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
14925 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_clip_cull_distance"));
14926
14927 constexpr char kVS[] = R"(#version 310 es
14928 void main()
14929 {
14930 gl_Position = vec4(1.0, 0.0, 0.0, 1.0);
14931 })";
14932
14933 constexpr char kGS[] = R"(#version 310 es
14934 #extension GL_EXT_geometry_shader : require
14935 #extension GL_EXT_clip_cull_distance : require
14936
14937 layout(lines_adjacency, invocations = 3) in;
14938 layout(points, max_vertices = 16) out;
14939
14940 vec4 gl_Position;
14941 float gl_ClipDistance[4];
14942 float gl_CullDistance[4];
14943
14944 void main()
14945 {
14946 for (int n = 0; n < 16; ++n)
14947 {
14948 gl_Position = vec4(n, 0.0, 0.0, 1.0);
14949 EmitVertex();
14950 }
14951
14952 EndPrimitive();
14953 })";
14954
14955 constexpr char kFS[] = R"(#version 310 es
14956 precision highp float;
14957
14958 out vec4 result;
14959
14960 void main()
14961 {
14962 result = vec4(1.0);
14963 })";
14964
14965 GLuint program = CompileProgramWithGS(kVS, kGS, kFS);
14966 EXPECT_EQ(0u, program);
14967 glDeleteProgram(program);
14968 }
14969
14970 // Negative test using builtins that can only be used when redefining gl_PerVertex
14971 // but have the builtins in a differently named struct
TEST_P(GLSLTest_ES31,PerVertexRenamedNegativeTest)14972 TEST_P(GLSLTest_ES31, PerVertexRenamedNegativeTest)
14973 {
14974 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
14975 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_clip_cull_distance"));
14976
14977 constexpr char kVS[] = R"(#version 310 es
14978 void main()
14979 {
14980 gl_Position = vec4(1.0, 0.0, 0.0, 1.0);
14981 })";
14982
14983 constexpr char kGS[] = R"(#version 310 es
14984 #extension GL_EXT_geometry_shader : require
14985 #extension GL_EXT_clip_cull_distance : require
14986
14987 layout(lines_adjacency, invocations = 3) in;
14988 layout(points, max_vertices = 16) out;
14989
14990 out Block {
14991 vec4 gl_Position;
14992 float gl_ClipDistance[4];
14993 float gl_CullDistance[4];
14994 };
14995
14996 void main()
14997 {
14998 for (int n = 0; n < 16; ++n)
14999 {
15000 gl_Position = vec4(n, 0.0, 0.0, 1.0);
15001 EmitVertex();
15002 }
15003
15004 EndPrimitive();
15005 })";
15006
15007 constexpr char kFS[] = R"(#version 310 es
15008 precision highp float;
15009
15010 out vec4 result;
15011
15012 void main()
15013 {
15014 result = vec4(1.0);
15015 })";
15016
15017 GLuint program = CompileProgramWithGS(kVS, kGS, kFS);
15018 EXPECT_EQ(0u, program);
15019 glDeleteProgram(program);
15020 }
15021
15022 // Test varying packing in presence of multiple I/O blocks
TEST_P(GLSLTest_ES31,MultipleIOBlocks)15023 TEST_P(GLSLTest_ES31, MultipleIOBlocks)
15024 {
15025 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
15026
15027 constexpr char kVS[] = R"(#version 310 es
15028 #extension GL_EXT_shader_io_blocks : require
15029
15030 in highp vec4 position;
15031
15032 out VSBlock1
15033 {
15034 vec4 a;
15035 vec4 b[2];
15036 } blockOut1;
15037
15038 out VSBlock2
15039 {
15040 vec4 c[2];
15041 vec4 d;
15042 } blockOut2;
15043
15044 void main()
15045 {
15046 blockOut1.a = vec4(0.15, 0.18, 0.21, 0.24);
15047 blockOut1.b[0] = vec4(0.27, 0.30, 0.33, 0.36);
15048 blockOut1.b[1] = vec4(0.39, 0.42, 0.45, 0.48);
15049 blockOut2.c[0] = vec4(0.51, 0.54, 0.57, 0.6);
15050 blockOut2.c[1] = vec4(0.63, 0.66, 0.66, 0.69);
15051 blockOut2.d = vec4(0.72, 0.75, 0.78, 0.81);
15052 gl_Position = position;
15053 })";
15054
15055 constexpr char kFS[] = R"(#version 310 es
15056 #extension GL_EXT_shader_io_blocks : require
15057 precision mediump float;
15058
15059 layout(location = 0) out mediump vec4 color;
15060
15061 in VSBlock1
15062 {
15063 vec4 a;
15064 vec4 b[2];
15065 } blockIn1;
15066
15067 in VSBlock2
15068 {
15069 vec4 c[2];
15070 vec4 d;
15071 } blockIn2;
15072
15073 bool isEq(vec4 a, vec4 b) { return all(lessThan(abs(a-b), vec4(0.001))); }
15074
15075 void main()
15076 {
15077 bool passR = isEq(blockIn1.a, vec4(0.15, 0.18, 0.21, 0.24));
15078 bool passG = isEq(blockIn1.b[0], vec4(0.27, 0.30, 0.33, 0.36)) &&
15079 isEq(blockIn1.b[1], vec4(0.39, 0.42, 0.45, 0.48));
15080 bool passB = isEq(blockIn2.c[0], vec4(0.51, 0.54, 0.57, 0.6)) &&
15081 isEq(blockIn2.c[1], vec4(0.63, 0.66, 0.66, 0.69));
15082 bool passA = isEq(blockIn2.d, vec4(0.72, 0.75, 0.78, 0.81));
15083
15084 color = vec4(passR, passG, passB, passA);
15085 })";
15086
15087 ANGLE_GL_PROGRAM(program, kVS, kFS);
15088 EXPECT_GL_NO_ERROR();
15089
15090 GLTexture color;
15091 glBindTexture(GL_TEXTURE_2D, color);
15092 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
15093
15094 GLFramebuffer fbo;
15095 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
15096 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
15097
15098 drawQuad(program, "position", 0);
15099
15100 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
15101 }
15102
15103 // Test varying packing in presence of I/O block arrays
TEST_P(GLSLTest_ES31,IOBlockArray)15104 TEST_P(GLSLTest_ES31, IOBlockArray)
15105 {
15106 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
15107
15108 constexpr char kVS[] = R"(#version 310 es
15109 #extension GL_EXT_shader_io_blocks : require
15110
15111 in highp vec4 position;
15112
15113 out VSBlock1
15114 {
15115 vec4 b[2];
15116 } blockOut1[2];
15117
15118 out VSBlock2
15119 {
15120 vec4 d;
15121 } blockOut2[3];
15122
15123 void main()
15124 {
15125 blockOut1[0].b[0] = vec4(0.15, 0.18, 0.21, 0.24);
15126 blockOut1[0].b[1] = vec4(0.27, 0.30, 0.33, 0.36);
15127 blockOut1[1].b[0] = vec4(0.39, 0.42, 0.45, 0.48);
15128 blockOut1[1].b[1] = vec4(0.51, 0.54, 0.57, 0.6);
15129 blockOut2[0].d = vec4(0.63, 0.66, 0.66, 0.69);
15130 blockOut2[1].d = vec4(0.72, 0.75, 0.78, 0.81);
15131 blockOut2[2].d = vec4(0.84, 0.87, 0.9, 0.93);
15132 gl_Position = position;
15133 })";
15134
15135 constexpr char kFS[] = R"(#version 310 es
15136 #extension GL_EXT_shader_io_blocks : require
15137 precision mediump float;
15138
15139 layout(location = 0) out mediump vec4 color;
15140
15141 in VSBlock1
15142 {
15143 vec4 b[2];
15144 } blockIn1[2];
15145
15146 in VSBlock2
15147 {
15148 vec4 d;
15149 } blockIn2[3];
15150
15151 bool isEq(vec4 a, vec4 b) { return all(lessThan(abs(a-b), vec4(0.001))); }
15152
15153 void main()
15154 {
15155 bool passR = isEq(blockIn1[0].b[0], vec4(0.15, 0.18, 0.21, 0.24)) &&
15156 isEq(blockIn1[0].b[1], vec4(0.27, 0.30, 0.33, 0.36));
15157 bool passG = isEq(blockIn1[1].b[0], vec4(0.39, 0.42, 0.45, 0.48)) &&
15158 isEq(blockIn1[1].b[1], vec4(0.51, 0.54, 0.57, 0.6));
15159 bool passB = isEq(blockIn2[0].d, vec4(0.63, 0.66, 0.66, 0.69));
15160 bool passA = isEq(blockIn2[1].d, vec4(0.72, 0.75, 0.78, 0.81)) &&
15161 isEq(blockIn2[2].d, vec4(0.84, 0.87, 0.9, 0.93));
15162
15163 color = vec4(passR, passG, passB, passA);
15164 })";
15165
15166 ANGLE_GL_PROGRAM(program, kVS, kFS);
15167 EXPECT_GL_NO_ERROR();
15168
15169 GLTexture color;
15170 glBindTexture(GL_TEXTURE_2D, color);
15171 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
15172
15173 GLFramebuffer fbo;
15174 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
15175 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
15176
15177 drawQuad(program, "position", 0);
15178
15179 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
15180 }
15181
15182 // Validate that link fails with I/O block member name mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberNameMismatch)15183 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberNameMismatch)
15184 {
15185 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
15186
15187 constexpr char kVS[] = R"(#version 310 es
15188 #extension GL_EXT_shader_io_blocks : require
15189 in highp vec4 position;
15190 out VSBlock { vec4 a; vec4 b[2]; } blockOut1;
15191 void main()
15192 {
15193 blockOut1.a = vec4(0);
15194 blockOut1.b[0] = vec4(0);
15195 blockOut1.b[1] = vec4(0);
15196 gl_Position = position;
15197 })";
15198
15199 constexpr char kFS[] = R"(#version 310 es
15200 #extension GL_EXT_shader_io_blocks : require
15201 precision mediump float;
15202 layout(location = 0) out mediump vec4 color;
15203 in VSBlock { vec4 c; vec4 b[2]; } blockIn1;
15204 void main()
15205 {
15206 color = vec4(blockIn1.c.x, blockIn1.b[0].y, blockIn1.b[1].z, 1.0);
15207 })";
15208
15209 GLuint program = CompileProgram(kVS, kFS);
15210 EXPECT_EQ(0u, program);
15211 }
15212
15213 // Validate that link fails with I/O block member array size mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberArraySizeMismatch)15214 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberArraySizeMismatch)
15215 {
15216 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
15217
15218 constexpr char kVS[] = R"(#version 310 es
15219 #extension GL_EXT_shader_io_blocks : require
15220 in highp vec4 position;
15221 out VSBlock { vec4 a; vec4 b[2]; } blockOut1;
15222 void main()
15223 {
15224 blockOut1.a = vec4(0);
15225 blockOut1.b[0] = vec4(0);
15226 blockOut1.b[1] = vec4(0);
15227 gl_Position = position;
15228 })";
15229
15230 constexpr char kFS[] = R"(#version 310 es
15231 #extension GL_EXT_shader_io_blocks : require
15232 precision mediump float;
15233 layout(location = 0) out mediump vec4 color;
15234 in VSBlock { vec4 a; vec4 b[3]; } blockIn1;
15235 void main()
15236 {
15237 color = vec4(blockIn1.a.x, blockIn1.b[0].y, blockIn1.b[1].z, 1.0);
15238 })";
15239
15240 GLuint program = CompileProgram(kVS, kFS);
15241 EXPECT_EQ(0u, program);
15242 }
15243
15244 // Validate that link fails with I/O block member type mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberTypeMismatch)15245 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberTypeMismatch)
15246 {
15247 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
15248
15249 constexpr char kVS[] = R"(#version 310 es
15250 #extension GL_EXT_shader_io_blocks : require
15251 in highp vec4 position;
15252 out VSBlock { vec4 a; vec4 b[2]; } blockOut1;
15253 void main()
15254 {
15255 blockOut1.a = vec4(0);
15256 blockOut1.b[0] = vec4(0);
15257 blockOut1.b[1] = vec4(0);
15258 gl_Position = position;
15259 })";
15260
15261 constexpr char kFS[] = R"(#version 310 es
15262 #extension GL_EXT_shader_io_blocks : require
15263 precision mediump float;
15264 layout(location = 0) out mediump vec4 color;
15265 in VSBlock { vec3 a; vec4 b[2]; } blockIn1;
15266 void main()
15267 {
15268 color = vec4(blockIn1.a.x, blockIn1.b[0].y, blockIn1.b[1].z, 1.0);
15269 })";
15270
15271 GLuint program = CompileProgram(kVS, kFS);
15272 EXPECT_EQ(0u, program);
15273 }
15274
15275 // Validate that link fails with I/O block location mismatches
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkLocationMismatch)15276 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkLocationMismatch)
15277 {
15278 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
15279
15280 constexpr char kVS[] = R"(#version 310 es
15281 #extension GL_EXT_shader_io_blocks : require
15282 in highp vec4 position;
15283 layout(location = 2) out VSBlock { vec4 a; vec4 b[2]; } blockOut1;
15284 void main()
15285 {
15286 blockOut1.a = vec4(0);
15287 blockOut1.b[0] = vec4(0);
15288 blockOut1.b[1] = vec4(0);
15289 gl_Position = position;
15290 })";
15291
15292 constexpr char kFS[] = R"(#version 310 es
15293 #extension GL_EXT_shader_io_blocks : require
15294 precision mediump float;
15295 layout(location = 0) out mediump vec4 color;
15296 layout(location = 1) in VSBlock { vec4 a; vec4 b[2]; } blockIn1;
15297 void main()
15298 {
15299 color = vec4(blockIn1.a.x, blockIn1.b[0].y, blockIn1.b[1].z, 1.0);
15300 })";
15301
15302 GLuint program = CompileProgram(kVS, kFS);
15303 EXPECT_EQ(0u, program);
15304 }
15305
15306 // Validate that link fails with I/O block member location mismatches
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberLocationMismatch)15307 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberLocationMismatch)
15308 {
15309 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
15310
15311 constexpr char kVS[] = R"(#version 310 es
15312 #extension GL_EXT_shader_io_blocks : require
15313 in highp vec4 position;
15314 out VSBlock { vec4 a; layout(location = 2) vec4 b[2]; } blockOut1;
15315 void main()
15316 {
15317 blockOut1.a = vec4(0);
15318 blockOut1.b[0] = vec4(0);
15319 blockOut1.b[1] = vec4(0);
15320 gl_Position = position;
15321 })";
15322
15323 constexpr char kFS[] = R"(#version 310 es
15324 #extension GL_EXT_shader_io_blocks : require
15325 precision mediump float;
15326 layout(location = 0) out mediump vec4 color;
15327 in VSBlock { vec4 a; layout(location = 3) vec4 b[2]; } blockIn1;
15328 void main()
15329 {
15330 color = vec4(blockIn1.a.x, blockIn1.b[0].y, blockIn1.b[1].z, 1.0);
15331 })";
15332
15333 GLuint program = CompileProgram(kVS, kFS);
15334 EXPECT_EQ(0u, program);
15335 }
15336
15337 // Validate that link fails with I/O block member struct name mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberStructNameMismatch)15338 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberStructNameMismatch)
15339 {
15340 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
15341
15342 constexpr char kVS[] = R"(#version 310 es
15343 #extension GL_EXT_shader_io_blocks : require
15344 in highp vec4 position;
15345 struct S1 { vec4 a; vec4 b[2]; };
15346 out VSBlock { S1 s; } blockOut1;
15347 void main()
15348 {
15349 blockOut1.s.a = vec4(0);
15350 blockOut1.s.b[0] = vec4(0);
15351 blockOut1.s.b[1] = vec4(0);
15352 gl_Position = position;
15353 })";
15354
15355 constexpr char kFS[] = R"(#version 310 es
15356 #extension GL_EXT_shader_io_blocks : require
15357 precision mediump float;
15358 layout(location = 0) out mediump vec4 color;
15359 struct S2 { vec4 a; vec4 b[2]; };
15360 in VSBlock { S2 s; } blockIn1;
15361 void main()
15362 {
15363 color = vec4(blockIn1.s.a.x, blockIn1.s.b[0].y, blockIn1.s.b[1].z, 1.0);
15364 })";
15365
15366 GLuint program = CompileProgram(kVS, kFS);
15367 EXPECT_EQ(0u, program);
15368 }
15369
15370 // Validate that link fails with I/O block member struct member name mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberStructMemberNameMismatch)15371 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberStructMemberNameMismatch)
15372 {
15373 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
15374
15375 constexpr char kVS[] = R"(#version 310 es
15376 #extension GL_EXT_shader_io_blocks : require
15377 in highp vec4 position;
15378 struct S { vec4 c; vec4 b[2]; };
15379 out VSBlock { S s; } blockOut1;
15380 void main()
15381 {
15382 blockOut1.s.c = vec4(0);
15383 blockOut1.s.b[0] = vec4(0);
15384 blockOut1.s.b[1] = vec4(0);
15385 gl_Position = position;
15386 })";
15387
15388 constexpr char kFS[] = R"(#version 310 es
15389 #extension GL_EXT_shader_io_blocks : require
15390 precision mediump float;
15391 layout(location = 0) out mediump vec4 color;
15392 struct S { vec4 a; vec4 b[2]; };
15393 in VSBlock { S s; } blockIn1;
15394 void main()
15395 {
15396 color = vec4(blockIn1.s.a.x, blockIn1.s.b[0].y, blockIn1.s.b[1].z, 1.0);
15397 })";
15398
15399 GLuint program = CompileProgram(kVS, kFS);
15400 EXPECT_EQ(0u, program);
15401 }
15402
15403 // Validate that link fails with I/O block member struct member type mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberStructMemberTypeMismatch)15404 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberStructMemberTypeMismatch)
15405 {
15406 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
15407
15408 constexpr char kVS[] = R"(#version 310 es
15409 #extension GL_EXT_shader_io_blocks : require
15410 in highp vec4 position;
15411 struct S { vec4 a; vec4 b[2]; };
15412 out VSBlock { S s; } blockOut1;
15413 void main()
15414 {
15415 blockOut1.s.a = vec4(0);
15416 blockOut1.s.b[0] = vec4(0);
15417 blockOut1.s.b[1] = vec4(0);
15418 gl_Position = position;
15419 })";
15420
15421 constexpr char kFS[] = R"(#version 310 es
15422 #extension GL_EXT_shader_io_blocks : require
15423 precision mediump float;
15424 layout(location = 0) out mediump vec4 color;
15425 struct S { vec3 a; vec4 b[2]; };
15426 in VSBlock { S s; } blockIn1;
15427 void main()
15428 {
15429 color = vec4(blockIn1.s.a.x, blockIn1.s.b[0].y, blockIn1.s.b[1].z, 1.0);
15430 })";
15431
15432 GLuint program = CompileProgram(kVS, kFS);
15433 EXPECT_EQ(0u, program);
15434 }
15435
15436 // Validate that link fails with I/O block member struct member array size mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberStructMemberArraySizeMismatch)15437 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberStructMemberArraySizeMismatch)
15438 {
15439 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
15440
15441 constexpr char kVS[] = R"(#version 310 es
15442 #extension GL_EXT_shader_io_blocks : require
15443 in highp vec4 position;
15444 struct S { vec4 a; vec4 b[3]; };
15445 out VSBlock { S s; } blockOut1;
15446 void main()
15447 {
15448 blockOut1.s.a = vec4(0);
15449 blockOut1.s.b[0] = vec4(0);
15450 blockOut1.s.b[1] = vec4(0);
15451 gl_Position = position;
15452 })";
15453
15454 constexpr char kFS[] = R"(#version 310 es
15455 #extension GL_EXT_shader_io_blocks : require
15456 precision mediump float;
15457 layout(location = 0) out mediump vec4 color;
15458 struct S { vec4 a; vec4 b[2]; };
15459 in VSBlock { S s; } blockIn1;
15460 void main()
15461 {
15462 color = vec4(blockIn1.s.a.x, blockIn1.s.b[0].y, blockIn1.s.b[1].z, 1.0);
15463 })";
15464
15465 GLuint program = CompileProgram(kVS, kFS);
15466 EXPECT_EQ(0u, program);
15467 }
15468
15469 // Validate that link fails with I/O block member struct member count mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberStructMemberCountMismatch)15470 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberStructMemberCountMismatch)
15471 {
15472 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
15473
15474 constexpr char kVS[] = R"(#version 310 es
15475 #extension GL_EXT_shader_io_blocks : require
15476 in highp vec4 position;
15477 struct S { vec4 a; vec4 b[2]; vec4 c; };
15478 out VSBlock { S s; } blockOut1;
15479 void main()
15480 {
15481 blockOut1.s.c = vec4(0);
15482 blockOut1.s.b[0] = vec4(0);
15483 blockOut1.s.b[1] = vec4(0);
15484 gl_Position = position;
15485 })";
15486
15487 constexpr char kFS[] = R"(#version 310 es
15488 #extension GL_EXT_shader_io_blocks : require
15489 precision mediump float;
15490 layout(location = 0) out mediump vec4 color;
15491 struct S { vec4 a; vec4 b[2]; };
15492 in VSBlock { S s; } blockIn1;
15493 void main()
15494 {
15495 color = vec4(blockIn1.s.a.x, blockIn1.s.b[0].y, blockIn1.s.b[1].z, 1.0);
15496 })";
15497
15498 GLuint program = CompileProgram(kVS, kFS);
15499 EXPECT_EQ(0u, program);
15500 }
15501
15502 // Validate that link fails with I/O block member nested struct mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberNestedStructMismatch)15503 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberNestedStructMismatch)
15504 {
15505 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
15506
15507 constexpr char kVS[] = R"(#version 310 es
15508 #extension GL_EXT_shader_io_blocks : require
15509 in highp vec4 position;
15510 struct S1 { vec4 c; vec4 b[2]; };
15511 struct S2 { S1 s; };
15512 struct S3 { S2 s; };
15513 out VSBlock { S3 s; } blockOut1;
15514 void main()
15515 {
15516 blockOut1.s.s.s.c = vec4(0);
15517 blockOut1.s.s.s.b[0] = vec4(0);
15518 blockOut1.s.s.s.b[1] = vec4(0);
15519 gl_Position = position;
15520 })";
15521
15522 constexpr char kFS[] = R"(#version 310 es
15523 #extension GL_EXT_shader_io_blocks : require
15524 precision mediump float;
15525 layout(location = 0) out mediump vec4 color;
15526 struct S1 { vec4 a; vec4 b[2]; };
15527 struct S2 { S1 s; };
15528 struct S3 { S2 s; };
15529 in VSBlock { S3 s; } blockIn1;
15530 void main()
15531 {
15532 color = vec4(blockIn1.s.s.s.a.x, blockIn1.s.s.s.b[0].y, blockIn1.s.s.s.b[1].z, 1.0);
15533 })";
15534
15535 GLuint program = CompileProgram(kVS, kFS);
15536 EXPECT_EQ(0u, program);
15537 }
15538
15539 // Test that separating declarators works with structs that have been separately defined.
TEST_P(GLSLTest_ES31,SeparateDeclaratorsOfStructType)15540 TEST_P(GLSLTest_ES31, SeparateDeclaratorsOfStructType)
15541 {
15542 constexpr char kVS[] = R"(#version 310 es
15543 precision highp float;
15544
15545 struct S
15546 {
15547 mat4 a;
15548 mat4 b;
15549 };
15550
15551 S s1 = S(mat4(1), mat4(2)), s2[2][3], s3[2] = S[2](S(mat4(0), mat4(3)), S(mat4(4), mat4(5)));
15552
15553 void main() {
15554 S s4[2][3] = s2, s5 = s3[0], s6[2] = S[2](s1, s5), s7 = s5;
15555
15556 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);
15557 })";
15558
15559 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
15560
15561 const char *sourceArray[1] = {kVS};
15562 GLint lengths[1] = {static_cast<GLint>(sizeof(kVS) - 1)};
15563 glShaderSource(shader, 1, sourceArray, lengths);
15564 glCompileShader(shader);
15565
15566 GLint compileResult;
15567 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
15568 EXPECT_NE(compileResult, 0);
15569 }
15570
15571 // Test that separating declarators works with structs that are simultaneously defined.
TEST_P(GLSLTest_ES31,SeparateDeclaratorsOfStructTypeBeingSpecified)15572 TEST_P(GLSLTest_ES31, SeparateDeclaratorsOfStructTypeBeingSpecified)
15573 {
15574 constexpr char kVS[] = R"(#version 310 es
15575 precision highp float;
15576
15577 struct S
15578 {
15579 mat4 a;
15580 mat4 b;
15581 } s1 = S(mat4(1), mat4(2)), s2[2][3], s3[2] = S[2](S(mat4(0), mat4(3)), S(mat4(4), mat4(5)));
15582
15583 void main() {
15584 struct T
15585 {
15586 mat4 a;
15587 mat4 b;
15588 } s4[2][3], s5 = T(s3[0].a, s3[0].b), s6[2] = T[2](T(s1.a, s1.b), s5), s7 = s5;
15589
15590 float f1 = s3[1].a[0].x, f2 = s2[0][2].b[1].y;
15591
15592 gl_Position = vec4(f1, f2, s4[1][0].a[2].z, s6[0].b[3].w);
15593 })";
15594
15595 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
15596
15597 const char *sourceArray[1] = {kVS};
15598 GLint lengths[1] = {static_cast<GLint>(sizeof(kVS) - 1)};
15599 glShaderSource(shader, 1, sourceArray, lengths);
15600 glCompileShader(shader);
15601
15602 GLint compileResult;
15603 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
15604 EXPECT_NE(compileResult, 0);
15605 }
15606
15607 // Test that separating declarators works with structs that are simultaneously defined and that are
15608 // nameless.
TEST_P(GLSLTest_ES31,SeparateDeclaratorsOfNamelessStructType)15609 TEST_P(GLSLTest_ES31, SeparateDeclaratorsOfNamelessStructType)
15610 {
15611 constexpr char kVS[] = R"(#version 310 es
15612 precision highp float;
15613
15614 struct
15615 {
15616 mat4 a;
15617 mat4 b;
15618 } s1, s2[2][3], s3[2];
15619
15620 void main() {
15621 struct
15622 {
15623 mat4 a;
15624 mat4 b;
15625 } s4[2][3], s5, s6[2], s7 = s5;
15626
15627 float f1 = s1.a[0].x + s3[1].a[0].x, f2 = s2[0][2].b[1].y + s7.b[1].z;
15628
15629 gl_Position = vec4(f1, f2, s4[1][0].a[2].z, s6[0].b[3].w);
15630 })";
15631
15632 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
15633
15634 const char *sourceArray[1] = {kVS};
15635 GLint lengths[1] = {static_cast<GLint>(sizeof(kVS) - 1)};
15636 glShaderSource(shader, 1, sourceArray, lengths);
15637 glCompileShader(shader);
15638
15639 GLint compileResult;
15640 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
15641 EXPECT_NE(compileResult, 0);
15642 }
15643
15644 // Test separation of struct declarations, case where separated struct is used as a member of
15645 // another struct.
TEST_P(GLSLTest,SeparateStructDeclaratorStructInStruct)15646 TEST_P(GLSLTest, SeparateStructDeclaratorStructInStruct)
15647 {
15648 const char kFragmentShader[] = R"(precision mediump float;
15649 uniform vec4 u;
15650 struct S1 { vec4 v; } a;
15651 void main()
15652 {
15653 struct S2 { S1 s1; } b;
15654 a.v = u;
15655 b.s1 = a;
15656 gl_FragColor = b.s1.v + vec4(0, 0, 0, 1);
15657 }
15658 )";
15659 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
15660 glUseProgram(program);
15661 GLint u = glGetUniformLocation(program, "u");
15662 glUniform4f(u, 0, 1, 0, 0);
15663 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
15664 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
15665 }
15666
15667 // Regression test for transformation bug which separates struct declarations from uniform
15668 // declarations. The bug was that the uniform variable usage in the initializer of a new
15669 // declaration (y below) was not being processed.
TEST_P(GLSLTest,UniformStructBug)15670 TEST_P(GLSLTest, UniformStructBug)
15671 {
15672 constexpr char kVS[] = R"(precision highp float;
15673
15674 uniform struct Global
15675 {
15676 float x;
15677 } u_global;
15678
15679 void main() {
15680 float y = u_global.x;
15681
15682 gl_Position = vec4(y);
15683 })";
15684
15685 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
15686
15687 const char *sourceArray[1] = {kVS};
15688 GLint lengths[1] = {static_cast<GLint>(sizeof(kVS) - 1)};
15689 glShaderSource(shader, 1, sourceArray, lengths);
15690 glCompileShader(shader);
15691
15692 GLint compileResult;
15693 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
15694 EXPECT_NE(compileResult, 0);
15695 }
15696
15697 // Regression test for transformation bug which separates struct declarations from uniform
15698 // declarations. The bug was that the arrayness of the declaration was not being applied to the
15699 // replaced uniform variable.
TEST_P(GLSLTest_ES31,UniformStructBug2)15700 TEST_P(GLSLTest_ES31, UniformStructBug2)
15701 {
15702 constexpr char kVS[] = R"(#version 310 es
15703 precision highp float;
15704
15705 uniform struct Global
15706 {
15707 float x;
15708 } u_global[2][3];
15709
15710 void main() {
15711 float y = u_global[0][0].x;
15712
15713 gl_Position = vec4(y);
15714 })";
15715
15716 GLuint shader = glCreateShader(GL_VERTEX_SHADER);
15717
15718 const char *sourceArray[1] = {kVS};
15719 GLint lengths[1] = {static_cast<GLint>(sizeof(kVS) - 1)};
15720 glShaderSource(shader, 1, sourceArray, lengths);
15721 glCompileShader(shader);
15722
15723 GLint compileResult;
15724 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
15725 EXPECT_NE(compileResult, 0);
15726 }
15727
15728 // Regression test based on fuzzer issue resulting in an AST validation failure. Struct definition
15729 // was not found in the tree. Tests that struct declaration in function return value is visible to
15730 // instantiations later on.
TEST_P(GLSLTest,MissingStructDeclarationBug)15731 TEST_P(GLSLTest, MissingStructDeclarationBug)
15732 {
15733 constexpr char kVS[] = R"(
15734 struct S
15735 {
15736 vec4 i;
15737 } p();
15738 void main()
15739 {
15740 S s;
15741 })";
15742
15743 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
15744 EXPECT_NE(0u, shader);
15745 glDeleteShader(shader);
15746 }
15747
15748 // Regression test based on fuzzer issue resulting in an AST validation failure. Struct definition
15749 // was not found in the tree. Tests that struct declaration in function return value is visible to
15750 // other struct declarations.
TEST_P(GLSLTest,MissingStructDeclarationBug2)15751 TEST_P(GLSLTest, MissingStructDeclarationBug2)
15752 {
15753 constexpr char kVS[] = R"(
15754 struct T
15755 {
15756 vec4 I;
15757 } p();
15758 struct
15759 {
15760 T c;
15761 };
15762 void main()
15763 {
15764 })";
15765
15766 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
15767 EXPECT_NE(0u, shader);
15768 glDeleteShader(shader);
15769 }
15770
15771 // Regression test for bug in HLSL code generation where the for loop init expression was expected
15772 // to always have an initializer.
TEST_P(GLSLTest,HandleExcessiveLoopBug)15773 TEST_P(GLSLTest, HandleExcessiveLoopBug)
15774 {
15775 constexpr char kVS[] = R"(void main(){for(int i;i>6;);})";
15776
15777 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
15778 EXPECT_NE(0u, shader);
15779 glDeleteShader(shader);
15780 }
15781
15782 // Regression test for a validation bug in the translator where func(void, int) was accepted even
15783 // though it's illegal, and the function was callable as if the void parameter isn't there.
TEST_P(GLSLTest,NoParameterAfterVoid)15784 TEST_P(GLSLTest, NoParameterAfterVoid)
15785 {
15786 constexpr char kVS[] = R"(void f(void, int a){}
15787 void main(){f(1);})";
15788
15789 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
15790 EXPECT_EQ(0u, shader);
15791 glDeleteShader(shader);
15792 }
15793
15794 // Similar to NoParameterAfterVoid, but tests func(void, void).
TEST_P(GLSLTest,NoParameterAfterVoid2)15795 TEST_P(GLSLTest, NoParameterAfterVoid2)
15796 {
15797 constexpr char kVS[] = R"(void f(void, void){}
15798 void main(){f();})";
15799
15800 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
15801 EXPECT_EQ(0u, shader);
15802 glDeleteShader(shader);
15803 }
15804
15805 // Test that providing more components to a matrix constructor than necessary works. Based on a
15806 // clusterfuzz test that caught an OOB array write in glslang.
TEST_P(GLSLTest,MatrixConstructor)15807 TEST_P(GLSLTest, MatrixConstructor)
15808 {
15809 constexpr char kVS[] = R"(attribute vec4 aPosition;
15810 varying vec4 vColor;
15811 void main()
15812 {
15813 gl_Position = aPosition;
15814 vec4 color = vec4(aPosition.xy, 0, 1);
15815 mat4 m4 = mat4(color, color.yzwx, color.zwx, color.zwxy, color.wxyz);
15816 vColor = m4[0];
15817 })";
15818
15819 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
15820 EXPECT_NE(0u, shader);
15821 glDeleteShader(shader);
15822 }
15823
15824 // Test constructors without precision
TEST_P(GLSLTest,ConstructFromBoolVector)15825 TEST_P(GLSLTest, ConstructFromBoolVector)
15826 {
15827 constexpr char kFS[] = R"(precision mediump float;
15828 uniform float u;
15829 void main()
15830 {
15831 mat4 m = mat4(u);
15832 mat2(0, bvec3(m));
15833 gl_FragColor = vec4(m);
15834 })";
15835
15836 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
15837 EXPECT_NE(0u, shader);
15838 glDeleteShader(shader);
15839 }
15840
15841 // Test constructing vector from matrix
TEST_P(GLSLTest,VectorConstructorFromMatrix)15842 TEST_P(GLSLTest, VectorConstructorFromMatrix)
15843 {
15844 constexpr char kFS[] = R"(precision mediump float;
15845 uniform mat2 umat2;
15846 void main()
15847 {
15848 gl_FragColor = vec4(umat2);
15849 })";
15850
15851 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
15852 EXPECT_NE(0u, shader);
15853 glDeleteShader(shader);
15854 }
15855
15856 // Test constructing matrix from vectors
TEST_P(GLSLTest,MatrixConstructorFromVectors)15857 TEST_P(GLSLTest, MatrixConstructorFromVectors)
15858 {
15859 constexpr char kFS[] = R"(precision mediump float;
15860 uniform vec2 uvec2;
15861 void main()
15862 {
15863 mat2 m = mat2(uvec2, uvec2.yx);
15864 gl_FragColor = vec4(m * uvec2, uvec2);
15865 })";
15866
15867 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
15868 glUseProgram(program);
15869
15870 GLint uloc = glGetUniformLocation(program, "uvec2");
15871 ASSERT_NE(uloc, -1);
15872 glUniform2f(uloc, 0.5, 0.8);
15873
15874 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
15875 EXPECT_GL_NO_ERROR();
15876
15877 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(227, 204, 127, 204), 1);
15878 }
15879
15880 // Test that constructing vector and matrix inside multiple declarations preserves the correct order
15881 // of operations.
TEST_P(GLSLTest,ConstructorinSequenceOperator)15882 TEST_P(GLSLTest, ConstructorinSequenceOperator)
15883 {
15884 constexpr char kFS[] = R"(precision mediump float;
15885 uniform vec2 u;
15886 void main()
15887 {
15888 vec2 v = u;
15889 mat2 m = (v[0] += 1.0, mat2(v, v[1], -v[0]));
15890 gl_FragColor = vec4(m[0], m[1]);
15891 })";
15892
15893 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
15894 glUseProgram(program);
15895
15896 GLint uloc = glGetUniformLocation(program, "u");
15897 ASSERT_NE(uloc, -1);
15898 glUniform2f(uloc, -0.5, 1.0);
15899
15900 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
15901 EXPECT_GL_NO_ERROR();
15902
15903 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(127, 255, 255, 0), 1);
15904 }
15905
15906 // Test that constructing vectors inside multiple declarations preserves the correct order
15907 // of operations.
TEST_P(GLSLTest,VectorConstructorsInMultiDeclaration)15908 TEST_P(GLSLTest, VectorConstructorsInMultiDeclaration)
15909 {
15910 constexpr char kFS[] = R"(precision mediump float;
15911 uniform vec2 u;
15912 void main()
15913 {
15914 vec2 v = vec2(u[0]),
15915 w = mat2(v, v) * u;
15916 gl_FragColor = vec4(v, w);
15917 })";
15918
15919 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
15920 glUseProgram(program);
15921
15922 GLint uloc = glGetUniformLocation(program, "u");
15923 ASSERT_NE(uloc, -1);
15924 glUniform2f(uloc, 0.5, 0.8);
15925
15926 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
15927 EXPECT_GL_NO_ERROR();
15928
15929 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(127, 127, 166, 166), 1);
15930 }
15931
15932 // Test complex constructor usage.
TEST_P(GLSLTest_ES3,ComplexConstructor)15933 TEST_P(GLSLTest_ES3, ComplexConstructor)
15934 {
15935 constexpr char kFS[] = R"(#version 300 es
15936 precision mediump float;
15937 uniform vec2 u; // = vec2(0.5, 0.8)
15938 uniform vec2 v; // = vec2(-0.2, 1.0)
15939
15940 out vec4 color;
15941
15942 bool f(mat2 m)
15943 {
15944 return m[0][0] > 0.;
15945 }
15946
15947 bool isEqual(float a, float b)
15948 {
15949 return abs(a - b) < 0.01;
15950 }
15951
15952 void main()
15953 {
15954 int shouldRemainZero = 0;
15955
15956 // Test side effects inside constructor args after short-circuit
15957 if (u.x < 0. && f(mat2(shouldRemainZero += 1, u, v)))
15958 {
15959 shouldRemainZero += 2;
15960 }
15961
15962 int shouldBecomeFive = 0;
15963
15964 // Test directly nested constructors
15965 mat4x3 m = mat4x3(mat2(shouldBecomeFive += 5, v, u));
15966
15967 // Test indirectly nested constructors
15968 mat2 m2 = mat2(f(mat2(u, v)), f(mat2(v, u)), f(mat2(f(mat2(1.)))), -1.);
15969
15970 // Verify
15971 bool sideEffectsOk = shouldRemainZero == 0 && shouldBecomeFive == 5;
15972
15973 bool mOk = isEqual(m[0][0], 5.) && isEqual(m[0][1], -0.2) && isEqual(m[0][2], 0.) &&
15974 isEqual(m[1][0], 1.) && isEqual(m[1][1], 0.5) && isEqual(m[1][2], 0.) &&
15975 isEqual(m[2][0], 0.) && isEqual(m[2][1], 0.) && isEqual(m[2][2], 1.) &&
15976 isEqual(m[3][0], 0.) && isEqual(m[3][1], 0.) && isEqual(m[3][2], 0.);
15977
15978 bool m2Ok = isEqual(m2[0][0], 1.) && isEqual(m2[0][1], 0.) &&
15979 isEqual(m2[1][0], 1.) && isEqual(m2[1][1], -1.);
15980
15981 color = vec4(sideEffectsOk ? 1 : 0, mOk ? 1 : 0, m2Ok ? 1 : 0, 1);
15982 })";
15983
15984 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
15985 glUseProgram(program);
15986
15987 GLint uloc = glGetUniformLocation(program, "u");
15988 GLint vloc = glGetUniformLocation(program, "v");
15989 ASSERT_NE(uloc, -1);
15990 ASSERT_NE(vloc, -1);
15991 glUniform2f(uloc, 0.5, 0.8);
15992 glUniform2f(vloc, -0.2, 1.0);
15993
15994 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
15995 EXPECT_GL_NO_ERROR();
15996
15997 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
15998 }
15999
16000 // Test that scalar(nonScalar) constructors work.
TEST_P(GLSLTest_ES3,ScalarConstructor)16001 TEST_P(GLSLTest_ES3, ScalarConstructor)
16002 {
16003 constexpr char kFS[] = R"(#version 300 es
16004 precision mediump float;
16005 uniform vec4 u;
16006 out vec4 color;
16007 void main()
16008 {
16009 float f1 = float(u);
16010 mat3 m = mat3(u, u, u);
16011 int i = int(m);
16012 color = vec4(f1, float(i), 0, 1);
16013 })";
16014
16015 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
16016 glUseProgram(program);
16017
16018 GLint uloc = glGetUniformLocation(program, "u");
16019 ASSERT_NE(uloc, -1);
16020 glUniform4f(uloc, 1.0, 0.4, 0.2, 0.7);
16021
16022 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
16023 EXPECT_GL_NO_ERROR();
16024
16025 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
16026 }
16027
16028 // Test that initializing global variables with non-constant values work
TEST_P(GLSLTest_ES3,InitGlobalNonConstant)16029 TEST_P(GLSLTest_ES3, InitGlobalNonConstant)
16030 {
16031 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_non_constant_global_initializers"));
16032
16033 constexpr char kVS[] = R"(#version 300 es
16034 #extension GL_EXT_shader_non_constant_global_initializers : require
16035 uniform vec4 u;
16036 out vec4 color;
16037
16038 vec4 global1 = u;
16039 vec4 global2 = u + vec4(1);
16040 vec4 global3 = global1 * global2;
16041 void main()
16042 {
16043 color = global3;
16044 })";
16045
16046 GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
16047 EXPECT_NE(0u, shader);
16048 glDeleteShader(shader);
16049 }
16050
16051 // Test that initializing global variables with complex constants work
TEST_P(GLSLTest_ES3,InitGlobalComplexConstant)16052 TEST_P(GLSLTest_ES3, InitGlobalComplexConstant)
16053 {
16054 constexpr char kFS[] = R"(#version 300 es
16055 precision highp float;
16056 out vec4 color;
16057
16058 struct T
16059 {
16060 float f;
16061 };
16062
16063 struct S
16064 {
16065 vec4 v;
16066 mat3x4 m[2];
16067 T t;
16068 };
16069
16070 S s = S(
16071 vec4(0, 1, 2, 3),
16072 mat3x4[2](
16073 mat3x4(
16074 vec4(4, 5, 6, 7),
16075 vec4(8, 9, 10, 11),
16076 vec4(12, 13, 14, 15)
16077 ),
16078 mat3x4(
16079 vec4(16, 17, 18, 19),
16080 vec4(20, 21, 22, 23),
16081 vec4(24, 25, 26, 27)
16082 )
16083 ),
16084 T(28.0)
16085 );
16086
16087 void main()
16088 {
16089 vec4 result = vec4(0, 1, 0, 1);
16090
16091 if (s.v != vec4(0, 1, 2, 3))
16092 result = vec4(1, 0, 0, 0);
16093
16094 for (int index = 0; index < 2; ++index)
16095 {
16096 for (int column = 0; column < 3; ++column)
16097 {
16098 int expect = index * 12 + column * 4 + 4;
16099 if (s.m[index][column] != vec4(expect, expect + 1, expect + 2, expect + 3))
16100 result = vec4(float(index + 1) / 2.0, 0, float(column + 1) / 3.0, 1);
16101 }
16102 }
16103
16104 if (s.t.f != 28.0)
16105 result = vec4(0, 0, 1, 0);
16106
16107 color = result;
16108 })";
16109
16110 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
16111
16112 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
16113 EXPECT_GL_NO_ERROR();
16114
16115 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
16116 }
16117
16118 // Test that built-ins with out parameters work
TEST_P(GLSLTest_ES31,BuiltInsWithOutParameters)16119 TEST_P(GLSLTest_ES31, BuiltInsWithOutParameters)
16120 {
16121 constexpr char kFS[] = R"(#version 310 es
16122 precision highp float;
16123 precision highp int;
16124
16125 out vec4 color;
16126
16127 uniform float f; // = 3.41
16128 uniform uvec4 u1; // = 0xFEDCBA98, 0x13579BDF, 0xFEDCBA98, 0x13579BDF
16129 uniform uvec4 u2; // = 0xECA86420, 0x12345678, 0x12345678, 0xECA86420
16130
16131 struct S
16132 {
16133 float fvalue;
16134 int ivalues[2];
16135 uvec4 uvalues[3];
16136 };
16137
16138 struct T
16139 {
16140 S s[2];
16141 };
16142
16143 void main()
16144 {
16145 float integer;
16146 float fraction = modf(f, integer);
16147
16148 T t;
16149
16150 t.s[0].fvalue = frexp(f, t.s[0].ivalues[0]);
16151 float significand = t.s[0].fvalue;
16152 int exponent = t.s[0].ivalues[0];
16153
16154 t.s[0].uvalues[0] = uaddCarry(u1, u2, t.s[0].uvalues[1].yxwz);
16155 uvec4 addResult = t.s[0].uvalues[0];
16156 uvec4 addCarry = t.s[0].uvalues[1].yxwz;
16157
16158 t.s[0].uvalues[2].wx = usubBorrow(u1.wx, u2.wx, t.s[1].uvalues[0].wx);
16159 uvec2 subResult = t.s[0].uvalues[2].wx;
16160 uvec2 subBorrow = t.s[1].uvalues[0].wx;
16161
16162 umulExtended(u1, u2, t.s[1].uvalues[1], t.s[1].uvalues[2]);
16163 uvec4 mulMsb = t.s[1].uvalues[1];
16164 uvec4 mulLsb = t.s[1].uvalues[2];
16165
16166 ivec2 imulMsb, imulLsb;
16167 imulExtended(ivec2(u1.wz), ivec2(u2.wz), imulMsb.yx, imulLsb.yx);
16168
16169 bool modfPassed = abs(fraction - 0.41) < 0.0001 && integer == 3.0;
16170 bool frexpPassed = abs(significand - 0.8525) < 0.0001 && exponent == 2;
16171 bool addPassed =
16172 addResult == uvec4(0xEB851EB8, 0x258BF257, 0x11111110, 0xFFFFFFFF) &&
16173 addCarry == uvec4(1, 0, 1, 0);
16174 bool subPassed = subResult == uvec2(0x26AF37BF, 0x12345678) && subBorrow == uvec2(1, 0);
16175 bool mulPassed =
16176 mulMsb == uvec4(0xEB9B208C, 0x01601D49, 0x121FA00A, 0x11E17CC0) &&
16177 mulLsb == uvec4(0xA83AB300, 0xD6B9FA88, 0x35068740, 0x822E97E0);
16178 bool imulPassed =
16179 imulMsb == ivec2(0xFFEB4992, 0xFE89E0E1) &&
16180 imulLsb == ivec2(0x35068740, 0x822E97E0);
16181
16182 color = vec4(modfPassed ? 1 : 0,
16183 frexpPassed ? 1 : 0,
16184 (addPassed ? 0.4 : 0.0) + (subPassed ? 0.6 : 0.0),
16185 (mulPassed ? 0.4 : 0.0) + (imulPassed ? 0.6 : 0.0));
16186 })";
16187
16188 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
16189 glUseProgram(program);
16190
16191 GLint floc = glGetUniformLocation(program, "f");
16192 GLint u1loc = glGetUniformLocation(program, "u1");
16193 GLint u2loc = glGetUniformLocation(program, "u2");
16194 ASSERT_NE(floc, -1);
16195 ASSERT_NE(u1loc, -1);
16196 ASSERT_NE(u2loc, -1);
16197 glUniform1f(floc, 3.41);
16198 glUniform4ui(u1loc, 0xFEDCBA98u, 0x13579BDFu, 0xFEDCBA98u, 0x13579BDFu);
16199 glUniform4ui(u2loc, 0xECA86420u, 0x12345678u, 0x12345678u, 0xECA86420u);
16200
16201 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
16202 EXPECT_GL_NO_ERROR();
16203
16204 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
16205 }
16206
16207 class GLSLTestLoops : public GLSLTest
16208 {
16209 protected:
runTest(const char * fs)16210 void runTest(const char *fs)
16211 {
16212 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fs);
16213
16214 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
16215 EXPECT_GL_NO_ERROR();
16216
16217 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
16218 }
16219 };
16220
16221 // Test basic for loops
TEST_P(GLSLTestLoops,BasicFor)16222 TEST_P(GLSLTestLoops, BasicFor)
16223 {
16224 constexpr char kFS[] = R"(#version 300 es
16225 precision mediump float;
16226 out vec4 color;
16227
16228 void main()
16229 {
16230 int result = 0;
16231 for (int i = 0; i < 10; ++i)
16232 for (int j = 0; j < 8; ++j)
16233 {
16234 for (int k = 0; k < 2; ++k, ++j) ++result;
16235 for (int k = 0; k < 3; ++k) ++result;
16236 for (int k = 0; k < 0; ++k) ++result;
16237 }
16238
16239 color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16240 })";
16241
16242 runTest(kFS);
16243 }
16244
16245 // Test for loop without condition
TEST_P(GLSLTestLoops,ForNoCondition)16246 TEST_P(GLSLTestLoops, ForNoCondition)
16247 {
16248 constexpr char kFS[] = R"(#version 300 es
16249 precision mediump float;
16250 out vec4 color;
16251
16252 void main()
16253 {
16254 int result = 0;
16255 for (int i = 0; i < 10; ++i)
16256 for (int j = 0; ; ++j)
16257 {
16258 for (int k = 0; k < 2; ++k, ++j) ++result;
16259 for (int k = 0; k < 3; ++k) ++result;
16260 for (int k = 0; k < 0; ++k) ++result;
16261
16262 if (j >= 8)
16263 break;
16264 }
16265
16266 color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16267 })";
16268
16269 runTest(kFS);
16270 }
16271
16272 // Test for loop without init and expression
TEST_P(GLSLTestLoops,ForNoInitConditionOrExpression)16273 TEST_P(GLSLTestLoops, ForNoInitConditionOrExpression)
16274 {
16275 constexpr char kFS[] = R"(#version 300 es
16276 precision mediump float;
16277 out vec4 color;
16278
16279 void main()
16280 {
16281 int result = 0;
16282 for (int i = 0; i < 10; ++i)
16283 {
16284 int j = 0;
16285 for (;;)
16286 {
16287 for (int k = 0; k < 2; ++k, ++j) ++result;
16288 for (int k = 0; k < 3; ++k) ++result;
16289 for (int k = 0; k < 0; ++k) ++result;
16290
16291 if (j >= 8)
16292 break;
16293 ++j;
16294 }
16295 }
16296
16297 color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16298 })";
16299
16300 runTest(kFS);
16301 }
16302
16303 // Test for loop with continue
TEST_P(GLSLTestLoops,ForContinue)16304 TEST_P(GLSLTestLoops, ForContinue)
16305 {
16306 constexpr char kFS[] = R"(#version 300 es
16307 precision mediump float;
16308 out vec4 color;
16309
16310 void main()
16311 {
16312 int result = 0;
16313 for (int i = 0; i < 10; ++i)
16314 for (int j = 0; j < 8; ++j)
16315 {
16316 for (int k = 0; k < 2; ++k, ++j) ++result;
16317 for (int k = 0; k < 3; ++k) ++result;
16318 if (i > 3)
16319 continue;
16320 for (int k = 0; k < 0; ++k) ++result;
16321 }
16322
16323 color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16324 })";
16325
16326 runTest(kFS);
16327 }
16328
16329 // Test for loop with continue at the end of block
TEST_P(GLSLTestLoops,ForUnconditionalContinue)16330 TEST_P(GLSLTestLoops, ForUnconditionalContinue)
16331 {
16332 constexpr char kFS[] = R"(#version 300 es
16333 precision mediump float;
16334 out vec4 color;
16335
16336 void main()
16337 {
16338 int result = 0;
16339 for (int i = 0; i < 10; ++i)
16340 for (int j = 0; j < 8; ++j)
16341 {
16342 for (int k = 0; k < 2; ++k, ++j) ++result;
16343 for (int k = 0; k < 3; ++k) ++result;
16344 for (int k = 0; k < 0; ++k) ++result;
16345 continue;
16346 }
16347
16348 color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16349 })";
16350
16351 runTest(kFS);
16352 }
16353
16354 // Test for loop with break at the end of block
TEST_P(GLSLTestLoops,ForUnconditionalBreak)16355 TEST_P(GLSLTestLoops, ForUnconditionalBreak)
16356 {
16357 constexpr char kFS[] = R"(#version 300 es
16358 precision mediump float;
16359 out vec4 color;
16360
16361 void main()
16362 {
16363 int result = 0;
16364 for (int i = 0; i < 10; ++i)
16365 for (int j = 0; j < 8; ++j)
16366 {
16367 for (int k = 0; k < 2; ++k, ++j) ++result;
16368 for (int k = 0; k < 3; ++k) ++result;
16369 for (int k = 0; k < 0; ++k) ++result;
16370 break;
16371 }
16372
16373 color = result == 50 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16374 })";
16375
16376 runTest(kFS);
16377 }
16378
16379 // Test for loop with break and continue
TEST_P(GLSLTestLoops,ForBreakContinue)16380 TEST_P(GLSLTestLoops, ForBreakContinue)
16381 {
16382 constexpr char kFS[] = R"(#version 300 es
16383 precision mediump float;
16384 out vec4 color;
16385
16386 void main()
16387 {
16388 int result = 0;
16389 for (int i = 0; i < 10; ++i)
16390 for (int j = 0; j < 8; ++j)
16391 {
16392 if (j < 2) continue;
16393 if (j > 6) break;
16394 if (i < 3) continue;
16395 if (i > 8) break;
16396 ++result;
16397 }
16398
16399 color = result == 30 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16400 })";
16401
16402 runTest(kFS);
16403 }
16404
16405 // Test basic while loops
TEST_P(GLSLTestLoops,BasicWhile)16406 TEST_P(GLSLTestLoops, BasicWhile)
16407 {
16408 constexpr char kFS[] = R"(#version 300 es
16409 precision mediump float;
16410 out vec4 color;
16411
16412 void main()
16413 {
16414 int result = 0;
16415 int i = 0;
16416 while (i < 10)
16417 {
16418 int j = 0;
16419 while (j < 8)
16420 {
16421 int k = 0;
16422 while (k < 2) { ++result; ++k; ++j; }
16423 while (k < 5) { ++result; ++k; }
16424 while (k < 4) { ++result; }
16425 ++j;
16426 }
16427 ++i;
16428 }
16429
16430 color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16431 })";
16432
16433 runTest(kFS);
16434 }
16435
16436 // Test while loops with continue
TEST_P(GLSLTestLoops,WhileContinue)16437 TEST_P(GLSLTestLoops, WhileContinue)
16438 {
16439 constexpr char kFS[] = R"(#version 300 es
16440 precision mediump float;
16441 out vec4 color;
16442
16443 void main()
16444 {
16445 int result = 0;
16446 int i = 0;
16447 while (i < 10)
16448 {
16449 int j = 0;
16450 while (j < 8)
16451 {
16452 int k = 0;
16453 while (k < 2) { ++result; ++k; ++j; }
16454 while (k < 5) { ++result; ++k; }
16455 if (i > 3)
16456 {
16457 ++j;
16458 continue;
16459 }
16460 while (k < 4) { ++result; }
16461 ++j;
16462 }
16463 ++i;
16464 }
16465
16466 color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16467 })";
16468
16469 runTest(kFS);
16470 }
16471
16472 // Test while loops with continue at the end of block
TEST_P(GLSLTestLoops,WhileUnconditionalContinue)16473 TEST_P(GLSLTestLoops, WhileUnconditionalContinue)
16474 {
16475 constexpr char kFS[] = R"(#version 300 es
16476 precision mediump float;
16477 out vec4 color;
16478
16479 void main()
16480 {
16481 int result = 0;
16482 int i = 0;
16483 while (i < 10)
16484 {
16485 int j = 0;
16486 while (j < 8)
16487 {
16488 int k = 0;
16489 while (k < 2) { ++result; ++k; ++j; }
16490 while (k < 5) { ++result; ++k; }
16491 while (k < 4) { ++result; }
16492 ++j;
16493 continue;
16494 }
16495 ++i;
16496 }
16497
16498 color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16499 })";
16500
16501 runTest(kFS);
16502 }
16503
16504 // Test while loops with break
TEST_P(GLSLTestLoops,WhileBreak)16505 TEST_P(GLSLTestLoops, WhileBreak)
16506 {
16507 constexpr char kFS[] = R"(#version 300 es
16508 precision mediump float;
16509 out vec4 color;
16510
16511 void main()
16512 {
16513 int result = 0;
16514 int i = 0;
16515 while (i < 10)
16516 {
16517 int j = 0;
16518 while (true)
16519 {
16520 int k = 0;
16521 while (k < 2) { ++result; ++k; ++j; }
16522 while (k < 5) { ++result; ++k; }
16523 while (k < 4) { ++result; }
16524 ++j;
16525 if (j >= 8)
16526 break;
16527 }
16528 ++i;
16529 }
16530
16531 color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16532 })";
16533
16534 runTest(kFS);
16535 }
16536
16537 // Test while loops with continue at the end of block
TEST_P(GLSLTestLoops,WhileUnconditionalBreak)16538 TEST_P(GLSLTestLoops, WhileUnconditionalBreak)
16539 {
16540 constexpr char kFS[] = R"(#version 300 es
16541 precision mediump float;
16542 out vec4 color;
16543
16544 void main()
16545 {
16546 int result = 0;
16547 int i = 0;
16548 while (i < 10)
16549 {
16550 int j = 0;
16551 while (j < 8)
16552 {
16553 int k = 0;
16554 while (k < 2) { ++result; ++k; ++j; }
16555 while (k < 5) { ++result; ++k; }
16556 while (k < 4) { ++result; }
16557 ++j;
16558 break;
16559 }
16560 ++i;
16561 }
16562
16563 color = result == 50 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16564 })";
16565
16566 runTest(kFS);
16567 }
16568
16569 // Test basic do-while loops
TEST_P(GLSLTestLoops,BasicDoWhile)16570 TEST_P(GLSLTestLoops, BasicDoWhile)
16571 {
16572 constexpr char kFS[] = R"(#version 300 es
16573 precision mediump float;
16574 out vec4 color;
16575
16576 void main()
16577 {
16578 int result = 0;
16579 int i = 0;
16580 do
16581 {
16582 int j = 0;
16583 do
16584 {
16585 int k = 0;
16586 do { ++result; ++k; ++j; } while (k < 2);
16587 do { ++result; ++k; } while (k < 5);
16588 do { ++result; } while (k < 3);
16589 ++j;
16590 } while (j < 8);
16591 ++i;
16592 } while (i < 10);
16593
16594 color = result == 180 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16595 })";
16596
16597 runTest(kFS);
16598 }
16599
16600 // Test do-while loops with continue
TEST_P(GLSLTestLoops,DoWhileContinue)16601 TEST_P(GLSLTestLoops, DoWhileContinue)
16602 {
16603 constexpr char kFS[] = R"(#version 300 es
16604 precision mediump float;
16605 out vec4 color;
16606
16607 void main()
16608 {
16609 int result = 0;
16610 int i = 0;
16611 do
16612 {
16613 int j = 0;
16614 do
16615 {
16616 int k = 0;
16617 do { ++result; ++k; ++j; } while (k < 2);
16618 if (i > 3)
16619 {
16620 ++j;
16621 continue;
16622 }
16623 do { ++result; ++k; } while (k < 5);
16624 do { ++result; } while (k < 3);
16625 ++j;
16626 } while (j < 8);
16627 ++i;
16628 } while (i < 10);
16629
16630 color = result == 108 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16631 })";
16632
16633 runTest(kFS);
16634 }
16635
16636 // Test do-while loops with continue at the end of block
TEST_P(GLSLTestLoops,DoWhileUnconditionalContinue)16637 TEST_P(GLSLTestLoops, DoWhileUnconditionalContinue)
16638 {
16639 constexpr char kFS[] = R"(#version 300 es
16640 precision mediump float;
16641 out vec4 color;
16642
16643 void main()
16644 {
16645 int result = 0;
16646 int i = 0;
16647 do
16648 {
16649 int j = 0;
16650 do
16651 {
16652 int k = 0;
16653 do { ++result; ++k; ++j; continue; } while (k < 2);
16654 do { ++result; ++k; continue; } while (k < 5);
16655 do { ++result; continue; } while (k < 3);
16656 ++j;
16657 } while (j < 8);
16658 ++i;
16659 } while (i < 10);
16660
16661 color = result == 180 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16662 })";
16663
16664 runTest(kFS);
16665 }
16666
16667 // Test do-while loops with break
TEST_P(GLSLTestLoops,DoWhileBreak)16668 TEST_P(GLSLTestLoops, DoWhileBreak)
16669 {
16670 constexpr char kFS[] = R"(#version 300 es
16671 precision mediump float;
16672 out vec4 color;
16673
16674 void main()
16675 {
16676 int result = 0;
16677 int i = 0;
16678 do
16679 {
16680 int j = 0;
16681 do
16682 {
16683 int k = 0;
16684 do { ++result; ++k; ++j; } while (k < 2);
16685 do { ++result; ++k; } while (k < 5);
16686 do { ++result; } while (k < 3);
16687 ++j;
16688 if (j >= 8)
16689 break;
16690 } while (true);
16691 ++i;
16692 } while (i < 10);
16693
16694 color = result == 180 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16695 })";
16696
16697 runTest(kFS);
16698 }
16699
16700 // Test do-while loops with break at the end of block
TEST_P(GLSLTestLoops,DoWhileUnconditionalBreak)16701 TEST_P(GLSLTestLoops, DoWhileUnconditionalBreak)
16702 {
16703 constexpr char kFS[] = R"(#version 300 es
16704 precision mediump float;
16705 out vec4 color;
16706
16707 void main()
16708 {
16709 int result = 0;
16710 int i = 0;
16711 do
16712 {
16713 int j = 0;
16714 do
16715 {
16716 int k = 0;
16717 do { ++result; ++k; ++j; break; } while (k < 2);
16718 do { ++result; ++k; break; } while (k < 5);
16719 do { ++result; break; } while (k < 3);
16720 ++j;
16721 } while (j < 8);
16722 ++i;
16723 } while (i < 10);
16724
16725 color = result == 120 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16726 })";
16727
16728 runTest(kFS);
16729 }
16730
16731 // Test for loop with continue inside switch.
TEST_P(GLSLTestLoops,ForContinueInSwitch)16732 TEST_P(GLSLTestLoops, ForContinueInSwitch)
16733 {
16734 constexpr char kFS[] = R"(#version 300 es
16735 precision mediump float;
16736 out vec4 color;
16737
16738 void main()
16739 {
16740 int result = 0;
16741 for (int i = 0; i < 10; ++i)
16742 for (int j = 0; j < 8; ++j)
16743 {
16744 switch (j)
16745 {
16746 case 2:
16747 case 3:
16748 case 4:
16749 ++result;
16750 // fallthrough
16751 case 5:
16752 case 6:
16753 ++result;
16754 break;
16755 default:
16756 continue;
16757 }
16758 }
16759
16760 color = result == 80 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16761 })";
16762
16763 runTest(kFS);
16764 }
16765
16766 // Test while loop with continue inside switch
TEST_P(GLSLTestLoops,WhileContinueInSwitch)16767 TEST_P(GLSLTestLoops, WhileContinueInSwitch)
16768 {
16769 constexpr char kFS[] = R"(#version 300 es
16770 precision mediump float;
16771 out vec4 color;
16772
16773 void main()
16774 {
16775 int result = 0;
16776 int i = 0;
16777 while (i < 10)
16778 {
16779 int j = 0;
16780 while (j < 8)
16781 {
16782 switch (j)
16783 {
16784 case 2:
16785 default:
16786 case 3:
16787 case 4:
16788 ++j;
16789 ++result;
16790 continue;
16791 case 0:
16792 case 1:
16793 case 7:
16794 break;
16795 }
16796 ++j;
16797 }
16798 ++i;
16799 }
16800
16801 color = result == 50 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16802 })";
16803
16804 runTest(kFS);
16805 }
16806
16807 // Test do-while loops with continue in switch
TEST_P(GLSLTestLoops,DoWhileContinueInSwitch)16808 TEST_P(GLSLTestLoops, DoWhileContinueInSwitch)
16809 {
16810 constexpr char kFS[] = R"(#version 300 es
16811 precision mediump float;
16812 out vec4 color;
16813
16814 void main()
16815 {
16816 int result = 0;
16817 int i = 0;
16818 do
16819 {
16820 int j = 0;
16821 do
16822 {
16823 switch (j)
16824 {
16825 case 0:
16826 ++j;
16827 continue;
16828 default:
16829 case 2:
16830 case 3:
16831 case 4:
16832 ++j;
16833 ++result;
16834 if (j >= 2 && j <= 6)
16835 break;
16836 else
16837 continue;
16838 }
16839 ++result;
16840 } while (j < 8);
16841 ++i;
16842 } while (i < 10);
16843
16844 color = result == 120 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16845 })";
16846
16847 runTest(kFS);
16848 }
16849
16850 // Test prune-able loop with side effect in statements.
TEST_P(GLSLTestLoops,SideEffectsInPrunableFor)16851 TEST_P(GLSLTestLoops, SideEffectsInPrunableFor)
16852 {
16853 constexpr char kFS[] = R"(#version 300 es
16854 precision mediump float;
16855 out vec4 color;
16856
16857 void main()
16858 {
16859 int a = 4;
16860 float b = 0.;
16861 for (int c = a++; (b += float(c) / 8.) < 0.; b += 0.3)
16862 {
16863 if (2 == 0);
16864 }
16865 int c = a - 4;
16866
16867 // Expect c to be 1 and b to be 0.5
16868 color = c == 1 && abs(b - 0.5) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16869 })";
16870
16871 runTest(kFS);
16872 }
16873
16874 // Test that precision is retained for constants (which are constant folded). Adapted from a WebGL
16875 // test.
TEST_P(GLSLTest,ConstantFoldedConstantsRetainPrecision)16876 TEST_P(GLSLTest, ConstantFoldedConstantsRetainPrecision)
16877 {
16878 constexpr char kFS[] = R"(
16879 // It is assumed that uTest is set to 0. It's here to make the expression not constant.
16880 uniform mediump float uTest;
16881 void main() {
16882 // exact representation of 4096.5 requires 13 bits of relative precision.
16883 const highp float c = 4096.5;
16884 mediump float a = 0.0;
16885 // Below, addition should be evaluated at highp, since one of the operands has the highp qualifier.
16886 // Thus fract should also be evaluated at highp.
16887 // See OpenGL ES Shading Language spec section 4.5.2.
16888 // This should make the result 0.5, since highp provides at least 16 bits of relative precision.
16889 // (exceptions for operation precision are allowed for a small number of computationally
16890 // intensive built-in functions, but it is reasonable to think that fract is not one of those).
16891 // However, if fract() is incorrectly evaluated at minimum precision fulfilling mediump criteria,
16892 // or at IEEE half float precision, the result is 0.0.
16893 a = fract(c + uTest);
16894 // Multiply by 2.0 to make the color green.
16895 gl_FragColor = vec4(0.0, 2.0 * a, 0.0, 1.0);
16896 })";
16897
16898 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
16899
16900 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
16901 EXPECT_GL_NO_ERROR();
16902
16903 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
16904 }
16905
16906 // Test that vector and matrix scalarization does not affect rendering.
TEST_P(GLSLTest,VectorAndMatrixScalarizationDoesNotAffectRendering)16907 TEST_P(GLSLTest, VectorAndMatrixScalarizationDoesNotAffectRendering)
16908 {
16909 constexpr char kFS[] = R"(
16910 precision mediump float;
16911
16912 varying vec2 v_texCoord;
16913
16914 float a = 0.;
16915 #define A 0.
16916
16917 #define r(a) mat2( cos( a + vec4(0,-1.5708,1.5708,0) ) )
16918 vec2 c;
16919 #define f(U,a) ( c = (U) * r(a) , sin(10.*c.x) )
16920
16921 void main() {
16922 vec2 U = v_texCoord;
16923
16924 gl_FragColor = U.y > .5
16925 ? vec4( f(U,a) , f(U*4.,a) , 0,1.0) // top
16926 : vec4( f(U,A) , f(U*4.,A) , 0,1.0); // bottom
16927 }
16928
16929 )";
16930
16931 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), kFS);
16932 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
16933
16934 // Make sure we rendered something.
16935 EXPECT_PIXEL_NE(0, 0, 0, 0, 0, 0);
16936
16937 // Comapare one line in top half to one line in bottom half.
16938 int compareWidth = getWindowWidth();
16939 int compareHeight = getWindowHeight() / 4;
16940
16941 ASSERT_GE(compareWidth, 2);
16942 ASSERT_GE(compareHeight, 2);
16943
16944 GLubyte pixelValue[4];
16945 constexpr int tolerance = 12;
16946
16947 for (int x = 0; x < compareWidth; ++x)
16948 {
16949 glReadPixels(x, compareHeight, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixelValue);
16950 EXPECT_PIXEL_NEAR(x, getWindowHeight() - compareHeight, pixelValue[0], pixelValue[1],
16951 pixelValue[2], pixelValue[3], tolerance);
16952 }
16953 EXPECT_GL_NO_ERROR();
16954 }
16955
16956 // Tests initializing a shader IO block using the shader translator option.
TEST_P(GLSLTest_ES31_InitShaderVariables,InitIOBlock)16957 TEST_P(GLSLTest_ES31_InitShaderVariables, InitIOBlock)
16958 {
16959 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
16960
16961 const char kVS[] = R"(#version 310 es
16962 #extension GL_EXT_shader_io_blocks : require
16963 in vec4 position;
16964 out BlockType {
16965 vec4 blockMember;
16966 } BlockTypeOut;
16967
16968 void main()
16969 {
16970 gl_Position = position;
16971 })";
16972
16973 const char kFS[] = R"(#version 310 es
16974 #extension GL_EXT_shader_io_blocks : require
16975 precision mediump float;
16976 out vec4 colorOut;
16977 in BlockType {
16978 vec4 blockMember;
16979 } BlockTypeOut;
16980
16981 void main()
16982 {
16983 if (BlockTypeOut.blockMember == vec4(0)) {
16984 colorOut = vec4(0, 1, 0, 1);
16985 } else {
16986 colorOut = vec4(1, 0, 0, 1);
16987 }
16988 })";
16989
16990 ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
16991 drawQuad(testProgram, "position", 0.5f, 1.0f, true);
16992 ASSERT_GL_NO_ERROR();
16993 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
16994 }
16995
16996 // Tests initializing a nameless shader IO block using the shader translator option.
TEST_P(GLSLTest_ES31_InitShaderVariables,InitIOBlockNameless)16997 TEST_P(GLSLTest_ES31_InitShaderVariables, InitIOBlockNameless)
16998 {
16999 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
17000
17001 const char kVS[] = R"(#version 310 es
17002 #extension GL_EXT_shader_io_blocks : require
17003 in vec4 position;
17004 out BlockType {
17005 vec4 blockMember;
17006 };
17007
17008 void main()
17009 {
17010 gl_Position = position;
17011 })";
17012
17013 const char kFS[] = R"(#version 310 es
17014 #extension GL_EXT_shader_io_blocks : require
17015 precision mediump float;
17016 out vec4 colorOut;
17017 in BlockType {
17018 vec4 blockMember;
17019 };
17020
17021 void main()
17022 {
17023 if (blockMember == vec4(0)) {
17024 colorOut = vec4(0, 1, 0, 1);
17025 } else {
17026 colorOut = vec4(1, 0, 0, 1);
17027 }
17028 })";
17029
17030 ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
17031 drawQuad(testProgram, "position", 0.5f, 1.0f, true);
17032 ASSERT_GL_NO_ERROR();
17033 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
17034 }
17035
17036 // Tests initializing a shader IO block with an array using the shader translator option.
TEST_P(GLSLTest_ES31_InitShaderVariables,InitIOBlockWithArray)17037 TEST_P(GLSLTest_ES31_InitShaderVariables, InitIOBlockWithArray)
17038 {
17039 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
17040
17041 const char kVS[] = R"(#version 310 es
17042 #extension GL_EXT_shader_io_blocks : require
17043 in vec4 position;
17044 out BlockType {
17045 vec4 blockMember[2];
17046 } BlockTypeOut;
17047
17048 void main()
17049 {
17050 gl_Position = position;
17051 })";
17052
17053 const char kFS[] = R"(#version 310 es
17054 #extension GL_EXT_shader_io_blocks : require
17055 precision mediump float;
17056 out vec4 colorOut;
17057 in BlockType {
17058 vec4 blockMember[2];
17059 } BlockTypeOut;
17060
17061 void main()
17062 {
17063 if (BlockTypeOut.blockMember[0] == vec4(0) &&
17064 BlockTypeOut.blockMember[1] == vec4(0)) {
17065 colorOut = vec4(0, 1, 0, 1);
17066 } else {
17067 colorOut = vec4(1, 0, 0, 1);
17068 }
17069 })";
17070
17071 ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
17072 drawQuad(testProgram, "position", 0.5f, 1.0f, true);
17073 ASSERT_GL_NO_ERROR();
17074 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
17075 }
17076
17077 // Tests initializing a shader IO block array using the shader translator option.
TEST_P(GLSLTest_ES31_InitShaderVariables,InitIOBlockArray)17078 TEST_P(GLSLTest_ES31_InitShaderVariables, InitIOBlockArray)
17079 {
17080 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
17081
17082 const char kVS[] = R"(#version 310 es
17083 #extension GL_EXT_shader_io_blocks : require
17084 in vec4 position;
17085 out BlockType {
17086 vec4 blockMember;
17087 } BlockTypeOut[2];
17088
17089 void main()
17090 {
17091 gl_Position = position;
17092 })";
17093
17094 const char kFS[] = R"(#version 310 es
17095 #extension GL_EXT_shader_io_blocks : require
17096 precision mediump float;
17097 out vec4 colorOut;
17098 in BlockType {
17099 vec4 blockMember;
17100 } BlockTypeOut[2];
17101
17102 void main()
17103 {
17104 if (BlockTypeOut[0].blockMember == vec4(0) &&
17105 BlockTypeOut[1].blockMember == vec4(0)) {
17106 colorOut = vec4(0, 1, 0, 1);
17107 } else {
17108 colorOut = vec4(1, 0, 0, 1);
17109 }
17110 })";
17111
17112 ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
17113 drawQuad(testProgram, "position", 0.5f, 1.0f, true);
17114 ASSERT_GL_NO_ERROR();
17115 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
17116 }
17117
17118 // Tests initializing a shader IO block with a struct using the shader translator option.
TEST_P(GLSLTest_ES31_InitShaderVariables,InitIOBlockWithStruct)17119 TEST_P(GLSLTest_ES31_InitShaderVariables, InitIOBlockWithStruct)
17120 {
17121 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
17122
17123 const char kVS[] = R"(#version 310 es
17124 #extension GL_EXT_shader_io_blocks : require
17125 in vec4 position;
17126 struct s {
17127 float f;
17128 vec2 v;
17129 };
17130 out BlockType {
17131 s blockMember;
17132 } BlockTypeOut;
17133
17134 void main()
17135 {
17136 gl_Position = position;
17137 })";
17138
17139 const char kFS[] = R"(#version 310 es
17140 #extension GL_EXT_shader_io_blocks : require
17141 precision mediump float;
17142 out vec4 colorOut;
17143 struct s {
17144 float f;
17145 vec2 v;
17146 };
17147 in BlockType {
17148 s blockMember;
17149 } BlockTypeOut;
17150
17151 void main()
17152 {
17153 if (BlockTypeOut.blockMember.f == 0.0 &&
17154 BlockTypeOut.blockMember.v == vec2(0)) {
17155 colorOut = vec4(0, 1, 0, 1);
17156 } else {
17157 colorOut = vec4(1, 0, 0, 1);
17158 }
17159 })";
17160
17161 ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
17162 drawQuad(testProgram, "position", 0.5f, 1.0f, true);
17163 ASSERT_GL_NO_ERROR();
17164 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
17165 }
17166
17167 // Tests initializing an IO block with a complicated set of types, using the shader translator.
TEST_P(GLSLTest_ES31_InitShaderVariables,InitIOBlockWithComplexTypes)17168 TEST_P(GLSLTest_ES31_InitShaderVariables, InitIOBlockWithComplexTypes)
17169 {
17170 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
17171
17172 const char kVS[] = R"(#version 310 es
17173 #extension GL_EXT_shader_io_blocks : require
17174 in vec4 position;
17175 struct s {
17176 float f;
17177 vec2 v;
17178 };
17179 out BlockType {
17180 vec4 v;
17181 s s1;
17182 s s2[2];
17183 } BlockTypeOut;
17184
17185 void main()
17186 {
17187 gl_Position = position;
17188 })";
17189
17190 const char kFS[] = R"(#version 310 es
17191 #extension GL_EXT_shader_io_blocks : require
17192 precision mediump float;
17193 out vec4 colorOut;
17194 struct s {
17195 float f;
17196 vec2 v;
17197 };
17198 in BlockType {
17199 vec4 v;
17200 s s1;
17201 s s2[2];
17202 } BlockTypeOut;
17203
17204 void main()
17205 {
17206 s sz = s(0.0, vec2(0));
17207 if (BlockTypeOut.v == vec4(0) &&
17208 BlockTypeOut.s1 == sz &&
17209 BlockTypeOut.s2[0] == sz &&
17210 BlockTypeOut.s2[1] == sz) {
17211 colorOut = vec4(0, 1, 0, 1);
17212 } else {
17213 colorOut = vec4(1, 0, 0, 1);
17214 }
17215 })";
17216
17217 ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
17218 drawQuad(testProgram, "position", 0.5f, 1.0f, true);
17219 ASSERT_GL_NO_ERROR();
17220 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
17221 }
17222
17223 // Tests an unsuccessful re-link using glBindAttribLocation.
TEST_P(GLSLTest_ES3,UnsuccessfulRelinkWithBindAttribLocation)17224 TEST_P(GLSLTest_ES3, UnsuccessfulRelinkWithBindAttribLocation)
17225 {
17226 // Make a simple program.
17227 ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
17228
17229 // Install the executable.
17230 glUseProgram(testProgram);
17231
17232 // Re-link with a bad XFB varying and a bound attrib location.
17233 const char *tfVaryings = "gl_FragColor";
17234 glTransformFeedbackVaryings(testProgram, 1, &tfVaryings, GL_SEPARATE_ATTRIBS);
17235 glBindAttribLocation(testProgram, 8, essl1_shaders::PositionAttrib());
17236 glLinkProgram(testProgram);
17237 GLint linkStatus = 999;
17238 glGetProgramiv(testProgram, GL_LINK_STATUS, &linkStatus);
17239 ASSERT_GL_NO_ERROR();
17240 ASSERT_EQ(linkStatus, GL_FALSE);
17241
17242 // Under normal GL this is not an error.
17243 glDrawArrays(GL_TRIANGLES, 79, 16);
17244 EXPECT_GL_NO_ERROR();
17245 }
17246
17247 // Tests an unsuccessful re-link using glBindAttribLocation under WebGL.
TEST_P(WebGL2GLSLTest,UnsuccessfulRelinkWithBindAttribLocation)17248 TEST_P(WebGL2GLSLTest, UnsuccessfulRelinkWithBindAttribLocation)
17249 {
17250 // Make a simple program.
17251 ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
17252
17253 // Install the executable.
17254 glUseProgram(testProgram);
17255
17256 // Re-link with a bad XFB varying and a bound attrib location.
17257 const char *tfVaryings = "gl_FragColor";
17258 glTransformFeedbackVaryings(testProgram, 1, &tfVaryings, GL_SEPARATE_ATTRIBS);
17259 glBindAttribLocation(testProgram, 8, essl1_shaders::PositionAttrib());
17260 glLinkProgram(testProgram);
17261 GLint linkStatus = 999;
17262 glGetProgramiv(testProgram, GL_LINK_STATUS, &linkStatus);
17263 ASSERT_GL_NO_ERROR();
17264 ASSERT_EQ(linkStatus, GL_FALSE);
17265
17266 // Under WebGL this is an error.
17267 glDrawArrays(GL_TRIANGLES, 79, 16);
17268 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
17269 }
17270
17271 // Covers a HLSL compiler bug.
TEST_P(GLSLTest_ES3,ComplexCrossExpression)17272 TEST_P(GLSLTest_ES3, ComplexCrossExpression)
17273 {
17274 constexpr char kFS[] = R"(#version 300 es
17275 precision mediump float;
17276 vec3 a = vec3(0.0);
17277 out vec4 color;
17278 void main()
17279 {
17280 cross(max(vec3(0.0), reflect(dot(a, vec3(0.0)), 0.0)), vec3(0.0));
17281 })";
17282
17283 ANGLE_GL_PROGRAM(testProgram, essl3_shaders::vs::Simple(), kFS);
17284 drawQuad(testProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
17285 ASSERT_GL_NO_ERROR();
17286 }
17287
17288 // Regression test for a crash in SPIR-V output when faced with an array of struct constant.
TEST_P(GLSLTest_ES3,ArrayOfStructConstantBug)17289 TEST_P(GLSLTest_ES3, ArrayOfStructConstantBug)
17290 {
17291 constexpr char kFS[] = R"(#version 300 es
17292 struct S {
17293 int foo;
17294 };
17295 void main() {
17296 S a[3];
17297 a = S[3](S(0), S(1), S(2));
17298 })";
17299
17300 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
17301
17302 const char *sourceArray[1] = {kFS};
17303 GLint lengths[1] = {static_cast<GLint>(sizeof(kFS) - 1)};
17304 glShaderSource(shader, 1, sourceArray, lengths);
17305 glCompileShader(shader);
17306
17307 GLint compileResult;
17308 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
17309 EXPECT_NE(compileResult, 0);
17310 }
17311
17312 // Regression test for a bug in SPIR-V output where float+matrix was mishandled.
TEST_P(GLSLTest_ES3,FloatPlusMatrix)17313 TEST_P(GLSLTest_ES3, FloatPlusMatrix)
17314 {
17315 constexpr char kFS[] = R"(#version 300 es
17316
17317 precision mediump float;
17318
17319 layout(location=0) out vec4 color;
17320
17321 uniform float f;
17322
17323 void main()
17324 {
17325 mat3x2 m = f + mat3x2(0);
17326 color = vec4(m[0][0]);
17327 })";
17328
17329 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
17330
17331 const char *sourceArray[1] = {kFS};
17332 GLint lengths[1] = {static_cast<GLint>(sizeof(kFS) - 1)};
17333 glShaderSource(shader, 1, sourceArray, lengths);
17334 glCompileShader(shader);
17335
17336 GLint compileResult;
17337 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
17338 EXPECT_NE(compileResult, 0);
17339 }
17340
17341 // Regression test for a bug in SPIR-V output where a transformation creates float(constant) without
17342 // folding it into a TIntermConstantUnion. This transformation is clamping non-constant indices in
17343 // WebGL. The |false ? i : 5| as index caused the transformation to consider this a non-constant
17344 // index.
TEST_P(WebGL2GLSLTest,IndexClampConstantIndexBug)17345 TEST_P(WebGL2GLSLTest, IndexClampConstantIndexBug)
17346 {
17347 constexpr char kFS[] = R"(#version 300 es
17348 precision highp float;
17349
17350 layout(location=0) out float f;
17351
17352 uniform int i;
17353
17354 void main()
17355 {
17356 float data[10];
17357 f = data[false ? i : 5];
17358 })";
17359
17360 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
17361
17362 const char *sourceArray[1] = {kFS};
17363 GLint lengths[1] = {static_cast<GLint>(sizeof(kFS) - 1)};
17364 glShaderSource(shader, 1, sourceArray, lengths);
17365 glCompileShader(shader);
17366
17367 GLint compileResult;
17368 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
17369 EXPECT_NE(compileResult, 0);
17370 }
17371
17372 // Test robustness of out-of-bounds lod in texelFetch
TEST_P(WebGL2GLSLTest,TexelFetchLodOutOfBounds)17373 TEST_P(WebGL2GLSLTest, TexelFetchLodOutOfBounds)
17374 {
17375 constexpr char kVS[] = R"(#version 300 es
17376 in vec4 vertexPosition;
17377 void main() {
17378 gl_Position = vertexPosition;
17379 })";
17380
17381 constexpr char kFS[] = R"(#version 300 es
17382 precision highp float;
17383 uniform highp sampler2DArray textureArray;
17384 uniform int textureLod;
17385 out vec4 fragColor;
17386 void main() {
17387 fragColor = texelFetch(textureArray, ivec3(gl_FragCoord.xy, 0), textureLod);
17388 })";
17389
17390 ANGLE_GL_PROGRAM(program, kVS, kFS);
17391 glUseProgram(program);
17392 const GLint lodLoc = glGetUniformLocation(program, "textureLod");
17393 EXPECT_NE(lodLoc, -1);
17394 const GLint textureLoc = glGetUniformLocation(program, "textureArray");
17395 EXPECT_NE(textureLoc, -1);
17396
17397 const GLint attribLocation = glGetAttribLocation(program, "vertexPosition");
17398 GLBuffer buffer;
17399 glBindBuffer(GL_ARRAY_BUFFER, buffer);
17400 constexpr float vertices[12] = {
17401 -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1,
17402 };
17403 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
17404 glEnableVertexAttribArray(attribLocation);
17405 glVertexAttribPointer(attribLocation, 2, GL_FLOAT, false, 0, 0);
17406
17407 GLTexture texture;
17408 glBindTexture(GL_TEXTURE_2D_ARRAY, texture);
17409 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 5, GL_RGBA8, 16, 16, 3);
17410 glUniform1i(textureLoc, 0);
17411
17412 // Test LOD too large
17413 glUniform1i(lodLoc, 0x7FFF);
17414 glDrawArrays(GL_TRIANGLES, 0, 6);
17415
17416 // Test LOD negative
17417 glUniform1i(lodLoc, -1);
17418 glDrawArrays(GL_TRIANGLES, 0, 6);
17419 }
17420
17421 // Test that framebuffer fetch transforms gl_LastFragData in the presence of gl_FragCoord without
17422 // failing validation (adapted from a Chromium test, see anglebug.com/42265427)
TEST_P(GLSLTest,FramebufferFetchWithLastFragData)17423 TEST_P(GLSLTest, FramebufferFetchWithLastFragData)
17424 {
17425 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch"));
17426
17427 constexpr char kFS[] = R"(#version 100
17428
17429 #extension GL_EXT_shader_framebuffer_fetch : require
17430 varying mediump vec4 color;
17431 void main() {
17432 gl_FragColor = length(gl_FragCoord.xy) * gl_LastFragData[0];
17433 })";
17434
17435 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
17436
17437 const char *sourceArray[1] = {kFS};
17438 GLint lengths[1] = {static_cast<GLint>(sizeof(kFS) - 1)};
17439 glShaderSource(shader, 1, sourceArray, lengths);
17440 glCompileShader(shader);
17441
17442 GLint compileResult;
17443 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
17444 EXPECT_NE(compileResult, 0);
17445 }
17446
17447 // Test that loop body ending in a branch doesn't fail compilation
TEST_P(GLSLTest,LoopBodyEndingInBranch1)17448 TEST_P(GLSLTest, LoopBodyEndingInBranch1)
17449 {
17450 constexpr char kFS[] = R"(void main(){for(int a,i;;gl_FragCoord)continue;})";
17451
17452 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
17453
17454 const char *sourceArray[1] = {kFS};
17455 GLint lengths[1] = {static_cast<GLint>(sizeof(kFS) - 1)};
17456 glShaderSource(shader, 1, sourceArray, lengths);
17457 glCompileShader(shader);
17458
17459 GLint compileResult;
17460 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
17461 EXPECT_NE(compileResult, 0);
17462 }
17463
17464 // Test that loop body ending in a branch doesn't fail compilation
TEST_P(GLSLTest,LoopBodyEndingInBranch2)17465 TEST_P(GLSLTest, LoopBodyEndingInBranch2)
17466 {
17467 constexpr char kFS[] =
17468 R"(void main(){for(int a,i;bool(gl_FragCoord.x);gl_FragCoord){continue;}})";
17469
17470 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
17471
17472 const char *sourceArray[1] = {kFS};
17473 GLint lengths[1] = {static_cast<GLint>(sizeof(kFS) - 1)};
17474 glShaderSource(shader, 1, sourceArray, lengths);
17475 glCompileShader(shader);
17476
17477 GLint compileResult;
17478 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
17479 EXPECT_NE(compileResult, 0);
17480 }
17481
17482 // Test that loop body ending in a branch doesn't fail compilation
TEST_P(GLSLTest,LoopBodyEndingInBranch3)17483 TEST_P(GLSLTest, LoopBodyEndingInBranch3)
17484 {
17485 constexpr char kFS[] = R"(void main(){for(int a,i;;gl_FragCoord){{continue;}}})";
17486
17487 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
17488
17489 const char *sourceArray[1] = {kFS};
17490 GLint lengths[1] = {static_cast<GLint>(sizeof(kFS) - 1)};
17491 glShaderSource(shader, 1, sourceArray, lengths);
17492 glCompileShader(shader);
17493
17494 GLint compileResult;
17495 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
17496 EXPECT_NE(compileResult, 0);
17497 }
17498
17499 // Test that loop body ending in a branch doesn't fail compilation
TEST_P(GLSLTest,LoopBodyEndingInBranch4)17500 TEST_P(GLSLTest, LoopBodyEndingInBranch4)
17501 {
17502 constexpr char kFS[] = R"(void main(){for(int a,i;;gl_FragCoord){{continue;}{}{}{{}{}}}})";
17503
17504 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
17505
17506 const char *sourceArray[1] = {kFS};
17507 GLint lengths[1] = {static_cast<GLint>(sizeof(kFS) - 1)};
17508 glShaderSource(shader, 1, sourceArray, lengths);
17509 glCompileShader(shader);
17510
17511 GLint compileResult;
17512 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
17513 EXPECT_NE(compileResult, 0);
17514 }
17515
17516 // Test that loop body ending in a branch doesn't fail compilation
TEST_P(GLSLTest,LoopBodyEndingInBranch5)17517 TEST_P(GLSLTest, LoopBodyEndingInBranch5)
17518 {
17519 constexpr char kFS[] = R"(void main(){while(bool(gl_FragCoord.x)){{continue;{}}{}}})";
17520
17521 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
17522
17523 const char *sourceArray[1] = {kFS};
17524 GLint lengths[1] = {static_cast<GLint>(sizeof(kFS) - 1)};
17525 glShaderSource(shader, 1, sourceArray, lengths);
17526 glCompileShader(shader);
17527
17528 GLint compileResult;
17529 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
17530 EXPECT_NE(compileResult, 0);
17531 }
17532
17533 // Test that loop body ending in a branch doesn't fail compilation
TEST_P(GLSLTest,LoopBodyEndingInBranch6)17534 TEST_P(GLSLTest, LoopBodyEndingInBranch6)
17535 {
17536 constexpr char kFS[] = R"(void main(){do{{continue;{}}{}}while(bool(gl_FragCoord.x));})";
17537
17538 GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
17539
17540 const char *sourceArray[1] = {kFS};
17541 GLint lengths[1] = {static_cast<GLint>(sizeof(kFS) - 1)};
17542 glShaderSource(shader, 1, sourceArray, lengths);
17543 glCompileShader(shader);
17544
17545 GLint compileResult;
17546 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
17547 EXPECT_NE(compileResult, 0);
17548 }
17549
17550 // Test that aliasing function out parameters work. The GLSL spec says:
17551 //
17552 // > Because the function works with local copies of parameters, there are no issues regarding
17553 // > aliasing of variables within a function.
17554 //
17555 // In the test below, while the value of x is unknown after the function call, the result of the
17556 // function must deterministically be true.
TEST_P(GLSLTest,AliasingFunctionOutParams)17557 TEST_P(GLSLTest, AliasingFunctionOutParams)
17558 {
17559 constexpr char kFS[] = R"(precision highp float;
17560
17561 const vec4 colorGreen = vec4(0.,1.,0.,1.);
17562 const vec4 colorRed = vec4(1.,0.,0.,1.);
17563
17564 bool outParametersAreDistinct(out float x, out float y) {
17565 x = 1.0;
17566 y = 2.0;
17567 return x == 1.0 && y == 2.0;
17568 }
17569 void main() {
17570 float x = 0.0;
17571 gl_FragColor = outParametersAreDistinct(x, x) ? colorGreen : colorRed;
17572 }
17573 )";
17574
17575 ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), kFS);
17576 drawQuad(testProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
17577 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
17578 ASSERT_GL_NO_ERROR();
17579 }
17580
17581 // Test that aliasing function out parameters work even when multiple params are aliased.
TEST_P(GLSLTest,AliasingFunctionOutParamsMultiple)17582 TEST_P(GLSLTest, AliasingFunctionOutParamsMultiple)
17583 {
17584 constexpr char kFS[] = R"(precision highp float;
17585
17586 const vec4 colorGreen = vec4(0.,1.,0.,1.);
17587 const vec4 colorRed = vec4(1.,0.,0.,1.);
17588
17589 bool outParametersAreDistinct(out float x, out float y, out float z, out float a) {
17590 x = 1.0;
17591 y = 2.0;
17592 z = 3.0;
17593 a = 4.0;
17594 return x == 1.0 && y == 2.0 && z == 3.0 && a == 4.0;
17595 }
17596 void main() {
17597 float x = 0.0;
17598 float y = 0.0;
17599 gl_FragColor = outParametersAreDistinct(x, x, y, y) ? colorGreen : colorRed;
17600 }
17601 )";
17602
17603 ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), kFS);
17604 drawQuad(testProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
17605 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
17606 ASSERT_GL_NO_ERROR();
17607 }
17608
17609 // Test that aliasing function inout parameters work.
TEST_P(GLSLTest,AliasingFunctionInOutParams)17610 TEST_P(GLSLTest, AliasingFunctionInOutParams)
17611 {
17612 constexpr char kFS[] = R"(precision highp float;
17613
17614 const vec4 colorGreen = vec4(0.,1.,0.,1.);
17615 const vec4 colorRed = vec4(1.,0.,0.,1.);
17616
17617 bool inoutParametersAreDistinct(inout float x, inout float y) {
17618 x = 1.0;
17619 y = 2.0;
17620 return x == 1.0 && y == 2.0;
17621 }
17622 void main() {
17623 float x = 0.0;
17624 gl_FragColor = inoutParametersAreDistinct(x, x) ? colorGreen : colorRed;
17625 }
17626 )";
17627
17628 ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), kFS);
17629 drawQuad(testProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
17630 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
17631 ASSERT_GL_NO_ERROR();
17632 }
17633
17634 // Test coverage of some matrix/scalar ops which Metal translation was missing.
TEST_P(GLSLTest,MatrixScalarOps)17635 TEST_P(GLSLTest, MatrixScalarOps)
17636 {
17637 constexpr char kFS[] = R"(precision highp float;
17638 void main() {
17639 float scalar = 0.5;
17640 mat3 matrix = mat3(vec3(0.1), vec3(0.1), vec3(0.1));
17641
17642 mat3 m0 = scalar / matrix;
17643 mat3 m1 = scalar * matrix;
17644 mat3 m2 = scalar + matrix;
17645 mat3 m3 = scalar - matrix;
17646
17647 gl_FragColor = vec4(m0[0][0], m1[0][0], m2[0][0], m3[0][0]);
17648 }
17649 )";
17650
17651 ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), kFS);
17652 ASSERT_GL_NO_ERROR();
17653
17654 drawQuad(testProgram, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
17655 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 13, 153, 102), 1.0);
17656 ASSERT_GL_NO_ERROR();
17657 }
17658
17659 // Test coverage of some matrix ops which Metal translation was missing.
TEST_P(GLSLTest,MatrixNegate)17660 TEST_P(GLSLTest, MatrixNegate)
17661 {
17662 constexpr char kFS[] = R"(precision highp float;
17663 void main() {
17664 mat3 matrix = mat3(vec3(-0.1), vec3(-0.1), vec3(-0.1));
17665
17666 mat3 m0 = -matrix;
17667
17668 gl_FragColor = vec4(m0[0][0], 0, 0, 1);
17669 }
17670 )";
17671
17672 ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), kFS);
17673 ASSERT_GL_NO_ERROR();
17674
17675 drawQuad(testProgram, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
17676 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(26, 0, 0, 255), 1.0);
17677 ASSERT_GL_NO_ERROR();
17678 }
17679
17680 // Test coverage of the mix(float, float, bool) overload which was missing in Metal translation
TEST_P(GLSLTest_ES3,MixFloatFloatBool)17681 TEST_P(GLSLTest_ES3, MixFloatFloatBool)
17682 {
17683 constexpr char kFS[] = R"(#version 300 es
17684 precision highp float;
17685 out vec4 fragColor;
17686 void main() {
17687 vec4 testData = vec4(0.0, 1.0, 0.5, 0.25);
17688 float scalar = mix(testData.x, testData.y, testData.x < 0.5);
17689 vec2 vector = mix(testData.xy, testData.xw, bvec2(testData.x < 0.5, testData.y < 0.5));
17690 fragColor = vec4(scalar, vector.x, vector.y, 1);
17691 }
17692 )";
17693
17694 ANGLE_GL_PROGRAM(testProgram, essl3_shaders::vs::Simple(), kFS);
17695 ASSERT_GL_NO_ERROR();
17696
17697 drawQuad(testProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
17698 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(255, 0, 255, 255));
17699 ASSERT_GL_NO_ERROR();
17700 }
17701
17702 // Test coverage of the mix(uint, uint, bool) overload which was missing in D3D11 translation
TEST_P(GLSLTest_ES31,MixUintUintBool)17703 TEST_P(GLSLTest_ES31, MixUintUintBool)
17704 {
17705 constexpr char kFS[] = R"(#version 310 es
17706 precision highp float;
17707 out vec4 fragColor;
17708 void main() {
17709 uvec4 testData1 = uvec4(0, 1, 2, 3);
17710 uvec4 testData2 = uvec4(4, 5, 6, 7);
17711 uint scalar = mix(testData1.x, testData2.x, true);
17712 uvec4 vector = mix(testData1, testData2, bvec4(false, true, true, false));
17713 fragColor = vec4(scalar == 4u ? 1.0 : 0.0, vector == uvec4(0, 5, 6, 3) ? 1.0 : 0.0, 0.0, 1.0);
17714 }
17715 )";
17716
17717 ANGLE_GL_PROGRAM(testProgram, essl31_shaders::vs::Simple(), kFS);
17718 ASSERT_GL_NO_ERROR();
17719
17720 drawQuad(testProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
17721 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(255, 255, 0, 255));
17722 ASSERT_GL_NO_ERROR();
17723 }
17724
17725 // Test coverage of the mix(int, int, bool) overload which was missing in D3D11 translation
TEST_P(GLSLTest_ES31,MixIntIntBool)17726 TEST_P(GLSLTest_ES31, MixIntIntBool)
17727 {
17728 constexpr char kFS[] = R"(#version 310 es
17729 precision highp float;
17730 out vec4 fragColor;
17731 void main() {
17732 ivec4 testData1 = ivec4(-4, -3, -2, -1);
17733 ivec4 testData2 = ivec4(4, 5, 6, 7);
17734 int scalar = mix(testData1.x, testData2.x, true);
17735 ivec4 vector = mix(testData1, testData2, bvec4(false, true, true, false));
17736 fragColor = vec4(scalar == 4 ? 1.0 : 0.0, vector == ivec4(-4, 5, 6, -1) ? 1.0 : 0.0, 0.0, 1.0);
17737 }
17738 )";
17739
17740 ANGLE_GL_PROGRAM(testProgram, essl31_shaders::vs::Simple(), kFS);
17741 ASSERT_GL_NO_ERROR();
17742
17743 drawQuad(testProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
17744 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(255, 255, 0, 255));
17745 ASSERT_GL_NO_ERROR();
17746 }
17747
17748 // Test that aliasing function inout parameters work when more than one param is aliased.
TEST_P(GLSLTest,AliasingFunctionInOutParamsMultiple)17749 TEST_P(GLSLTest, AliasingFunctionInOutParamsMultiple)
17750 {
17751 constexpr char kFS[] = R"(precision highp float;
17752
17753 const vec4 colorGreen = vec4(0.,1.,0.,1.);
17754 const vec4 colorRed = vec4(1.,0.,0.,1.);
17755
17756 bool inoutParametersAreDistinct(inout float x, inout float y, inout float z, inout float a) {
17757 x = 1.0;
17758 y = 2.0;
17759 z = 3.0;
17760 a = 4.0;
17761 return x == 1.0 && y == 2.0 && z == 3.0 && a == 4.0;
17762 }
17763 void main() {
17764 float x = 0.0;
17765 float y = 0.0;
17766 gl_FragColor = inoutParametersAreDistinct(x, x, y, y) ? colorGreen : colorRed;
17767 }
17768 )";
17769
17770 ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), kFS);
17771 drawQuad(testProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
17772 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
17773 ASSERT_GL_NO_ERROR();
17774 }
17775
17776 // Test that aliasing function out parameter with a global works.
TEST_P(GLSLTest,AliasingFunctionOutParamAndGlobal)17777 TEST_P(GLSLTest, AliasingFunctionOutParamAndGlobal)
17778 {
17779 constexpr char kFS[] = R"(precision highp float;
17780
17781 const vec4 colorGreen = vec4(0.,1.,0.,1.);
17782 const vec4 colorRed = vec4(1.,0.,0.,1.);
17783
17784 float x = 1.0;
17785 bool outParametersAreDistinctFromGlobal(out float y) {
17786 y = 2.0;
17787 return x == 1.0 && y == 2.0;
17788 }
17789 void main() {
17790 gl_FragColor = outParametersAreDistinctFromGlobal(x) ? colorGreen : colorRed;
17791 }
17792 )";
17793
17794 ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), kFS);
17795 drawQuad(testProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
17796 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
17797 ASSERT_GL_NO_ERROR();
17798 }
17799
17800 // Make sure const sampler parameters work.
TEST_P(GLSLTest,ConstSamplerParameter)17801 TEST_P(GLSLTest, ConstSamplerParameter)
17802 {
17803 constexpr char kFS[] = R"(precision mediump float;
17804 uniform sampler2D samp;
17805
17806 vec4 sampleConstSampler(const sampler2D s) {
17807 return texture2D(s, vec2(0));
17808 }
17809
17810 void main() {
17811 gl_FragColor = sampleConstSampler(samp);
17812 }
17813 )";
17814 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
17815 glUseProgram(program);
17816 GLTexture texture;
17817 GLColor expected = MakeGLColor(32, 64, 96, 255);
17818 glBindTexture(GL_TEXTURE_2D, texture);
17819 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, expected.data());
17820 GLint u = glGetUniformLocation(program, "samp");
17821 EXPECT_NE(u, -1);
17822 glUniform1i(u, 0);
17823 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
17824 EXPECT_PIXEL_COLOR_EQ(0, 0, expected);
17825 ASSERT_GL_NO_ERROR();
17826 }
17827
17828 // Make sure const sampler parameters work.
TEST_P(GLSLTest,ConstInSamplerParameter)17829 TEST_P(GLSLTest, ConstInSamplerParameter)
17830 {
17831 constexpr char kFS[] = R"(precision mediump float;
17832 uniform sampler2D u;
17833 vec4 sampleConstSampler(const in sampler2D s) {
17834 return texture2D(s, vec2(0));
17835 }
17836 void main() {
17837 gl_FragColor = sampleConstSampler(u);
17838 }
17839 )";
17840 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
17841 glUseProgram(program);
17842 GLTexture texture;
17843 GLColor expected = MakeGLColor(32, 64, 96, 255);
17844 glBindTexture(GL_TEXTURE_2D, texture);
17845 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, expected.data());
17846 GLint u = glGetUniformLocation(program, "u");
17847 EXPECT_NE(u, -1);
17848 glUniform1i(u, 0);
17849 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
17850 EXPECT_PIXEL_COLOR_EQ(0, 0, expected);
17851 ASSERT_GL_NO_ERROR();
17852 }
17853
17854 // Make sure passing const sampler parameters to another function work.
TEST_P(GLSLTest,ConstSamplerParameterAsArgument)17855 TEST_P(GLSLTest, ConstSamplerParameterAsArgument)
17856 {
17857 constexpr char kFS[] = R"(precision mediump float;
17858
17859 uniform sampler2D samp;
17860
17861 vec4 sampleSampler(sampler2D s) {
17862 return texture2D(s, vec2(0));
17863 }
17864
17865 vec4 sampleConstSampler(const sampler2D s) {
17866 return sampleSampler(s);
17867 }
17868
17869 void main() {
17870 gl_FragColor = sampleConstSampler(samp);
17871 }
17872 )";
17873 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
17874 glUseProgram(program);
17875 GLTexture texture;
17876 GLColor expected = MakeGLColor(32, 64, 96, 255);
17877 glBindTexture(GL_TEXTURE_2D, texture);
17878 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, expected.data());
17879 GLint u = glGetUniformLocation(program, "samp");
17880 EXPECT_NE(u, -1);
17881 glUniform1i(u, 0);
17882 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
17883 EXPECT_PIXEL_COLOR_EQ(0, 0, expected);
17884 ASSERT_GL_NO_ERROR();
17885 }
17886
17887 // Test for a driver bug with matrix multiplication in the tessellation control shader.
TEST_P(GLSLTest_ES31,TessellationControlShaderMatrixMultiplicationBug)17888 TEST_P(GLSLTest_ES31, TessellationControlShaderMatrixMultiplicationBug)
17889 {
17890 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
17891
17892 constexpr char kTCS[] = R"(#version 310 es
17893 #extension GL_EXT_tessellation_shader : enable
17894 layout(vertices = 1) out;
17895 precision highp float;
17896
17897 patch out mat4 x;
17898
17899 void main()
17900 {
17901 x = mat4(
17902 0.53455, 0.47307, 0.34935, 0.28717,
17903 0.67195, 0.59992, 0.48213, 0.43678,
17904 0.76376, 0.6772, 0.55361, 0.5165,
17905 0.77996, 0.68862, 0.56187, 0.52611
17906 );
17907
17908 const mat4 m = mat4(
17909 vec4( -1.0, 3.0,-3.0, 1.0),
17910 vec4( 3.0,-6.0, 3.0, 0.0),
17911 vec4( -3.0, 3.0, 0.0, 0.0),
17912 vec4( 1.0, 0.0, 0.0, 0.0)
17913 );
17914
17915 x = m * x;
17916
17917 gl_TessLevelInner[0u] = 1.;
17918 gl_TessLevelInner[1u] = 1.;
17919 gl_TessLevelOuter[0u] = 1.;
17920 gl_TessLevelOuter[1u] = 1.;
17921 gl_TessLevelOuter[2u] = 1.;
17922 gl_TessLevelOuter[3u] = 1.;
17923 })";
17924
17925 constexpr char kTES[] = R"(#version 310 es
17926 #extension GL_EXT_tessellation_shader : enable
17927 layout(quads, cw, fractional_odd_spacing) in;
17928 precision highp float;
17929
17930 patch in mat4 x;
17931
17932 out mat4 x_fs;
17933
17934 void main()
17935 {
17936 x_fs = x;
17937 gl_Position = vec4(gl_TessCoord.xy * 2. - 1., 0, 1);
17938 })";
17939
17940 constexpr char kFS[] = R"(#version 310 es
17941 precision highp float;
17942
17943 in mat4 x_fs;
17944 out vec4 color;
17945
17946 void main()
17947 {
17948 // Note: on the failing driver, .w of every column has the same value as .x of the same column.
17949
17950 const mat4 expect = mat4(
17951 0.12378, -0.18672, -0.18444, 0.53455,
17952 0.1182, -0.13728, -0.21609, 0.67195,
17953 0.12351, -0.11109, -0.25968, 0.76376,
17954 0.1264, -0.10623, -0.27402, 0.77996
17955 );
17956
17957 color = vec4(all(lessThan(abs(x_fs[0] - expect[0]), vec4(0.01))),
17958 all(lessThan(abs(x_fs[1] - expect[1]), vec4(0.01))),
17959 all(lessThan(abs(x_fs[2] - expect[2]), vec4(0.01))),
17960 all(lessThan(abs(x_fs[3] - expect[3]), vec4(0.01))));
17961 })";
17962
17963 ANGLE_GL_PROGRAM_WITH_TESS(program, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
17964 drawPatches(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, GL_FALSE);
17965 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
17966 ASSERT_GL_NO_ERROR();
17967 }
17968
17969 // Test for a driver bug with matrix copy in the tessellation control shader.
TEST_P(GLSLTest_ES31,TessellationControlShaderMatrixCopyBug)17970 TEST_P(GLSLTest_ES31, TessellationControlShaderMatrixCopyBug)
17971 {
17972 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
17973
17974 constexpr char kTCS[] = R"(#version 310 es
17975 #extension GL_EXT_tessellation_shader : enable
17976 layout(vertices = 1) out;
17977 precision highp float;
17978
17979 patch out mat4 x;
17980 patch out vec4 col0;
17981
17982 void main()
17983 {
17984 // Note: if |x| is not an |out| varying, the test passes.
17985 x = mat4(
17986 0.53455, 0.47307, 0.34935, 0.28717,
17987 0.67195, 0.59992, 0.48213, 0.43678,
17988 0.76376, 0.6772, 0.55361, 0.5165,
17989 0.77996, 0.68862, 0.56187, 0.52611
17990 );
17991
17992 const mat4 m = mat4(
17993 vec4( -1.0, 3.0,-3.0, 1.0),
17994 vec4( 3.0,-6.0, 3.0, 0.0),
17995 vec4( -3.0, 3.0, 0.0, 0.0),
17996 vec4( 1.0, 0.0, 0.0, 0.0)
17997 );
17998
17999 mat4 temp = x;
18000
18001 // Note: On the failing driver, commenting this line makes the test pass.
18002 // However, the output being tested is |temp|, assigned above, not |x|.
18003 x = m * x;
18004
18005 col0 = temp[0];
18006
18007 gl_TessLevelInner[0u] = 1.;
18008 gl_TessLevelInner[1u] = 1.;
18009 gl_TessLevelOuter[0u] = 1.;
18010 gl_TessLevelOuter[1u] = 1.;
18011 gl_TessLevelOuter[2u] = 1.;
18012 gl_TessLevelOuter[3u] = 1.;
18013 })";
18014
18015 constexpr char kTES[] = R"(#version 310 es
18016 #extension GL_EXT_tessellation_shader : enable
18017 layout(quads, cw, fractional_odd_spacing) in;
18018 precision highp float;
18019
18020 patch in vec4 col0;
18021
18022 out vec4 col0_fs;
18023
18024 void main()
18025 {
18026 col0_fs = col0;
18027 gl_Position = vec4(gl_TessCoord.xy * 2. - 1., 0, 1);
18028 })";
18029
18030 constexpr char kFS[] = R"(#version 310 es
18031 precision highp float;
18032
18033 in vec4 col0_fs;
18034 out vec4 color;
18035
18036 void main()
18037 {
18038 // Note: on the failing driver, |col0| has the value of |m * x|, not |temp|.
18039 color = vec4(abs(col0_fs.x - 0.53455) < 0.01,
18040 abs(col0_fs.y - 0.47307) < 0.01,
18041 abs(col0_fs.z - 0.34935) < 0.01,
18042 abs(col0_fs.w - 0.28717) < 0.01);
18043 })";
18044
18045 ANGLE_GL_PROGRAM_WITH_TESS(program, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
18046 drawPatches(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, GL_FALSE);
18047 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
18048 ASSERT_GL_NO_ERROR();
18049 }
18050
18051 // Tests the generation of HLSL functions with uint/int parameters that may be ambiguous.
TEST_P(GLSLTest_ES3,AmbiguousHLSLIntegerFunctionParameters)18052 TEST_P(GLSLTest_ES3, AmbiguousHLSLIntegerFunctionParameters)
18053 {
18054 const char kVS[] = R"(#version 300 es
18055 precision highp float;
18056 void main()
18057 {
18058 gl_Position = vec4(0, 0, 0, 0);
18059 })";
18060
18061 const char kFS[] = R"(#version 300 es
18062 precision highp float;
18063 out vec4 color;
18064 void main()
18065 {
18066 // Ensure that both uint and int to float constructors are generated before the ambiguous usage.
18067 int i = int(gl_FragCoord.x);
18068 float f1 = float(i);
18069 color.r = f1;
18070
18071 uint ui = uint(gl_FragCoord.x);
18072 float f2 = float(i);
18073 color.g = f2;
18074
18075 // Ambiguous call
18076 float f3 = float(1u << (2u * ui));
18077 color.b = f3;
18078 })";
18079
18080 ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
18081 }
18082
18083 // Tests adding a struct definition inline in a shader.
18084 // Metal backend contains a pass that separates struct definition and declaration.
TEST_P(GLSLTest_ES3,StructInShader)18085 TEST_P(GLSLTest_ES3, StructInShader)
18086 {
18087 const char kVS[] = R"(#version 300 es
18088 precision highp float;
18089 void main(void)
18090 {
18091 struct structMain {
18092 float i;
18093 } testStruct;
18094
18095 testStruct.i = 5.0 ;
18096 gl_Position = vec4(testStruct.i - 4.0, 0, 0, 1);
18097 })";
18098
18099 const char kFS[] = R"(#version 300 es
18100 precision highp float;
18101 out vec4 color;
18102 void main()
18103 {
18104 color = vec4(0,1,0,0);
18105 })";
18106
18107 ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
18108 }
18109
18110 // Issue: A while loop's expression, and a branch
18111 // condition with EOpContinue were being deep
18112 // copied as part of monomorphize functions,
18113 // causing a crash, as they were not null-checked.
18114 // Tests transforming a function that will be monomorphized.
TEST_P(GLSLTest_ES3,MonomorphizeForAndContinue)18115 TEST_P(GLSLTest_ES3, MonomorphizeForAndContinue)
18116 {
18117
18118 constexpr char kFS[] =
18119 R"(#version 300 es
18120
18121 precision mediump float;
18122 out vec4 fragOut;
18123 struct aParam
18124 {
18125 sampler2D sampler;
18126 };
18127 uniform aParam theParam;
18128
18129 float monomorphizedFunction(aParam a)
18130 {
18131 int i = 0;
18132 vec4 j = vec4(0);
18133 for(;;)
18134 {
18135 if(i++ < 10)
18136 {
18137 j += texture(a.sampler, vec2(0.0f,0.0f));
18138 continue;
18139 }
18140 break;
18141 }
18142 return j.a;
18143 }
18144 void main()
18145 {
18146 fragOut.a = monomorphizedFunction(theParam);
18147 }
18148 )";
18149 CompileShader(GL_FRAGMENT_SHADER, kFS);
18150 ASSERT_GL_NO_ERROR();
18151 }
18152
18153 // Tests inout parameters with array references.
TEST_P(GLSLTest_ES3,InoutWithArrayRefs)18154 TEST_P(GLSLTest_ES3, InoutWithArrayRefs)
18155 {
18156 const char kVS[] = R"(#version 300 es
18157 precision highp float;
18158 void swap(inout float a, inout float b)
18159 {
18160 float tmp = a;
18161 a = b;
18162 b = tmp;
18163 }
18164
18165 void main(void)
18166 {
18167 vec3 testVec = vec3(0.0, 1.0, 1.0);
18168 swap(testVec[0], testVec[1]);
18169 gl_Position = vec4(testVec[0], testVec[1], testVec[2], 1.0);
18170 })";
18171
18172 const char kFS[] = R"(#version 300 es
18173 precision highp float;
18174 out vec4 color;
18175 void main()
18176 {
18177 color = vec4(0,1,0,0);
18178 })";
18179
18180 ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
18181 }
18182
18183 // Test that sample variables compile.
TEST_P(GLSLTest_ES3,SampleVariables)18184 TEST_P(GLSLTest_ES3, SampleVariables)
18185 {
18186 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_sample_variables"));
18187
18188 const char kFS[] = R"(#version 300 es
18189 #extension GL_OES_sample_variables : require
18190 precision highp float;
18191 out vec4 color;
18192 void main()
18193 {
18194 gl_SampleMask[0] = gl_SampleMaskIn[0] & 0x55555555;
18195 color = vec4(gl_SamplePosition.yx, float(gl_SampleID), float(gl_MaxSamples + gl_NumSamples));
18196 })";
18197
18198 ANGLE_GL_PROGRAM(testProgram, essl3_shaders::vs::Simple(), kFS);
18199 }
18200
18201 // Test that shader caching maintains uniforms across compute shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheComputeWithUniform)18202 TEST_P(GLSLTest_ES31, ShaderCacheComputeWithUniform)
18203 {
18204 ANGLE_SKIP_TEST_IF(!IsVulkan());
18205 constexpr char kCS[] = R"(#version 310 es
18206 layout (local_size_x = 2, local_size_y = 3, local_size_z = 1) in;
18207
18208 uniform uint inputs[6];
18209
18210 layout (binding = 0, std430) buffer OutputBuffer {
18211 uint outputs[6];
18212 };
18213
18214 void main() {
18215 outputs[gl_LocalInvocationIndex] = inputs[gl_LocalInvocationIndex];
18216 }
18217 )";
18218
18219 ANGLE_GL_COMPUTE_PROGRAM(unusedProgram, kCS);
18220 ASSERT_GL_NO_ERROR();
18221 // Delete the shader and recompile to fetch from cache.
18222 glDeleteProgram(unusedProgram);
18223 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
18224 ASSERT_GL_NO_ERROR();
18225 glUseProgram(program);
18226
18227 constexpr std::array<GLuint, 6> kInputUniform = {1, 2, 3, 4, 5, 6};
18228 for (int i = 0; i < static_cast<int>(kInputUniform.size()); ++i)
18229 {
18230 const std::string uniformName =
18231 std::string("inputs[") + std::to_string(i) + std::string("]");
18232 int inputLocation =
18233 glGetUniformLocation(program, static_cast<const GLchar *>(uniformName.c_str()));
18234 glUniform1ui(inputLocation, kInputUniform[i]);
18235 ASSERT_GL_NO_ERROR();
18236 }
18237
18238 constexpr std::array<GLuint, 6> kOutputInitData = {0, 0, 0, 0, 0, 0};
18239 GLBuffer outputBuffer;
18240 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
18241 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLuint) * kOutputInitData.size(),
18242 kOutputInitData.data(), GL_STATIC_READ);
18243 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, outputBuffer);
18244
18245 glDispatchCompute(1, 1, 1);
18246 glDeleteProgram(program);
18247 ASSERT_GL_NO_ERROR();
18248 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
18249
18250 auto outputData = static_cast<const GLuint *>(glMapBufferRange(
18251 GL_SHADER_STORAGE_BUFFER, 0, sizeof(GLuint) * kOutputInitData.size(), GL_MAP_READ_BIT));
18252 for (int i = 0; i < static_cast<int>(kInputUniform.size()); ++i)
18253 {
18254 EXPECT_EQ(kInputUniform[i], outputData[i]);
18255 }
18256 }
18257
18258 // Test that shader caching maintains uniform blocks across shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheComputeWithUniformBlocks)18259 TEST_P(GLSLTest_ES31, ShaderCacheComputeWithUniformBlocks)
18260 {
18261 ANGLE_SKIP_TEST_IF(!IsVulkan());
18262 constexpr char kCS[] = R"(#version 310 es
18263 layout (local_size_x = 2, local_size_y = 3, local_size_z = 1) in;
18264
18265 layout (std140) uniform Input1 {
18266 uint input1;
18267 };
18268
18269 layout (std140) uniform Input2 {
18270 uint input2;
18271 };
18272
18273 layout (binding = 0, std430) buffer OutputBuffer {
18274 uint outputs[6];
18275 };
18276
18277 void main() {
18278 if (gl_LocalInvocationIndex < uint(3))
18279 {
18280 outputs[gl_LocalInvocationIndex] = input1;
18281 }
18282 else
18283 {
18284 outputs[gl_LocalInvocationIndex] = input2;
18285 }
18286 }
18287 )";
18288
18289 ANGLE_GL_COMPUTE_PROGRAM(unusedProgram, kCS);
18290 ASSERT_GL_NO_ERROR();
18291 // Delete the shader and recompile to fetch from cache.
18292 glDeleteProgram(unusedProgram);
18293 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
18294 ASSERT_GL_NO_ERROR();
18295 glUseProgram(program);
18296
18297 constexpr GLuint kInput1Data = 1;
18298 GLBuffer input1;
18299 glBindBuffer(GL_UNIFORM_BUFFER, input1);
18300 glBufferData(GL_UNIFORM_BUFFER, sizeof(GLuint), &kInput1Data, GL_STATIC_COPY);
18301 const GLuint kInput1Index = glGetUniformBlockIndex(program, "Input1");
18302 glUniformBlockBinding(program, kInput1Index, 1);
18303 glBindBufferBase(GL_UNIFORM_BUFFER, 1, input1);
18304 glBindBuffer(GL_UNIFORM_BUFFER, 0);
18305 ASSERT_GL_NO_ERROR();
18306
18307 constexpr GLuint kInput2Data = 2;
18308 GLBuffer input2;
18309 glBindBuffer(GL_UNIFORM_BUFFER, input2);
18310 glBufferData(GL_UNIFORM_BUFFER, sizeof(GLuint), &kInput2Data, GL_STATIC_COPY);
18311 const GLuint kInput2Index = glGetUniformBlockIndex(program, "Input2");
18312 glUniformBlockBinding(program, kInput2Index, 2);
18313 glBindBufferBase(GL_UNIFORM_BUFFER, 2, input2);
18314 glBindBuffer(GL_UNIFORM_BUFFER, 0);
18315 ASSERT_GL_NO_ERROR();
18316
18317 constexpr std::array<GLuint, 6> kOutputInitData = {0, 0, 0, 0, 0, 0};
18318 GLBuffer outputBuffer;
18319 glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
18320 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLuint) * kOutputInitData.size(),
18321 kOutputInitData.data(), GL_STATIC_READ);
18322 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, outputBuffer);
18323 ASSERT_GL_NO_ERROR();
18324
18325 glDispatchCompute(1, 1, 1);
18326 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
18327 glDeleteProgram(program);
18328 ASSERT_GL_NO_ERROR();
18329
18330 auto outputData = static_cast<const GLuint *>(glMapBufferRange(
18331 GL_SHADER_STORAGE_BUFFER, 0, sizeof(GLuint) * kOutputInitData.size(), GL_MAP_READ_BIT));
18332 constexpr std::array<GLuint, 6> kWant = {kInput1Data, kInput1Data, kInput1Data,
18333 kInput2Data, kInput2Data, kInput2Data};
18334 for (int i = 0; i < static_cast<int>(kWant.size()); ++i)
18335 {
18336 EXPECT_EQ(kWant[i], outputData[i]);
18337 }
18338 }
18339
18340 // Test that shader caching maintains uniforms across vertex shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheVertexWithUniform)18341 TEST_P(GLSLTest_ES31, ShaderCacheVertexWithUniform)
18342 {
18343 ANGLE_SKIP_TEST_IF(!IsVulkan());
18344 constexpr char kVS[] = R"(#version 310 es
18345
18346 precision mediump float;
18347
18348 layout (location = 0) in vec4 a_position;
18349
18350 uniform float redInput;
18351
18352 out float redValue;
18353
18354 void main() {
18355 gl_Position = a_position;
18356 redValue = redInput;
18357 })";
18358
18359 constexpr char kFS[] = R"(#version 310 es
18360
18361 precision mediump float;
18362
18363 in float redValue;
18364
18365 out vec4 fragColor;
18366
18367 void main()
18368 {
18369 fragColor = vec4(redValue, 0., 0., 1.);
18370 })";
18371
18372 ANGLE_GL_PROGRAM(unusedProgram, kVS, kFS);
18373 ASSERT_GL_NO_ERROR();
18374 // Delete the shader and recompile to fetch from cache.
18375 glDeleteProgram(unusedProgram);
18376 ANGLE_GL_PROGRAM(program, kVS, kFS);
18377 ASSERT_GL_NO_ERROR();
18378 glUseProgram(program);
18379
18380 constexpr GLfloat kRedValue = 1.0f;
18381 int redInputLocation = glGetUniformLocation(program, "redInput");
18382 glUniform1f(redInputLocation, kRedValue);
18383 ASSERT_GL_NO_ERROR();
18384
18385 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18386 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18387 }
18388
18389 // Test that shader caching maintains uniform blocks across vertex shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheVertexWithUniformBlock)18390 TEST_P(GLSLTest_ES31, ShaderCacheVertexWithUniformBlock)
18391 {
18392 ANGLE_SKIP_TEST_IF(!IsVulkan());
18393 constexpr char kVS[] = R"(#version 310 es
18394
18395 precision mediump float;
18396
18397 layout (location = 0) in vec4 a_position;
18398
18399 layout (std140) uniform Input {
18400 float redInput;
18401 };
18402
18403 out float redValue;
18404
18405 void main() {
18406 gl_Position = a_position;
18407 redValue = redInput;
18408 })";
18409
18410 constexpr char kFS[] = R"(#version 310 es
18411
18412 precision mediump float;
18413
18414 in float redValue;
18415
18416 out vec4 fragColor;
18417
18418 void main()
18419 {
18420 fragColor = vec4(redValue, 0., 0., 1.);
18421 })";
18422
18423 ANGLE_GL_PROGRAM(unusedProgram, kVS, kFS);
18424 ASSERT_GL_NO_ERROR();
18425 // Delete the shader and recompile to fetch from cache.
18426 glDeleteProgram(unusedProgram);
18427 ANGLE_GL_PROGRAM(program, kVS, kFS);
18428 ASSERT_GL_NO_ERROR();
18429 glUseProgram(program);
18430
18431 constexpr GLfloat kInputData = 1.0f;
18432 GLBuffer input;
18433 glBindBuffer(GL_UNIFORM_BUFFER, input);
18434 glBufferData(GL_UNIFORM_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
18435 const GLuint kInputIndex = glGetUniformBlockIndex(program, "Input");
18436 glUniformBlockBinding(program, kInputIndex, 0);
18437 glBindBufferBase(GL_UNIFORM_BUFFER, 0, input);
18438 glBindBuffer(GL_UNIFORM_BUFFER, 0);
18439 ASSERT_GL_NO_ERROR();
18440
18441 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18442 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18443 }
18444
18445 // Test that shader caching maintains SSBOs across vertex shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheVertexWithSSBO)18446 TEST_P(GLSLTest_ES31, ShaderCacheVertexWithSSBO)
18447 {
18448 ANGLE_SKIP_TEST_IF(!IsVulkan());
18449
18450 // Check that GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS is at least 1.
18451 GLint maxVertexShaderStorageBlocks;
18452 glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &maxVertexShaderStorageBlocks);
18453 ANGLE_SKIP_TEST_IF(maxVertexShaderStorageBlocks == 0);
18454 constexpr char kVS[] = R"(#version 310 es
18455
18456 precision mediump float;
18457
18458 layout (location = 0) in vec4 a_position;
18459
18460 layout (binding = 0, std430) buffer Input {
18461 float redInput;
18462 };
18463
18464 out float redValue;
18465
18466 void main() {
18467 gl_Position = a_position;
18468 redValue = redInput;
18469 })";
18470
18471 constexpr char kFS[] = R"(#version 310 es
18472
18473 precision mediump float;
18474
18475 in float redValue;
18476
18477 out vec4 fragColor;
18478
18479 void main()
18480 {
18481 fragColor = vec4(redValue, 0., 0., 1.);
18482 })";
18483
18484 ANGLE_GL_PROGRAM(unusedProgram, kVS, kFS);
18485 ASSERT_GL_NO_ERROR();
18486 // Delete the shader and recompile to fetch from cache.
18487 glDeleteProgram(unusedProgram);
18488 ANGLE_GL_PROGRAM(program, kVS, kFS);
18489 ASSERT_GL_NO_ERROR();
18490 glUseProgram(program);
18491
18492 constexpr GLfloat kInputData = 1.0f;
18493 GLBuffer input;
18494 glBindBuffer(GL_SHADER_STORAGE_BUFFER, input);
18495 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
18496 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, input);
18497 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
18498 ASSERT_GL_NO_ERROR();
18499
18500 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18501 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18502 }
18503
18504 // Test that shader caching maintains uniforms across vertex shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheFragmentWithUniform)18505 TEST_P(GLSLTest_ES31, ShaderCacheFragmentWithUniform)
18506 {
18507 ANGLE_SKIP_TEST_IF(!IsVulkan());
18508 constexpr char kFS[] = R"(#version 310 es
18509
18510 precision mediump float;
18511
18512 uniform float redValue;
18513
18514 out vec4 fragColor;
18515
18516 void main()
18517 {
18518 fragColor = vec4(redValue, 0., 0., 1.);
18519 })";
18520
18521 ANGLE_GL_PROGRAM(unusedProgram, essl31_shaders::vs::Simple(), kFS);
18522 ASSERT_GL_NO_ERROR();
18523 // Delete the shader and recompile to fetch from cache.
18524 glDeleteProgram(unusedProgram);
18525 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
18526 ASSERT_GL_NO_ERROR();
18527 glUseProgram(program);
18528
18529 GLfloat redValue = 1.0f;
18530 int redInputLocation = glGetUniformLocation(program, "redValue");
18531 glUniform1f(redInputLocation, redValue);
18532 ASSERT_GL_NO_ERROR();
18533
18534 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18535 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18536 }
18537
18538 // Test that shader caching maintains uniform blocks across vertex shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheFragmentWithUniformBlock)18539 TEST_P(GLSLTest_ES31, ShaderCacheFragmentWithUniformBlock)
18540 {
18541 ANGLE_SKIP_TEST_IF(!IsVulkan());
18542 constexpr char kFS[] = R"(#version 310 es
18543
18544 precision mediump float;
18545
18546 layout (std140) uniform Input {
18547 float redValue;
18548 };
18549
18550 out vec4 fragColor;
18551
18552 void main()
18553 {
18554 fragColor = vec4(redValue, 0., 0., 1.);
18555 })";
18556
18557 ANGLE_GL_PROGRAM(unusedProgram, essl31_shaders::vs::Simple(), kFS);
18558 ASSERT_GL_NO_ERROR();
18559 // Delete the shader and recompile to fetch from cache.
18560 glDeleteProgram(unusedProgram);
18561 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
18562 ASSERT_GL_NO_ERROR();
18563 glUseProgram(program);
18564
18565 constexpr GLfloat kInputData = 1.0f;
18566 GLBuffer input;
18567 glBindBuffer(GL_UNIFORM_BUFFER, input);
18568 glBufferData(GL_UNIFORM_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
18569 const GLuint kInputIndex = glGetUniformBlockIndex(program, "Input");
18570 glUniformBlockBinding(program, kInputIndex, 0);
18571 glBindBufferBase(GL_UNIFORM_BUFFER, 0, input);
18572 glBindBuffer(GL_UNIFORM_BUFFER, 0);
18573 ASSERT_GL_NO_ERROR();
18574
18575 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18576 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18577 }
18578
18579 // Test that shader caching maintains SSBOs across vertex shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheFragmentWithSSBO)18580 TEST_P(GLSLTest_ES31, ShaderCacheFragmentWithSSBO)
18581 {
18582 ANGLE_SKIP_TEST_IF(!IsVulkan());
18583 constexpr char kFS[] = R"(#version 310 es
18584
18585 precision mediump float;
18586
18587 layout (binding = 0, std430) buffer Input {
18588 float redValue;
18589 };
18590
18591 out vec4 fragColor;
18592
18593 void main()
18594 {
18595 fragColor = vec4(redValue, 0., 0., 1.);
18596 })";
18597
18598 ANGLE_GL_PROGRAM(unusedProgram, essl31_shaders::vs::Simple(), kFS);
18599 ASSERT_GL_NO_ERROR();
18600 // Delete the shader and recompile to fetch from cache.
18601 glDeleteProgram(unusedProgram);
18602 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
18603 ASSERT_GL_NO_ERROR();
18604 glUseProgram(program);
18605
18606 constexpr GLfloat kInputData = 1.0f;
18607 GLBuffer input;
18608 glBindBuffer(GL_SHADER_STORAGE_BUFFER, input);
18609 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
18610 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, input);
18611 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
18612 ASSERT_GL_NO_ERROR();
18613
18614 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18615 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18616 }
18617
18618 // Test that shader caching maintains whether GL_ARB_sample_shading is enabled across shader
18619 // compilations.
TEST_P(GLSLTest_ES31,ShaderCacheFragmentWithARBSampleShading)18620 TEST_P(GLSLTest_ES31, ShaderCacheFragmentWithARBSampleShading)
18621 {
18622 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ARB_sample_shading"));
18623 ANGLE_SKIP_TEST_IF(!IsVulkan());
18624
18625 constexpr char kFS[] = R"(#version 310 es
18626 #extension GL_ARB_sample_shading : enable
18627
18628 precision mediump float;
18629
18630 out vec4 fragColor;
18631
18632 void main()
18633 {
18634 #ifdef GL_ARB_sample_shading
18635 fragColor = vec4(1., 0., 0., 1.);
18636 #else
18637 fragColor = vec4(0.);
18638 #endif
18639 })";
18640
18641 ANGLE_GL_PROGRAM(unusedProgram, essl31_shaders::vs::Simple(), kFS);
18642 ASSERT_GL_NO_ERROR();
18643 // Delete the shader and recompile to fetch from cache.
18644 glDeleteProgram(unusedProgram);
18645 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
18646 ASSERT_GL_NO_ERROR();
18647 glUseProgram(program);
18648
18649 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18650 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18651 }
18652
18653 // Test that shader caching maintains which advanced blending equations (provided by
18654 // GL_KHR_blend_equation_advanced) are used across shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheFragmentWithKHRAdvancedBlendEquations)18655 TEST_P(GLSLTest_ES31, ShaderCacheFragmentWithKHRAdvancedBlendEquations)
18656 {
18657 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_KHR_blend_equation_advanced"));
18658 ANGLE_SKIP_TEST_IF(!IsVulkan());
18659
18660 constexpr char kFS[] = R"(#version 310 es
18661 #extension GL_KHR_blend_equation_advanced : require
18662
18663 layout (blend_support_multiply) out;
18664
18665 precision mediump float;
18666
18667 out vec4 fragColor;
18668
18669 void main()
18670 {
18671 fragColor = vec4(1., 0., 0., 1.);
18672 })";
18673
18674 ANGLE_GL_PROGRAM(unusedProgram, essl31_shaders::vs::Simple(), kFS);
18675 ASSERT_GL_NO_ERROR();
18676 // Delete the shader and recompile to fetch from cache.
18677 glDeleteProgram(unusedProgram);
18678 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
18679 ASSERT_GL_NO_ERROR();
18680 glUseProgram(program);
18681
18682 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18683 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18684 }
18685
18686 // Test that shader caching maintains uniforms in geometry shaders across shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheGeometryWithUniform)18687 TEST_P(GLSLTest_ES31, ShaderCacheGeometryWithUniform)
18688 {
18689 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
18690 ANGLE_SKIP_TEST_IF(!IsVulkan());
18691
18692 constexpr char kGS[] = R"(#version 310 es
18693 #extension GL_EXT_geometry_shader : require
18694 precision mediump float;
18695
18696 layout (triangles) in;
18697 layout (triangle_strip, max_vertices = 3) out;
18698
18699 uniform float redInput;
18700
18701 out float redValue;
18702
18703 void main() {
18704 gl_Position = gl_in[0].gl_Position;
18705 redValue = redInput;
18706 EmitVertex();
18707
18708 gl_Position = gl_in[1].gl_Position;
18709 redValue = redInput;
18710 EmitVertex();
18711
18712 gl_Position = gl_in[2].gl_Position;
18713 redValue = redInput;
18714 EmitVertex();
18715
18716 EndPrimitive();
18717 }
18718 )";
18719
18720 constexpr char kFS[] = R"(#version 310 es
18721 precision mediump float;
18722
18723 out vec4 fragColor;
18724
18725 in float redValue;
18726
18727 void main()
18728 {
18729 fragColor = vec4(redValue, 0., 0., 1.);
18730 })";
18731
18732 ANGLE_GL_PROGRAM_WITH_GS(unusedProgram, essl31_shaders::vs::Simple(), kGS, kFS);
18733 ASSERT_GL_NO_ERROR();
18734 // Delete the shader and recompile to fetch from cache.
18735 glDeleteProgram(unusedProgram);
18736 ANGLE_GL_PROGRAM_WITH_GS(program, essl31_shaders::vs::Simple(), kGS, kFS);
18737 ASSERT_GL_NO_ERROR();
18738 glUseProgram(program);
18739
18740 constexpr GLfloat kRedValue = 1.0f;
18741 int redInputLocation = glGetUniformLocation(program, "redInput");
18742 glUniform1f(redInputLocation, kRedValue);
18743 ASSERT_GL_NO_ERROR();
18744
18745 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18746 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18747 }
18748
18749 // Test that shader caching maintains uniform blocks in geometry shaders across shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheGeometryWithUniformBlock)18750 TEST_P(GLSLTest_ES31, ShaderCacheGeometryWithUniformBlock)
18751 {
18752 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
18753 ANGLE_SKIP_TEST_IF(!IsVulkan());
18754
18755 constexpr char kGS[] = R"(#version 310 es
18756 #extension GL_EXT_geometry_shader : require
18757 precision mediump float;
18758
18759 layout (triangles) in;
18760 layout (triangle_strip, max_vertices = 3) out;
18761
18762 layout (std140) uniform Input {
18763 float redInput;
18764 };
18765
18766 out float redValue;
18767
18768 void main() {
18769 gl_Position = gl_in[0].gl_Position;
18770 redValue = redInput;
18771 EmitVertex();
18772
18773 gl_Position = gl_in[1].gl_Position;
18774 redValue = redInput;
18775 EmitVertex();
18776
18777 gl_Position = gl_in[2].gl_Position;
18778 redValue = redInput;
18779 EmitVertex();
18780
18781 EndPrimitive();
18782 }
18783 )";
18784
18785 constexpr char kFS[] = R"(#version 310 es
18786 precision mediump float;
18787
18788 out vec4 fragColor;
18789
18790 in float redValue;
18791
18792 void main()
18793 {
18794 fragColor = vec4(redValue, 0., 0., 1.);
18795 })";
18796
18797 ANGLE_GL_PROGRAM_WITH_GS(unusedProgram, essl31_shaders::vs::Simple(), kGS, kFS);
18798 ASSERT_GL_NO_ERROR();
18799 // Delete the shader and recompile to fetch from cache.
18800 glDeleteProgram(unusedProgram);
18801 ANGLE_GL_PROGRAM_WITH_GS(program, essl31_shaders::vs::Simple(), kGS, kFS);
18802 ASSERT_GL_NO_ERROR();
18803 glUseProgram(program);
18804
18805 constexpr GLfloat kInputData = 1.0f;
18806 GLBuffer input;
18807 glBindBuffer(GL_UNIFORM_BUFFER, input);
18808 glBufferData(GL_UNIFORM_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
18809 const GLuint kInputIndex = glGetUniformBlockIndex(program, "Input");
18810 glUniformBlockBinding(program, kInputIndex, 0);
18811 glBindBufferBase(GL_UNIFORM_BUFFER, 0, input);
18812 glBindBuffer(GL_UNIFORM_BUFFER, 0);
18813 ASSERT_GL_NO_ERROR();
18814
18815 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18816 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18817 }
18818
18819 // Test that shader caching maintains SSBO in geometry shaders across shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheGeometryWithSSBO)18820 TEST_P(GLSLTest_ES31, ShaderCacheGeometryWithSSBO)
18821 {
18822 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
18823 ANGLE_SKIP_TEST_IF(!IsVulkan());
18824 GLint maxGeometryShaderStorageBlocks = 0;
18825 glGetIntegerv(GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT, &maxGeometryShaderStorageBlocks);
18826 ANGLE_SKIP_TEST_IF(maxGeometryShaderStorageBlocks == 0);
18827
18828 constexpr char kGS[] = R"(#version 310 es
18829 #extension GL_EXT_geometry_shader : require
18830 precision mediump float;
18831
18832 layout (triangles) in;
18833 layout (triangle_strip, max_vertices = 3) out;
18834
18835 layout (binding = 0, std430) buffer Input {
18836 float redInput;
18837 };
18838
18839 out float redValue;
18840
18841 void main() {
18842 gl_Position = gl_in[0].gl_Position;
18843 redValue = redInput;
18844 EmitVertex();
18845
18846 gl_Position = gl_in[1].gl_Position;
18847 redValue = redInput;
18848 EmitVertex();
18849
18850 gl_Position = gl_in[2].gl_Position;
18851 redValue = redInput;
18852 EmitVertex();
18853
18854 EndPrimitive();
18855 }
18856 )";
18857
18858 constexpr char kFS[] = R"(#version 310 es
18859 precision mediump float;
18860
18861 out vec4 fragColor;
18862
18863 in float redValue;
18864
18865 void main()
18866 {
18867 fragColor = vec4(redValue, 0., 0., 1.);
18868 })";
18869
18870 ANGLE_GL_PROGRAM_WITH_GS(unusedProgram, essl31_shaders::vs::Simple(), kGS, kFS);
18871 ASSERT_GL_NO_ERROR();
18872 // Delete the shader and recompile to fetch from cache.
18873 glDeleteProgram(unusedProgram);
18874 ANGLE_GL_PROGRAM_WITH_GS(program, essl31_shaders::vs::Simple(), kGS, kFS);
18875 ASSERT_GL_NO_ERROR();
18876 glUseProgram(program);
18877
18878 constexpr GLfloat kInputData = 1.0f;
18879 GLBuffer input;
18880 glBindBuffer(GL_SHADER_STORAGE_BUFFER, input);
18881 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
18882 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, input);
18883 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
18884 ASSERT_GL_NO_ERROR();
18885
18886 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18887 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18888 }
18889
18890 // Test that shader caching maintains the number of invocations in geometry shaders across shader
18891 // compilations.
TEST_P(GLSLTest_ES31,ShaderCacheGeometryWithInvocations)18892 TEST_P(GLSLTest_ES31, ShaderCacheGeometryWithInvocations)
18893 {
18894 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
18895 ANGLE_SKIP_TEST_IF(!IsVulkan());
18896
18897 constexpr char kGS[] = R"(#version 310 es
18898 #extension GL_EXT_geometry_shader : require
18899 precision mediump float;
18900
18901 layout (triangles, invocations = 2) in;
18902 layout (triangle_strip, max_vertices = 3) out;
18903
18904 out float redValue;
18905
18906 void main() {
18907 float redOut = 0.;
18908 if (gl_InvocationID == 1) {
18909 redOut = 1.;
18910 }
18911
18912 gl_Position = gl_in[0].gl_Position;
18913 redValue = redOut;
18914 EmitVertex();
18915
18916 gl_Position = gl_in[1].gl_Position;
18917 redValue = redOut;
18918 EmitVertex();
18919
18920 gl_Position = gl_in[2].gl_Position;
18921 redValue = redOut;
18922 EmitVertex();
18923
18924 EndPrimitive();
18925 }
18926 )";
18927
18928 constexpr char kFS[] = R"(#version 310 es
18929 precision mediump float;
18930
18931 out vec4 fragColor;
18932
18933 in float redValue;
18934
18935 void main()
18936 {
18937 fragColor = vec4(redValue, 0., 0., 1.);
18938 })";
18939
18940 ANGLE_GL_PROGRAM_WITH_GS(unusedProgram, essl31_shaders::vs::Simple(), kGS, kFS);
18941 ASSERT_GL_NO_ERROR();
18942 // Delete the shader and recompile to fetch from cache.
18943 glDeleteProgram(unusedProgram);
18944 ANGLE_GL_PROGRAM_WITH_GS(program, essl31_shaders::vs::Simple(), kGS, kFS);
18945 ASSERT_GL_NO_ERROR();
18946 glUseProgram(program);
18947
18948 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18949 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18950 }
18951
18952 // Test that shader caching maintains uniforms in tessellation control shaders across shader
18953 // compilations.
TEST_P(GLSLTest_ES31,ShaderCacheTessellationControlWithUniform)18954 TEST_P(GLSLTest_ES31, ShaderCacheTessellationControlWithUniform)
18955 {
18956 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
18957 ANGLE_SKIP_TEST_IF(!IsVulkan());
18958
18959 constexpr char kTCS[] = R"(#version 310 es
18960 #extension GL_EXT_tessellation_shader : require
18961 precision mediump float;
18962
18963 layout (vertices = 1) out;
18964
18965 uniform float redInput;
18966
18967 patch out float redValueCS;
18968
18969 void main()
18970 {
18971 gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
18972 gl_TessLevelInner[0] = 1.0;
18973 gl_TessLevelInner[1] = 1.0;
18974 gl_TessLevelOuter[0] = 1.0;
18975 gl_TessLevelOuter[1] = 1.0;
18976 gl_TessLevelOuter[2] = 1.0;
18977 gl_TessLevelOuter[3] = 1.0;
18978
18979 redValueCS = redInput;
18980 }
18981
18982 )";
18983
18984 constexpr char kTES[] = R"(#version 310 es
18985 #extension GL_EXT_tessellation_shader : require
18986 precision mediump float;
18987
18988 layout (quads, cw, fractional_odd_spacing) in;
18989
18990 patch in float redValueCS;
18991
18992 out float redValue;
18993
18994 void main()
18995 {
18996 gl_Position = vec4(gl_TessCoord.xy * 2. - 1., 0, 1);
18997
18998 redValue = redValueCS;
18999 }
19000 )";
19001
19002 constexpr char kFS[] = R"(#version 310 es
19003 precision mediump float;
19004
19005 out vec4 fragColor;
19006
19007 in float redValue;
19008
19009 void main()
19010 {
19011 fragColor = vec4(redValue, 0., 0., 1.);
19012 })";
19013
19014 ANGLE_GL_PROGRAM_WITH_TESS(unusedProgram, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
19015 ASSERT_GL_NO_ERROR();
19016 // Delete the shader and recompile to fetch from cache.
19017 glDeleteProgram(unusedProgram);
19018 ANGLE_GL_PROGRAM_WITH_TESS(program, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
19019 ASSERT_GL_NO_ERROR();
19020 glUseProgram(program);
19021
19022 constexpr GLfloat kRedValue = 1.0f;
19023 int redInputLocation = glGetUniformLocation(program, "redInput");
19024 glUniform1f(redInputLocation, kRedValue);
19025 ASSERT_GL_NO_ERROR();
19026
19027 drawPatches(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, GL_FALSE);
19028 ASSERT_GL_NO_ERROR();
19029
19030 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
19031 }
19032
19033 // Test that shader caching maintains uniform blocks in tessellation control shaders across shader
19034 // compilations.
TEST_P(GLSLTest_ES31,ShaderCacheTessellationControlWithUniformBlock)19035 TEST_P(GLSLTest_ES31, ShaderCacheTessellationControlWithUniformBlock)
19036 {
19037 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
19038 ANGLE_SKIP_TEST_IF(!IsVulkan());
19039
19040 constexpr char kTCS[] = R"(#version 310 es
19041 #extension GL_EXT_tessellation_shader : require
19042 precision mediump float;
19043
19044 layout (vertices = 1) out;
19045
19046 layout (std140) uniform Input {
19047 float redInput;
19048 };
19049
19050 patch out float redValueCS;
19051
19052 void main()
19053 {
19054 gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
19055 gl_TessLevelInner[0] = 1.0;
19056 gl_TessLevelInner[1] = 1.0;
19057 gl_TessLevelOuter[0] = 1.0;
19058 gl_TessLevelOuter[1] = 1.0;
19059 gl_TessLevelOuter[2] = 1.0;
19060 gl_TessLevelOuter[3] = 1.0;
19061
19062 redValueCS = redInput;
19063 }
19064
19065 )";
19066
19067 constexpr char kTES[] = R"(#version 310 es
19068 #extension GL_EXT_tessellation_shader : require
19069 precision mediump float;
19070
19071 layout (quads, cw, fractional_odd_spacing) in;
19072
19073 patch in float redValueCS;
19074
19075 out float redValue;
19076
19077 void main()
19078 {
19079 gl_Position = vec4(gl_TessCoord.xy * 2. - 1., 0, 1);
19080
19081 redValue = redValueCS;
19082 }
19083 )";
19084
19085 constexpr char kFS[] = R"(#version 310 es
19086 precision mediump float;
19087
19088 out vec4 fragColor;
19089
19090 in float redValue;
19091
19092 void main()
19093 {
19094 fragColor = vec4(redValue, 0., 0., 1.);
19095 })";
19096
19097 ANGLE_GL_PROGRAM_WITH_TESS(unusedProgram, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
19098 ASSERT_GL_NO_ERROR();
19099 // Delete the shader and recompile to fetch from cache.
19100 glDeleteProgram(unusedProgram);
19101 ANGLE_GL_PROGRAM_WITH_TESS(program, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
19102 ASSERT_GL_NO_ERROR();
19103 glUseProgram(program);
19104
19105 constexpr GLfloat kInputData = 1.0f;
19106 GLBuffer input;
19107 glBindBuffer(GL_UNIFORM_BUFFER, input);
19108 glBufferData(GL_UNIFORM_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
19109 const GLuint kInputIndex = glGetUniformBlockIndex(program, "Input");
19110 glUniformBlockBinding(program, kInputIndex, 0);
19111 glBindBufferBase(GL_UNIFORM_BUFFER, 0, input);
19112 glBindBuffer(GL_UNIFORM_BUFFER, 0);
19113 ASSERT_GL_NO_ERROR();
19114
19115 drawPatches(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, GL_FALSE);
19116 ASSERT_GL_NO_ERROR();
19117
19118 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
19119 }
19120
19121 // Test that shader caching maintains SSBOs in tessellation control shaders across shader
19122 // compilations.
TEST_P(GLSLTest_ES31,ShaderCacheTessellationControlWithSSBO)19123 TEST_P(GLSLTest_ES31, ShaderCacheTessellationControlWithSSBO)
19124 {
19125 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
19126 ANGLE_SKIP_TEST_IF(!IsVulkan());
19127 GLint maxTessControlShaderStorageBlocks;
19128 glGetIntegerv(GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS_EXT,
19129 &maxTessControlShaderStorageBlocks);
19130 ANGLE_SKIP_TEST_IF(maxTessControlShaderStorageBlocks == 0);
19131
19132 constexpr char kTCS[] = R"(#version 310 es
19133 #extension GL_EXT_tessellation_shader : require
19134 precision mediump float;
19135
19136 layout (vertices = 1) out;
19137
19138 layout (binding = 0, std430) buffer Input {
19139 float redInput;
19140 };
19141
19142 patch out float redValueCS;
19143
19144 void main()
19145 {
19146 gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
19147 gl_TessLevelInner[0] = 1.0;
19148 gl_TessLevelInner[1] = 1.0;
19149 gl_TessLevelOuter[0] = 1.0;
19150 gl_TessLevelOuter[1] = 1.0;
19151 gl_TessLevelOuter[2] = 1.0;
19152 gl_TessLevelOuter[3] = 1.0;
19153
19154 redValueCS = redInput;
19155 }
19156
19157 )";
19158
19159 constexpr char kTES[] = R"(#version 310 es
19160 #extension GL_EXT_tessellation_shader : require
19161 precision mediump float;
19162
19163 layout (quads, cw, fractional_odd_spacing) in;
19164
19165 patch in float redValueCS;
19166
19167 out float redValue;
19168
19169 void main()
19170 {
19171 gl_Position = vec4(gl_TessCoord.xy * 2. - 1., 0, 1);
19172
19173 redValue = redValueCS;
19174 }
19175 )";
19176
19177 constexpr char kFS[] = R"(#version 310 es
19178 precision mediump float;
19179
19180 out vec4 fragColor;
19181
19182 in float redValue;
19183
19184 void main()
19185 {
19186 fragColor = vec4(redValue, 0., 0., 1.);
19187 })";
19188
19189 ANGLE_GL_PROGRAM_WITH_TESS(unusedProgram, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
19190 ASSERT_GL_NO_ERROR();
19191 // Delete the shader and recompile to fetch from cache.
19192 glDeleteProgram(unusedProgram);
19193 ANGLE_GL_PROGRAM_WITH_TESS(program, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
19194 ASSERT_GL_NO_ERROR();
19195 glUseProgram(program);
19196
19197 constexpr GLfloat kInputData = 1.0f;
19198 GLBuffer input;
19199 glBindBuffer(GL_SHADER_STORAGE_BUFFER, input);
19200 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
19201 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, input);
19202 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
19203 ASSERT_GL_NO_ERROR();
19204
19205 drawPatches(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, GL_FALSE);
19206 ASSERT_GL_NO_ERROR();
19207
19208 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
19209 }
19210
19211 // Test that shader caching maintains uniforms in tessellation evaluation shaders across shader
19212 // compilations.
TEST_P(GLSLTest_ES31,ShaderCacheTessellationEvalWithUniform)19213 TEST_P(GLSLTest_ES31, ShaderCacheTessellationEvalWithUniform)
19214 {
19215 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
19216 ANGLE_SKIP_TEST_IF(!IsVulkan());
19217
19218 constexpr char kTCS[] = R"(#version 310 es
19219 #extension GL_EXT_tessellation_shader : require
19220 precision mediump float;
19221
19222 layout (vertices = 1) out;
19223
19224 void main()
19225 {
19226 gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
19227 gl_TessLevelInner[0] = 1.0;
19228 gl_TessLevelInner[1] = 1.0;
19229 gl_TessLevelOuter[0] = 1.0;
19230 gl_TessLevelOuter[1] = 1.0;
19231 gl_TessLevelOuter[2] = 1.0;
19232 gl_TessLevelOuter[3] = 1.0;
19233 }
19234
19235 )";
19236
19237 constexpr char kTES[] = R"(#version 310 es
19238 #extension GL_EXT_tessellation_shader : require
19239 precision mediump float;
19240
19241 layout (quads, cw, fractional_odd_spacing) in;
19242
19243 uniform float redInput;
19244
19245 out float redValue;
19246
19247 void main()
19248 {
19249 gl_Position = vec4(gl_TessCoord.xy * 2. - 1., 0, 1);
19250
19251 redValue = redInput;
19252 }
19253 )";
19254
19255 constexpr char kFS[] = R"(#version 310 es
19256 precision mediump float;
19257
19258 out vec4 fragColor;
19259
19260 in float redValue;
19261
19262 void main()
19263 {
19264 fragColor = vec4(redValue, 0., 0., 1.);
19265 })";
19266
19267 ANGLE_GL_PROGRAM_WITH_TESS(unusedProgram, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
19268 ASSERT_GL_NO_ERROR();
19269 // Delete the shader and recompile to fetch from cache.
19270 glDeleteProgram(unusedProgram);
19271 ANGLE_GL_PROGRAM_WITH_TESS(program, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
19272 ASSERT_GL_NO_ERROR();
19273 glUseProgram(program);
19274
19275 constexpr GLfloat kRedValue = 1.0f;
19276 int redInputLocation = glGetUniformLocation(program, "redInput");
19277 glUniform1f(redInputLocation, kRedValue);
19278 ASSERT_GL_NO_ERROR();
19279
19280 drawPatches(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, GL_FALSE);
19281 ASSERT_GL_NO_ERROR();
19282
19283 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
19284 }
19285
19286 // Test that shader caching maintains uniform blocks in tessellation evaluation shaders across
19287 // shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheTessellationEvalWithUniformBlock)19288 TEST_P(GLSLTest_ES31, ShaderCacheTessellationEvalWithUniformBlock)
19289 {
19290 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
19291 ANGLE_SKIP_TEST_IF(!IsVulkan());
19292
19293 constexpr char kTCS[] = R"(#version 310 es
19294 #extension GL_EXT_tessellation_shader : require
19295 precision mediump float;
19296
19297 layout (vertices = 1) out;
19298
19299 void main()
19300 {
19301 gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
19302 gl_TessLevelInner[0] = 1.0;
19303 gl_TessLevelInner[1] = 1.0;
19304 gl_TessLevelOuter[0] = 1.0;
19305 gl_TessLevelOuter[1] = 1.0;
19306 gl_TessLevelOuter[2] = 1.0;
19307 gl_TessLevelOuter[3] = 1.0;
19308 }
19309
19310 )";
19311
19312 constexpr char kTES[] = R"(#version 310 es
19313 #extension GL_EXT_tessellation_shader : require
19314 precision mediump float;
19315
19316 layout (quads, cw, fractional_odd_spacing) in;
19317
19318 layout (std140) uniform Input {
19319 float redInput;
19320 };
19321
19322 out float redValue;
19323
19324 void main()
19325 {
19326 gl_Position = vec4(gl_TessCoord.xy * 2. - 1., 0, 1);
19327
19328 redValue = redInput;
19329 }
19330 )";
19331
19332 constexpr char kFS[] = R"(#version 310 es
19333 precision mediump float;
19334
19335 out vec4 fragColor;
19336
19337 in float redValue;
19338
19339 void main()
19340 {
19341 fragColor = vec4(redValue, 0., 0., 1.);
19342 })";
19343
19344 ANGLE_GL_PROGRAM_WITH_TESS(unusedProgram, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
19345 ASSERT_GL_NO_ERROR();
19346 // Delete the shader and recompile to fetch from cache.
19347 glDeleteProgram(unusedProgram);
19348 ANGLE_GL_PROGRAM_WITH_TESS(program, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
19349 ASSERT_GL_NO_ERROR();
19350 glUseProgram(program);
19351
19352 constexpr GLfloat kInputData = 1.0f;
19353 GLBuffer input;
19354 glBindBuffer(GL_UNIFORM_BUFFER, input);
19355 glBufferData(GL_UNIFORM_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
19356 const GLuint kInputIndex = glGetUniformBlockIndex(program, "Input");
19357 glUniformBlockBinding(program, kInputIndex, 0);
19358 glBindBufferBase(GL_UNIFORM_BUFFER, 0, input);
19359 glBindBuffer(GL_UNIFORM_BUFFER, 0);
19360 ASSERT_GL_NO_ERROR();
19361
19362 drawPatches(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, GL_FALSE);
19363 ASSERT_GL_NO_ERROR();
19364
19365 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
19366 }
19367
19368 // Test that shader caching maintains SSBOs in tessellation evaluation shaders across shader
19369 // compilations.
TEST_P(GLSLTest_ES31,ShaderCacheTessellationEvalWithSSBO)19370 TEST_P(GLSLTest_ES31, ShaderCacheTessellationEvalWithSSBO)
19371 {
19372 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
19373 ANGLE_SKIP_TEST_IF(!IsVulkan());
19374 GLint maxTessEvalShaderStorageBlocks;
19375 glGetIntegerv(GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS_EXT,
19376 &maxTessEvalShaderStorageBlocks);
19377 ANGLE_SKIP_TEST_IF(maxTessEvalShaderStorageBlocks == 0);
19378
19379 constexpr char kTCS[] = R"(#version 310 es
19380 #extension GL_EXT_tessellation_shader : require
19381 precision mediump float;
19382
19383 layout (vertices = 1) out;
19384
19385 void main()
19386 {
19387 gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
19388 gl_TessLevelInner[0] = 1.0;
19389 gl_TessLevelInner[1] = 1.0;
19390 gl_TessLevelOuter[0] = 1.0;
19391 gl_TessLevelOuter[1] = 1.0;
19392 gl_TessLevelOuter[2] = 1.0;
19393 gl_TessLevelOuter[3] = 1.0;
19394 }
19395
19396 )";
19397
19398 constexpr char kTES[] = R"(#version 310 es
19399 #extension GL_EXT_tessellation_shader : require
19400 precision mediump float;
19401
19402 layout (quads, cw, fractional_odd_spacing) in;
19403
19404 layout (binding = 0, std430) buffer Input {
19405 float redInput;
19406 };
19407
19408 out float redValue;
19409
19410 void main()
19411 {
19412 gl_Position = vec4(gl_TessCoord.xy * 2. - 1., 0, 1);
19413
19414 redValue = redInput;
19415 }
19416 )";
19417
19418 constexpr char kFS[] = R"(#version 310 es
19419 precision mediump float;
19420
19421 out vec4 fragColor;
19422
19423 in float redValue;
19424
19425 void main()
19426 {
19427 fragColor = vec4(redValue, 0., 0., 1.);
19428 })";
19429
19430 ANGLE_GL_PROGRAM_WITH_TESS(unusedProgram, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
19431 ASSERT_GL_NO_ERROR();
19432 // Delete the shader and recompile to fetch from cache.
19433 glDeleteProgram(unusedProgram);
19434 ANGLE_GL_PROGRAM_WITH_TESS(program, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
19435 ASSERT_GL_NO_ERROR();
19436 glUseProgram(program);
19437
19438 constexpr GLfloat kInputData = 1.0f;
19439 GLBuffer input;
19440 glBindBuffer(GL_SHADER_STORAGE_BUFFER, input);
19441 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
19442 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, input);
19443 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
19444 ASSERT_GL_NO_ERROR();
19445
19446 drawPatches(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, GL_FALSE);
19447 ASSERT_GL_NO_ERROR();
19448
19449 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
19450 }
19451
19452 // Test that only macros for ESSL 1.0 compatible extensions are defined
TEST_P(GLSLTest,ESSL1ExtensionMacros)19453 TEST_P(GLSLTest, ESSL1ExtensionMacros)
19454 {
19455 std::string fs = essl1_shaders::fs::Red();
19456 fs += ExpectedExtensionMacros({
19457 "GL_ANGLE_multi_draw",
19458 "GL_APPLE_clip_distance",
19459 "GL_ARB_texture_rectangle",
19460 "GL_ARM_shader_framebuffer_fetch",
19461 "GL_EXT_blend_func_extended",
19462 "GL_EXT_draw_buffers",
19463 "GL_EXT_frag_depth",
19464 "GL_EXT_separate_shader_objects",
19465 "GL_EXT_shader_framebuffer_fetch_non_coherent",
19466 "GL_EXT_shader_framebuffer_fetch",
19467 "GL_EXT_shader_non_constant_global_initializers",
19468 "GL_EXT_shader_texture_lod",
19469 "GL_EXT_shadow_samplers",
19470 "GL_KHR_blend_equation_advanced",
19471 "GL_NV_EGL_stream_consumer_external",
19472 "GL_NV_shader_framebuffer_fetch",
19473 "GL_OES_EGL_image_external",
19474 "GL_OES_standard_derivatives",
19475 "GL_OES_texture_3D",
19476 "GL_WEBGL_video_texture",
19477 });
19478 fs += UnexpectedExtensionMacros({
19479 "GL_ANDROID_extension_pack_es31a",
19480 "GL_ANGLE_base_vertex_base_instance_shader_builtin",
19481 "GL_ANGLE_clip_cull_distance",
19482 "GL_ANGLE_shader_pixel_local_storage",
19483 "GL_ANGLE_texture_multisample",
19484 "GL_EXT_clip_cull_distance",
19485 "GL_EXT_geometry_shader",
19486 "GL_EXT_gpu_shader5",
19487 "GL_EXT_primitive_bounding_box",
19488 "GL_EXT_shader_io_blocks",
19489 "GL_EXT_tessellation_shader",
19490 "GL_EXT_texture_buffer",
19491 "GL_EXT_texture_cube_map_array",
19492 "GL_EXT_YUV_target",
19493 "GL_NV_shader_noperspective_interpolation",
19494 "GL_OES_EGL_image_external_essl3",
19495 "GL_OES_geometry_shader",
19496 "GL_OES_primitive_bounding_box",
19497 "GL_OES_sample_variables",
19498 "GL_OES_shader_image_atomic",
19499 "GL_OES_shader_io_blocks",
19500 "GL_OES_shader_multisample_interpolation",
19501 "GL_OES_texture_buffer",
19502 "GL_OES_texture_cube_map_array",
19503 "GL_OES_texture_storage_multisample_2d_array",
19504 "GL_OVR_multiview",
19505 "GL_OVR_multiview2",
19506 });
19507 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), fs.c_str());
19508 ASSERT_GL_NO_ERROR();
19509 }
19510
19511 // Test that only macros for ESSL 3.0 compatible extensions are defined
TEST_P(GLSLTest_ES3,ESSL3ExtensionMacros)19512 TEST_P(GLSLTest_ES3, ESSL3ExtensionMacros)
19513 {
19514 std::string fs = essl3_shaders::fs::Red();
19515 fs += ExpectedExtensionMacros({
19516 "GL_ANGLE_base_vertex_base_instance_shader_builtin",
19517 "GL_ANGLE_clip_cull_distance",
19518 "GL_ANGLE_multi_draw",
19519 "GL_ANGLE_shader_pixel_local_storage",
19520 "GL_ANGLE_texture_multisample",
19521 "GL_APPLE_clip_distance",
19522 "GL_ARB_texture_rectangle",
19523 "GL_ARM_shader_framebuffer_fetch",
19524 "GL_EXT_blend_func_extended",
19525 "GL_EXT_clip_cull_distance",
19526 "GL_EXT_separate_shader_objects",
19527 "GL_EXT_shader_framebuffer_fetch_non_coherent",
19528 "GL_EXT_shader_framebuffer_fetch",
19529 "GL_EXT_shader_non_constant_global_initializers",
19530 "GL_EXT_YUV_target",
19531 "GL_KHR_blend_equation_advanced",
19532 "GL_NV_EGL_stream_consumer_external",
19533 "GL_NV_shader_noperspective_interpolation",
19534 // Enabled on ESSL 3+ to workaround app bug. http://issuetracker.google.com/285871779
19535 "GL_OES_EGL_image_external",
19536 "GL_OES_EGL_image_external_essl3",
19537 // Enabled on ESSL 3+ to workaround app bug. http://issuetracker.google.com/285871779
19538 "GL_OES_texture_3D",
19539 "GL_OES_sample_variables",
19540 "GL_OES_shader_multisample_interpolation",
19541 "GL_OVR_multiview",
19542 "GL_OVR_multiview2",
19543 "GL_WEBGL_video_texture",
19544 });
19545 fs += UnexpectedExtensionMacros({
19546 "GL_ANDROID_extension_pack_es31a",
19547 "GL_EXT_draw_buffers",
19548 "GL_EXT_frag_depth",
19549 "GL_EXT_geometry_shader",
19550 "GL_EXT_gpu_shader5",
19551 "GL_EXT_primitive_bounding_box",
19552 "GL_EXT_shader_io_blocks",
19553 "GL_EXT_shader_texture_lod",
19554 "GL_EXT_shadow_samplers",
19555 "GL_EXT_tessellation_shader",
19556 "GL_EXT_texture_buffer",
19557 "GL_EXT_texture_cube_map_array",
19558 "GL_NV_shader_framebuffer_fetch",
19559 "GL_OES_geometry_shader",
19560 "GL_OES_primitive_bounding_box",
19561 "GL_OES_shader_image_atomic",
19562 "GL_OES_shader_io_blocks",
19563 "GL_OES_standard_derivatives",
19564 "GL_OES_texture_buffer",
19565 "GL_OES_texture_cube_map_array",
19566 "GL_OES_texture_storage_multisample_2d_array",
19567 });
19568 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fs.c_str());
19569 ASSERT_GL_NO_ERROR();
19570 }
19571
19572 // Test that only macros for ESSL 3.1 compatible extensions are defined
TEST_P(GLSLTest_ES31,ESSL31ExtensionMacros)19573 TEST_P(GLSLTest_ES31, ESSL31ExtensionMacros)
19574 {
19575 std::string fs = essl31_shaders::fs::Red();
19576 fs += ExpectedExtensionMacros({
19577 "GL_ANDROID_extension_pack_es31a",
19578 "GL_ANGLE_base_vertex_base_instance_shader_builtin",
19579 "GL_ANGLE_clip_cull_distance",
19580 "GL_ANGLE_multi_draw",
19581 "GL_ANGLE_shader_pixel_local_storage",
19582 "GL_ANGLE_texture_multisample",
19583 "GL_APPLE_clip_distance",
19584 "GL_ARB_texture_rectangle",
19585 "GL_ARM_shader_framebuffer_fetch",
19586 "GL_EXT_blend_func_extended",
19587 "GL_EXT_clip_cull_distance",
19588 "GL_EXT_geometry_shader",
19589 "GL_EXT_gpu_shader5",
19590 "GL_EXT_primitive_bounding_box",
19591 "GL_EXT_separate_shader_objects",
19592 "GL_EXT_shader_framebuffer_fetch_non_coherent",
19593 "GL_EXT_shader_framebuffer_fetch",
19594 "GL_EXT_shader_io_blocks",
19595 "GL_EXT_shader_non_constant_global_initializers",
19596 "GL_EXT_tessellation_shader",
19597 "GL_EXT_texture_buffer",
19598 "GL_EXT_texture_cube_map_array",
19599 "GL_EXT_YUV_target",
19600 "GL_KHR_blend_equation_advanced",
19601 "GL_NV_EGL_stream_consumer_external",
19602 "GL_NV_shader_noperspective_interpolation",
19603 // Enabled on ESSL 3+ to workaround app bug. http://issuetracker.google.com/285871779
19604 "GL_OES_EGL_image_external",
19605 "GL_OES_EGL_image_external_essl3",
19606 // Enabled on ESSL 3+ to workaround app bug. http://issuetracker.google.com/285871779
19607 "GL_OES_texture_3D",
19608 "GL_OES_geometry_shader",
19609 "GL_OES_primitive_bounding_box",
19610 "GL_OES_sample_variables",
19611 "GL_OES_shader_image_atomic",
19612 "GL_OES_shader_io_blocks",
19613 "GL_OES_shader_multisample_interpolation",
19614 "GL_OES_texture_buffer",
19615 "GL_OES_texture_cube_map_array",
19616 "GL_OES_texture_storage_multisample_2d_array",
19617 "GL_OVR_multiview",
19618 "GL_OVR_multiview2",
19619 "GL_WEBGL_video_texture",
19620 });
19621 fs += UnexpectedExtensionMacros({
19622 "GL_EXT_draw_buffers",
19623 "GL_EXT_frag_depth",
19624 "GL_EXT_shader_texture_lod",
19625 "GL_EXT_shadow_samplers",
19626 "GL_NV_shader_framebuffer_fetch",
19627 "GL_OES_standard_derivatives",
19628 });
19629 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), fs.c_str());
19630 ASSERT_GL_NO_ERROR();
19631 }
19632
19633 // Make sure names starting with webgl_ work.
TEST_P(GLSLTest_ES3,NameWithWebgl)19634 TEST_P(GLSLTest_ES3, NameWithWebgl)
19635 {
19636 constexpr char kFS[] = R"(#version 300 es
19637 out highp vec4 webgl_color;
19638 void main()
19639 {
19640 webgl_color = vec4(0, 1, 0, 1);
19641 })";
19642
19643 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
19644 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
19645 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
19646 }
19647
19648 // Make sure webgl_FragColor works.
TEST_P(GLSLTest_ES3,NameWithWebglFragColor)19649 TEST_P(GLSLTest_ES3, NameWithWebglFragColor)
19650 {
19651 constexpr char kFS[] = R"(#version 300 es
19652 out highp vec4 webgl_FragColor;
19653 void main()
19654 {
19655 webgl_FragColor = vec4(0, 1, 0, 1);
19656 })";
19657
19658 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
19659 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
19660 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
19661 }
19662
19663 // Test that the ScalarizeVecAndMatConstructorArgs workaround works correctly with constructors that
19664 // have no precision. Regression test for a bug where the generated helper has no precision
19665 // specified on the parameters and return value.
TEST_P(GLSLTest,ScalarizeVectorWorkaroundVsPrecisionlessConstructor)19666 TEST_P(GLSLTest, ScalarizeVectorWorkaroundVsPrecisionlessConstructor)
19667 {
19668 constexpr char kFS[] = R"(precision highp float;
19669 void main() {
19670 bool b1 = true;
19671 float f1 = dot(vec4(b1 ? 1.0 : 0.0, 0.0, 0.0, 0.0), vec4(1.0));
19672 gl_FragColor = vec4(f1,0.0,0.0, 1.0);
19673 })";
19674
19675 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
19676 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
19677 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
19678 }
19679
19680 // Test that Metal compiler doesn't inline non-const globals
TEST_P(WebGLGLSLTest,InvalidGlobalsNotInlined)19681 TEST_P(WebGLGLSLTest, InvalidGlobalsNotInlined)
19682 {
19683 constexpr char kFS[] = R"(#version 100
19684 precision highp float;
19685 float v1 = 0.5;
19686 float v2 = v1;
19687
19688 float f1() {
19689 return v2;
19690 }
19691
19692 void main() {
19693 gl_FragColor = vec4(v1 + f1(),0.0,0.0, 1.0);
19694 })";
19695 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
19696 ASSERT_GL_NO_ERROR();
19697 }
19698
19699 // Test that a struct can have lots of fields. Regression test for an inefficient O(n^2) check for
19700 // fields having unique names.
TEST_P(GLSLTest_ES3,LotsOfFieldsInStruct)19701 TEST_P(GLSLTest_ES3, LotsOfFieldsInStruct)
19702 {
19703 std::ostringstream fs;
19704 fs << R"(#version 300 es
19705 precision highp float;
19706 struct LotsOfFields
19707 {
19708 )";
19709 // Note: 16383 is the SPIR-V limit for struct member count.
19710 for (uint32_t i = 0; i < 16383; ++i)
19711 {
19712 fs << " float field" << i << ";\n";
19713 }
19714 fs << R"(};
19715 uniform B { LotsOfFields s; };
19716 out vec4 color;
19717 void main() {
19718 color = vec4(s.field0, 0.0, 0.0, 1.0);
19719 })";
19720
19721 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fs.str().c_str());
19722 }
19723
19724 // Test that structs with too many fields are rejected. In SPIR-V, the instruction that defines the
19725 // struct lists the fields which means the length of the instruction is a function of the field
19726 // count. Since SPIR-V instruction sizes are limited to 16 bits, structs with more fields cannot be
19727 // represented.
TEST_P(GLSLTest_ES3,TooManyFieldsInStruct)19728 TEST_P(GLSLTest_ES3, TooManyFieldsInStruct)
19729 {
19730 std::ostringstream fs;
19731 fs << R"(#version 300 es
19732 precision highp float;
19733 struct TooManyFields
19734 {
19735 )";
19736 for (uint32_t i = 0; i < (1 << 16); ++i)
19737 {
19738 fs << " float field" << i << ";\n";
19739 }
19740 fs << R"(};
19741 uniform B { TooManyFields s; };
19742 out vec4 color;
19743 void main() {
19744 color = vec4(s.field0, 0.0, 0.0, 1.0);
19745 })";
19746
19747 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, fs.str().c_str());
19748 EXPECT_EQ(0u, shader);
19749 }
19750
19751 // Same as TooManyFieldsInStruct, but with samplers in the struct.
TEST_P(GLSLTest_ES3,TooManySamplerFieldsInStruct)19752 TEST_P(GLSLTest_ES3, TooManySamplerFieldsInStruct)
19753 {
19754 std::ostringstream fs;
19755 fs << R"(#version 300 es
19756 precision highp float;
19757 struct TooManyFields
19758 {
19759 )";
19760 for (uint32_t i = 0; i < (1 << 16); ++i)
19761 {
19762 fs << " sampler2D field" << i << ";\n";
19763 }
19764 fs << R"(};
19765 uniform TooManyFields s;
19766 out vec4 color;
19767 void main() {
19768 color = texture(s.field0, vec2(0));
19769 })";
19770
19771 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, fs.str().c_str());
19772 EXPECT_EQ(0u, shader);
19773 }
19774
19775 // More complex variation of ManySamplerFieldsInStruct. This one compiles fine.
TEST_P(GLSLTest_ES3,ManySamplerFieldsInStructComplex)19776 TEST_P(GLSLTest_ES3, ManySamplerFieldsInStructComplex)
19777 {
19778 // D3D and OpenGL may be more restrictive about this many samplers.
19779 ANGLE_SKIP_TEST_IF(IsD3D() || IsOpenGL());
19780
19781 std::ostringstream fs;
19782 fs << R"(#version 300 es
19783 precision highp float;
19784
19785 struct X {
19786 mediump sampler2D a[0xf00];
19787 mediump sampler2D b[0xf00];
19788 mediump sampler2D c[0xf000];
19789 mediump sampler2D d[0xf00];
19790 };
19791
19792 struct Y {
19793 X s1;
19794 mediump sampler2D a[0xf00];
19795 mediump sampler2D b[0xf000];
19796 mediump sampler2D c[0x14000];
19797 };
19798
19799 struct S {
19800 Y s1;
19801 };
19802
19803 struct structBuffer { S s; };
19804
19805 uniform structBuffer b;
19806
19807 out vec4 color;
19808 void main()
19809 {
19810 color = texture(b.s.s1.s1.c[0], vec2(0));
19811 })";
19812
19813 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, fs.str().c_str());
19814 EXPECT_NE(0u, shader);
19815 }
19816
19817 // Make sure a large array of samplers works.
TEST_P(GLSLTest,ManySamplers)19818 TEST_P(GLSLTest, ManySamplers)
19819 {
19820 // D3D and OpenGL may be more restrictive about this many samplers.
19821 ANGLE_SKIP_TEST_IF(IsD3D() || IsOpenGL());
19822
19823 std::ostringstream fs;
19824 fs << R"(precision highp float;
19825
19826 uniform mediump sampler2D c[0x12000];
19827
19828 void main()
19829 {
19830 gl_FragColor = texture2D(c[0], vec2(0));
19831 })";
19832
19833 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, fs.str().c_str());
19834 EXPECT_NE(0u, shader);
19835 }
19836
19837 // Make sure a large array of samplers works when declared in a struct.
TEST_P(GLSLTest,ManySamplersInStruct)19838 TEST_P(GLSLTest, ManySamplersInStruct)
19839 {
19840 // D3D and OpenGL may be more restrictive about this many samplers.
19841 ANGLE_SKIP_TEST_IF(IsD3D() || IsOpenGL());
19842
19843 std::ostringstream fs;
19844 fs << R"(precision highp float;
19845
19846 struct X {
19847 mediump sampler2D c[0x12000];
19848 };
19849
19850 uniform X x;
19851
19852 void main()
19853 {
19854 gl_FragColor = texture2D(x.c[0], vec2(0));
19855 })";
19856
19857 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, fs.str().c_str());
19858 EXPECT_NE(0u, shader);
19859 }
19860
19861 // Test that passing large arrays to functions are compiled correctly. Regression test for the
19862 // SPIR-V generator that made a copy of the array to pass to the function, by decomposing and
19863 // reconstructing it (in the absence of OpCopyLogical), but the reconstruction instruction has a
19864 // length higher than can fit in SPIR-V.
TEST_P(GLSLTest_ES3,LargeInterfaceBlockArrayPassedToFunction)19865 TEST_P(GLSLTest_ES3, LargeInterfaceBlockArrayPassedToFunction)
19866 {
19867 constexpr char kFS[] = R"(#version 300 es
19868 precision highp float;
19869 uniform Large { float a[65536]; };
19870 float f(float b[65536])
19871 {
19872 b[0] = 1.0;
19873 return b[0] + b[1];
19874 }
19875 out vec4 color;
19876 void main() {
19877 color = vec4(f(a), 0.0, 0.0, 1.0);
19878 })";
19879
19880 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
19881 EXPECT_EQ(0u, shader);
19882 }
19883
19884 // Make sure the shader in LargeInterfaceBlockArrayPassedToFunction works if the large local is
19885 // avoided.
TEST_P(GLSLTest_ES3,LargeInterfaceBlockArray)19886 TEST_P(GLSLTest_ES3, LargeInterfaceBlockArray)
19887 {
19888 int maxUniformBlockSize = 0;
19889 glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &maxUniformBlockSize);
19890 ANGLE_SKIP_TEST_IF(maxUniformBlockSize < 16384 * 4);
19891
19892 constexpr char kFS[] = R"(#version 300 es
19893 precision highp float;
19894 uniform Large { float a[16384]; };
19895 out vec4 color;
19896 void main() {
19897 color = vec4(a[0], 0.0, 0.0, 1.0);
19898 })";
19899
19900 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
19901 }
19902
19903 // Similar to LargeInterfaceBlockArrayPassedToFunction, but the array is nested in a struct.
TEST_P(GLSLTest_ES3,LargeInterfaceBlockNestedArrayPassedToFunction)19904 TEST_P(GLSLTest_ES3, LargeInterfaceBlockNestedArrayPassedToFunction)
19905 {
19906 constexpr char kFS[] = R"(#version 300 es
19907 precision highp float;
19908 struct S { float a[65536]; };
19909 uniform Large { S s; };
19910 float f(float b[65536])
19911 {
19912 b[0] = 1.0;
19913 return b[0] + b[1];
19914 }
19915 out vec4 color;
19916 void main() {
19917 color = vec4(f(s.a), 0.0, 0.0, 1.0);
19918 })";
19919
19920 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
19921 EXPECT_EQ(0u, shader);
19922 }
19923
19924 // Make sure the shader in LargeInterfaceBlockNestedArrayPassedToFunction works if the large local
19925 // is avoided.
TEST_P(GLSLTest_ES3,LargeInterfaceBlockNestedArray)19926 TEST_P(GLSLTest_ES3, LargeInterfaceBlockNestedArray)
19927 {
19928 int maxUniformBlockSize = 0;
19929 glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &maxUniformBlockSize);
19930 ANGLE_SKIP_TEST_IF(maxUniformBlockSize < 16384 * 4);
19931
19932 constexpr char kFS[] = R"(#version 300 es
19933 precision highp float;
19934 struct S { float a[16384]; };
19935 uniform Large { S s; };
19936 out vec4 color;
19937 void main() {
19938 color = vec4(s.a[0], 0.0, 0.0, 1.0);
19939 })";
19940
19941 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
19942 }
19943
19944 // Similar to LargeInterfaceBlockArrayPassedToFunction, but the large array is copied to a local
19945 // variable instead.
TEST_P(GLSLTest_ES3,LargeInterfaceBlockArrayCopiedToLocal)19946 TEST_P(GLSLTest_ES3, LargeInterfaceBlockArrayCopiedToLocal)
19947 {
19948 constexpr char kFS[] = R"(#version 300 es
19949 precision highp float;
19950 uniform Large { float a[65536]; };
19951 out vec4 color;
19952 void main() {
19953 float b[65536] = a;
19954 color = vec4(b[0], 0.0, 0.0, 1.0);
19955 })";
19956
19957 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
19958 EXPECT_EQ(0u, shader);
19959 }
19960
19961 // Similar to LargeInterfaceBlockArrayCopiedToLocal, but the array is nested in a struct
TEST_P(GLSLTest_ES3,LargeInterfaceBlockNestedArrayCopiedToLocal)19962 TEST_P(GLSLTest_ES3, LargeInterfaceBlockNestedArrayCopiedToLocal)
19963 {
19964 constexpr char kFS[] = R"(#version 300 es
19965 precision highp float;
19966 struct S { float a[65536]; };
19967 uniform Large { S s; };
19968 out vec4 color;
19969 void main() {
19970 S s2 = s;
19971 color = vec4(s2.a[0], 0.0, 0.0, 1.0);
19972 })";
19973
19974 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
19975 EXPECT_EQ(0u, shader);
19976 }
19977
19978 // Test that too large varyings are rejected.
TEST_P(GLSLTest_ES3,LargeArrayVarying)19979 TEST_P(GLSLTest_ES3, LargeArrayVarying)
19980 {
19981 constexpr char kFS[] = R"(#version 300 es
19982 precision highp float;
19983 in float a[65536];
19984 out vec4 color;
19985 void main() {
19986 color = vec4(a[0], 0.0, 0.0, 1.0);
19987 })";
19988
19989 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
19990 EXPECT_EQ(0u, shader);
19991 }
19992
19993 // Regression test for const globals losing const qualifiers during MSL
19994 // translation and exceeding available temporary registers on Apple GPUs.
TEST_P(GLSLTest_ES3,LargeConstGlobalArraysOfStructs)19995 TEST_P(GLSLTest_ES3, LargeConstGlobalArraysOfStructs)
19996 {
19997 const int n = 128;
19998 std::stringstream fragmentShader;
19999 fragmentShader << "#version 300 es\n"
20000 << "precision mediump float;\n"
20001 << "uniform mediump int zero;\n"
20002 << "out vec4 color;\n"
20003 << "struct S { vec3 A; vec3 B; float C; };\n";
20004 for (int i = 0; i < 3; ++i)
20005 {
20006 fragmentShader << "const S s" << i << "[" << n << "] = S[" << n << "](\n";
20007 for (int j = 0; j < n; ++j)
20008 {
20009 fragmentShader << " S(vec3(0., 1., 0.), vec3(" << j << "), 0.)"
20010 << (j != n - 1 ? ",\n" : "\n");
20011 }
20012 fragmentShader << ");\n";
20013 }
20014 // To ensure that the array is not rescoped, it must be accessed from two functions.
20015 // To ensure that the array is not optimized out, it must be accessed with a dynamic index.
20016 fragmentShader << "vec4 foo() {\n"
20017 << " return vec4(s0[zero].A * s1[zero].A * s2[zero].A, 1.0);\n"
20018 << "}\n"
20019 << "void main() {\n"
20020 << " color = foo() * vec4(s0[zero].A * s1[zero].A * s2[zero].A, 1.0);\n"
20021 << "}\n";
20022 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fragmentShader.str().c_str());
20023
20024 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
20025 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
20026 ASSERT_GL_NO_ERROR();
20027 }
20028
20029 // Test that framebuffer fetch emulation does not add a user-visible uniform.
TEST_P(GLSLTest,FramebufferFetchDoesNotAddUniforms)20030 TEST_P(GLSLTest, FramebufferFetchDoesNotAddUniforms)
20031 {
20032 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch"));
20033 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_draw_buffers"));
20034
20035 static constexpr char kFS[] = R"(#version 100
20036 #extension GL_EXT_shader_framebuffer_fetch : require
20037 #extension GL_EXT_draw_buffers : require
20038 uniform highp vec4 u_color;
20039
20040 void main (void)
20041 {
20042 gl_FragData[0] = gl_LastFragData[0] + u_color;
20043 gl_FragData[1] = gl_LastFragData[1] + u_color;
20044 gl_FragData[2] = gl_LastFragData[2] + u_color;
20045 gl_FragData[3] = gl_LastFragData[3] + u_color;
20046 })";
20047
20048 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
20049 glUseProgram(program);
20050
20051 GLint activeUniforms = 0, uniformsMaxLength = 0;
20052 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &activeUniforms);
20053 glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &uniformsMaxLength);
20054
20055 // There should be only one active uniform
20056 EXPECT_EQ(activeUniforms, 1);
20057
20058 // And that is u_color
20059 GLsizei nameLen = uniformsMaxLength;
20060 std::vector<char> name(uniformsMaxLength);
20061
20062 GLint size;
20063 GLenum type;
20064
20065 glGetActiveUniform(program, 0, uniformsMaxLength, &nameLen, &size, &type, name.data());
20066 EXPECT_EQ(std::string(name.data()), "u_color");
20067 EXPECT_EQ(size, 1);
20068 EXPECT_EQ(type, static_cast<GLenum>(GL_FLOAT_VEC4));
20069 }
20070
20071 // Test that framebuffer fetch emulation does not add a user-visible uniform.
TEST_P(GLSLTest_ES31,FramebufferFetchDoesNotAddUniforms)20072 TEST_P(GLSLTest_ES31, FramebufferFetchDoesNotAddUniforms)
20073 {
20074 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch"));
20075
20076 static constexpr char kFS[] = R"(#version 310 es
20077 #extension GL_EXT_shader_framebuffer_fetch : require
20078 layout(location = 0) inout highp vec4 o_color;
20079
20080 layout(std140, binding = 0) buffer outBlock {
20081 highp vec4 data[256];
20082 };
20083
20084 uniform highp vec4 u_color;
20085 void main (void)
20086 {
20087 uint index = uint(gl_FragCoord.y) * 16u + uint(gl_FragCoord.x);
20088 data[index] = o_color;
20089 o_color += u_color;
20090 })";
20091
20092 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
20093 glUseProgram(program);
20094
20095 GLint activeUniforms = 0, uniformsMaxLength = 0;
20096 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &activeUniforms);
20097 glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &uniformsMaxLength);
20098
20099 // There should be only one active uniform
20100 EXPECT_EQ(activeUniforms, 1);
20101
20102 // And that is u_color
20103 GLsizei nameLen = uniformsMaxLength;
20104 std::vector<char> name(uniformsMaxLength);
20105
20106 GLint size;
20107 GLenum type;
20108
20109 glGetActiveUniform(program, 0, uniformsMaxLength, &nameLen, &size, &type, name.data());
20110 EXPECT_EQ(std::string(name.data()), "u_color");
20111 EXPECT_EQ(size, 1);
20112 EXPECT_EQ(type, static_cast<GLenum>(GL_FLOAT_VEC4));
20113 }
20114
20115 // Test that advanced blend emulation does not add a user-visible uniform.
TEST_P(GLSLTest_ES31,AdvancedBlendEquationsDoesNotAddUniforms)20116 TEST_P(GLSLTest_ES31, AdvancedBlendEquationsDoesNotAddUniforms)
20117 {
20118 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_KHR_blend_equation_advanced"));
20119
20120 static constexpr char kFS[] = R"(#version 310 es
20121 #extension GL_KHR_blend_equation_advanced : require
20122
20123 layout (blend_support_multiply) out;
20124
20125 out highp vec4 o_color;
20126
20127 layout(std140, binding = 0) buffer outBlock {
20128 highp vec4 data[256];
20129 };
20130
20131 uniform highp vec4 u_color;
20132 void main (void)
20133 {
20134 o_color = u_color;
20135 })";
20136
20137 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
20138 glUseProgram(program);
20139
20140 GLint activeUniforms = 0, uniformsMaxLength = 0;
20141 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &activeUniforms);
20142 glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &uniformsMaxLength);
20143
20144 // There should be only one active uniform
20145 EXPECT_EQ(activeUniforms, 1);
20146
20147 // And that is u_color
20148 GLsizei nameLen = uniformsMaxLength;
20149 std::vector<char> name(uniformsMaxLength);
20150
20151 GLint size;
20152 GLenum type;
20153
20154 glGetActiveUniform(program, 0, uniformsMaxLength, &nameLen, &size, &type, name.data());
20155 EXPECT_EQ(std::string(name.data()), "u_color");
20156 EXPECT_EQ(size, 1);
20157 EXPECT_EQ(type, static_cast<GLenum>(GL_FLOAT_VEC4));
20158 }
20159
20160 // Tests struct in function return type.
TEST_P(GLSLTest,StructInFunctionDefinition)20161 TEST_P(GLSLTest, StructInFunctionDefinition)
20162 {
20163 const char kFragmentShader[] = R"(precision mediump float;
20164 struct Foo
20165 {
20166 float v;
20167 };
20168
20169 Foo foo()
20170 {
20171 Foo f;
20172 f.v = 0.5;
20173 return f;
20174 }
20175
20176 void main()
20177 {
20178 gl_FragColor = vec4(1, 0, 0, 1);
20179 Foo f = foo();
20180 if (f.v == 0.5)
20181 {
20182 gl_FragColor = vec4(0, 1, 0, 1);
20183 }
20184 })";
20185
20186 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
20187 glUseProgram(program);
20188
20189 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
20190 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
20191 }
20192
20193 // Tests struct definition in function return type.
TEST_P(GLSLTest,StructDefinitionInFunctionDefinition)20194 TEST_P(GLSLTest, StructDefinitionInFunctionDefinition)
20195 {
20196 const char kFragmentShader[] = R"(precision mediump float;
20197 struct Foo { float v; } foo()
20198 {
20199 Foo f;
20200 f.v = 0.5;
20201 return f;
20202 }
20203
20204 void main()
20205 {
20206 gl_FragColor = vec4(1, 0, 0, 1);
20207 Foo f = foo();
20208 if (f.v == 0.5)
20209 {
20210 gl_FragColor = vec4(0, 1, 0, 1);
20211 }
20212 })";
20213
20214 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
20215 glUseProgram(program);
20216
20217 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
20218 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
20219 }
20220
20221 // Test struct definition in forward declaration of function return type.
TEST_P(GLSLTest,StructDefinitionInFunctionPrototype)20222 TEST_P(GLSLTest, StructDefinitionInFunctionPrototype)
20223 {
20224 const char kFragmentShader[] = R"(precision mediump float;
20225 struct Foo { float v; } foo();
20226
20227 void main()
20228 {
20229 gl_FragColor = vec4(1, 0, 0, 1);
20230 Foo f = foo();
20231 if (f.v == 0.5)
20232 {
20233 gl_FragColor = vec4(0, 1, 0, 1);
20234 }
20235 }
20236
20237 Foo foo()
20238 {
20239 Foo f;
20240 f.v = 0.5;
20241 return f;
20242 })";
20243
20244 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
20245 glUseProgram(program);
20246
20247 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
20248 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
20249 }
20250
20251 // Test that struct declarations are introduced into the correct scope.
TEST_P(GLSLTest,StructDefinitionInFunctionPrototypeScope)20252 TEST_P(GLSLTest, StructDefinitionInFunctionPrototypeScope)
20253 {
20254 const char kFragmentShader[] = R"(precision mediump float;
20255
20256 struct Foo { float v; } foo()
20257 {
20258 Foo f;
20259 f.v = 0.5;
20260 return f;
20261 }
20262
20263 struct Bar { Foo f; } bar()
20264 {
20265 Bar b;
20266 b.f = foo();
20267 return b;
20268 }
20269
20270 void main()
20271 {
20272 gl_FragColor = vec4(1, 0, 0, 1);
20273 Bar b = bar();
20274 if (b.f.v == 0.5)
20275 {
20276 gl_FragColor = vec4(0, 1, 0, 1);
20277 }
20278 })";
20279
20280 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
20281 glUseProgram(program);
20282
20283 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
20284 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
20285 }
20286
20287 // Test that struct declarations are introduced into the correct scope.
TEST_P(GLSLTest,NestedReturnedStructs)20288 TEST_P(GLSLTest, NestedReturnedStructs)
20289 {
20290 const char kFragmentShader[] = R"(precision mediump float;
20291 struct Foo { float v; } foo(float bar);
20292
20293 void main()
20294 {
20295 gl_FragColor = vec4(1, 0, 0, 1);
20296 float v = foo(foo(0.5).v).v;
20297 if (v == 0.5)
20298 {
20299 gl_FragColor = vec4(0, 1, 0, 1);
20300 }
20301 }
20302
20303 Foo foo(float bar)
20304 {
20305 Foo f;
20306 f.v = bar;
20307 return f;
20308 })";
20309
20310 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
20311 glUseProgram(program);
20312
20313 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
20314 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
20315 }
20316
20317 // Test that vec equality works.
TEST_P(GLSLTest,VecEquality)20318 TEST_P(GLSLTest, VecEquality)
20319 {
20320 const char kFragmentShader[] = R"(precision mediump float;
20321 uniform vec4 u;
20322 void main()
20323 {
20324 gl_FragColor = vec4(0, 0, 0, 1);
20325 vec4 a = vec4(1.0, 2.0, 3.0, 4.0);
20326 if (a == u)
20327 gl_FragColor.g = 1.0;
20328
20329 vec4 b = vec4(1.0) + u;
20330 if (b == u)
20331 gl_FragColor.r = 1.0;
20332 }
20333 )";
20334
20335 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
20336 glUseProgram(program);
20337 GLint u = glGetUniformLocation(program, "u");
20338 glUniform4f(u, 1, 2, 3, 4);
20339
20340 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
20341 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
20342 }
20343
20344 // Test that mat equality works.
TEST_P(GLSLTest,MatEquality)20345 TEST_P(GLSLTest, MatEquality)
20346 {
20347 const char kFragmentShader[] = R"(precision mediump float;
20348 uniform vec4 u;
20349 void main()
20350 {
20351 gl_FragColor = vec4(0, 0, 0, 1);
20352 mat4 a = mat4(1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4);
20353 if (a == mat4(u, u, u, u))
20354 gl_FragColor.g = 1.0;
20355 mat4 b = mat4(1.0);
20356 if (b == mat4(u, u, u, u))
20357 gl_FragColor.r = 1.0;
20358 }
20359 )";
20360
20361 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
20362 glUseProgram(program);
20363 GLint u = glGetUniformLocation(program, "u");
20364 glUniform4f(u, 1, 2, 3, 4);
20365
20366 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
20367 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
20368 }
20369
20370 // Test that struct equality works.
TEST_P(GLSLTest,StructEquality)20371 TEST_P(GLSLTest, StructEquality)
20372 {
20373 const char kFragmentShader[] = R"(precision mediump float;
20374 uniform vec4 u;
20375 struct A {
20376 vec4 i;
20377 };
20378 void main()
20379 {
20380 gl_FragColor = vec4(0, 0, 0, 1);
20381 A a, b;
20382 a.i = vec4(1,2,3,4);
20383 b.i = u;
20384 if (a == b)
20385 gl_FragColor.g = 1.0;
20386 b.i = vec4(1.0);
20387 if (a == b)
20388 gl_FragColor.r = 1.0;
20389 }
20390 )";
20391 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
20392 glUseProgram(program);
20393 GLint u = glGetUniformLocation(program, "u");
20394 glUniform4f(u, 1, 2, 3, 4);
20395
20396 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
20397 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
20398 }
20399
20400 // Test that nested struct equality works.
TEST_P(GLSLTest,NestedStructEquality)20401 TEST_P(GLSLTest, NestedStructEquality)
20402 {
20403 const char kFragmentShader[] = R"(precision mediump float;
20404 uniform vec4 u;
20405 struct A {
20406 vec4 i;
20407 };
20408 struct B {
20409 A a;
20410 };
20411 void main()
20412 {
20413 gl_FragColor = vec4(0, 0, 0, 1);
20414 B a, b;
20415 a.a.i = vec4(1,2,3,4);
20416 b.a.i = u;
20417 if (a == b)
20418 gl_FragColor.g = 1.0;
20419 b.a.i = vec4(1.0);
20420 if (a == b)
20421 gl_FragColor.r = 1.0;
20422 }
20423 )";
20424 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
20425 glUseProgram(program);
20426 GLint u = glGetUniformLocation(program, "u");
20427 glUniform4f(u, 1, 2, 3, 4);
20428
20429 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
20430 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
20431 }
20432
20433 // Test that double underscores user defined name is allowed
TEST_P(GLSLTest_ES3,DoubleUnderscoresName)20434 TEST_P(GLSLTest_ES3, DoubleUnderscoresName)
20435 {
20436 constexpr char kFS[] = R"(#version 300 es
20437 precision mediump float;
20438 out vec4 oColor;
20439 uniform struct __Data {float red;} data;
20440 void main() {oColor=vec4(data.red,0,1,1);})";
20441
20442 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
20443 glUseProgram(program);
20444 // populate uniform
20445 GLint uniformLocation = glGetUniformLocation(program, "data.red");
20446 EXPECT_NE(uniformLocation, -1);
20447 glUniform1f(uniformLocation, 0);
20448
20449 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
20450 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
20451 ASSERT_GL_NO_ERROR();
20452 }
20453
20454 // Test that user defined name starts with "ANGLE" or "ANGLE_"
TEST_P(GLSLTest_ES3,VariableNameStartsWithANGLE)20455 TEST_P(GLSLTest_ES3, VariableNameStartsWithANGLE)
20456 {
20457 constexpr char kFS[] = R"(#version 300 es
20458 precision mediump float;
20459 out vec4 oColor;
20460 uniform struct ANGLEData{float red;} data;
20461 uniform struct ANGLE_Data{float green;} _data;
20462 void main() {oColor=vec4(data.red,_data.green,1,1);})";
20463
20464 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
20465 glUseProgram(program);
20466 // populate uniform
20467 GLint uniformRedLocation = glGetUniformLocation(program, "data.red");
20468 GLint uniformGreenLocation = glGetUniformLocation(program, "_data.green");
20469 EXPECT_NE(uniformRedLocation, -1);
20470 EXPECT_NE(uniformGreenLocation, -1);
20471 glUniform1f(uniformRedLocation, 0);
20472 glUniform1f(uniformGreenLocation, 0);
20473
20474 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
20475 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
20476 ASSERT_GL_NO_ERROR();
20477 }
20478
20479 // Test that underscores in array names work with out arrays.
TEST_P(GLSLTest_ES3,UnderscoresWorkWithOutArrays)20480 TEST_P(GLSLTest_ES3, UnderscoresWorkWithOutArrays)
20481 {
20482 GLuint fbo;
20483 glGenFramebuffers(1, &fbo);
20484 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
20485
20486 GLuint textures[4];
20487 glGenTextures(4, textures);
20488
20489 for (size_t texIndex = 0; texIndex < ArraySize(textures); texIndex++)
20490 {
20491 glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
20492 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
20493 GL_UNSIGNED_BYTE, nullptr);
20494 }
20495
20496 GLint maxDrawBuffers;
20497 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
20498 ASSERT_GE(maxDrawBuffers, 4);
20499
20500 GLuint readFramebuffer;
20501 glGenFramebuffers(1, &readFramebuffer);
20502 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFramebuffer);
20503
20504 constexpr char kFS[] = R"(#version 300 es
20505 precision highp float;
20506 out vec4 _e[4];
20507 void main()
20508 {
20509 _e[0] = vec4(1.0, 0.0, 0.0, 1.0);
20510 _e[1] = vec4(0.0, 1.0, 0.0, 1.0);
20511 _e[2] = vec4(0.0, 0.0, 1.0, 1.0);
20512 _e[3] = vec4(1.0, 1.0, 1.0, 1.0);
20513 }
20514 )";
20515 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
20516 GLenum allBufs[4] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2,
20517 GL_COLOR_ATTACHMENT3};
20518 constexpr GLuint kMaxBuffers = 4;
20519 // Enable all draw buffers.
20520 for (GLuint texIndex = 0; texIndex < kMaxBuffers; texIndex++)
20521 {
20522 glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
20523 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
20524 textures[texIndex], 0);
20525 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
20526 textures[texIndex], 0);
20527 }
20528 glDrawBuffers(kMaxBuffers, allBufs);
20529
20530 // Draw with simple program.
20531 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
20532 ASSERT_GL_NO_ERROR();
20533 verifyAttachment2DColor(0, textures[0], GL_TEXTURE_2D, 0, GLColor::red);
20534 verifyAttachment2DColor(1, textures[1], GL_TEXTURE_2D, 0, GLColor::green);
20535 verifyAttachment2DColor(2, textures[2], GL_TEXTURE_2D, 0, GLColor::blue);
20536 verifyAttachment2DColor(3, textures[3], GL_TEXTURE_2D, 0, GLColor::white);
20537 }
20538
20539 } // anonymous namespace
20540
20541 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(
20542 GLSLTest,
20543 ES3_OPENGL().enable(Feature::ForceInitShaderVariables),
20544 ES3_OPENGL().enable(Feature::ScalarizeVecAndMatConstructorArgs),
20545 ES3_OPENGLES().enable(Feature::ScalarizeVecAndMatConstructorArgs),
20546 ES3_VULKAN().enable(Feature::AvoidOpSelectWithMismatchingRelaxedPrecision),
20547 ES3_VULKAN().enable(Feature::ForceInitShaderVariables),
20548 ES3_VULKAN().disable(Feature::SupportsSPIRV14));
20549
20550 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(GLSLTestNoValidation);
20551
20552 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLTest_ES3);
20553 ANGLE_INSTANTIATE_TEST_ES3_AND(
20554 GLSLTest_ES3,
20555 ES3_OPENGL().enable(Feature::ForceInitShaderVariables),
20556 ES3_OPENGL().enable(Feature::ScalarizeVecAndMatConstructorArgs),
20557 ES3_OPENGLES().enable(Feature::ScalarizeVecAndMatConstructorArgs),
20558 ES3_VULKAN().enable(Feature::AvoidOpSelectWithMismatchingRelaxedPrecision),
20559 ES3_VULKAN().enable(Feature::ForceInitShaderVariables),
20560 ES3_VULKAN().disable(Feature::SupportsSPIRV14));
20561
20562 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLTestLoops);
20563 ANGLE_INSTANTIATE_TEST_ES3(GLSLTestLoops);
20564
20565 ANGLE_INSTANTIATE_TEST_ES2(WebGLGLSLTest);
20566
20567 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WebGL2GLSLTest);
20568 ANGLE_INSTANTIATE_TEST_ES3(WebGL2GLSLTest);
20569
20570 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLTest_ES31);
20571 ANGLE_INSTANTIATE_TEST_ES31_AND(GLSLTest_ES31,
20572 ES31_VULKAN().enable(Feature::ForceInitShaderVariables),
20573 ES31_VULKAN().disable(Feature::SupportsSPIRV14));
20574
20575 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLTest_ES31_InitShaderVariables);
20576 ANGLE_INSTANTIATE_TEST(
20577 GLSLTest_ES31_InitShaderVariables,
20578 ES31_VULKAN().enable(Feature::ForceInitShaderVariables),
20579 ES31_VULKAN().disable(Feature::SupportsSPIRV14).enable(Feature::ForceInitShaderVariables));
20580