xref: /aosp_15_r20/external/angle/src/tests/gl_tests/GLSLTest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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