• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 class GLSLTest : public ANGLETest
18 {
19   protected:
GLSLTest()20     GLSLTest()
21     {
22         setWindowWidth(128);
23         setWindowHeight(128);
24         setConfigRedBits(8);
25         setConfigGreenBits(8);
26         setConfigBlueBits(8);
27         setConfigAlphaBits(8);
28     }
29 
GenerateVaryingType(GLint vectorSize)30     std::string GenerateVaryingType(GLint vectorSize)
31     {
32         char varyingType[10];
33 
34         if (vectorSize == 1)
35         {
36             sprintf(varyingType, "float");
37         }
38         else
39         {
40             sprintf(varyingType, "vec%d", vectorSize);
41         }
42 
43         return std::string(varyingType);
44     }
45 
GenerateVectorVaryingDeclaration(GLint vectorSize,GLint arraySize,GLint id)46     std::string GenerateVectorVaryingDeclaration(GLint vectorSize, GLint arraySize, GLint id)
47     {
48         char buff[100];
49 
50         if (arraySize == 1)
51         {
52             sprintf(buff, "varying %s v%d;\n", GenerateVaryingType(vectorSize).c_str(), id);
53         }
54         else
55         {
56             sprintf(buff, "varying %s v%d[%d];\n", GenerateVaryingType(vectorSize).c_str(), id,
57                     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             sprintf(buff, "\t v%d = %s(1.0);\n", id, GenerateVaryingType(vectorSize).c_str());
71             returnString += buff;
72         }
73         else
74         {
75             for (int i = 0; i < arraySize; i++)
76             {
77                 sprintf(buff, "\t v%d[%d] = %s(1.0);\n", id, i,
78                         GenerateVaryingType(vectorSize).c_str());
79                 returnString += buff;
80             }
81         }
82 
83         return returnString;
84     }
85 
GenerateVectorVaryingUseCode(GLint arraySize,GLint id)86     std::string GenerateVectorVaryingUseCode(GLint arraySize, GLint id)
87     {
88         if (arraySize == 1)
89         {
90             char buff[100];
91             sprintf(buff, "v%d + ", id);
92             return std::string(buff);
93         }
94         else
95         {
96             std::string returnString;
97             for (int i = 0; i < arraySize; i++)
98             {
99                 char buff[100];
100                 sprintf(buff, "v%d[%d] + ", id, i);
101                 returnString += buff;
102             }
103             return returnString;
104         }
105     }
106 
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)107     void GenerateGLSLWithVaryings(GLint floatCount,
108                                   GLint floatArrayCount,
109                                   GLint vec2Count,
110                                   GLint vec2ArrayCount,
111                                   GLint vec3Count,
112                                   GLint vec3ArrayCount,
113                                   GLint vec4Count,
114                                   GLint vec4ArrayCount,
115                                   bool useFragCoord,
116                                   bool usePointCoord,
117                                   bool usePointSize,
118                                   std::string *fragmentShader,
119                                   std::string *vertexShader)
120     {
121         // Generate a string declaring the varyings, to share between the fragment shader and the
122         // vertex shader.
123         std::string varyingDeclaration;
124 
125         unsigned int varyingCount = 0;
126 
127         for (GLint i = 0; i < floatCount; i++)
128         {
129             varyingDeclaration += GenerateVectorVaryingDeclaration(1, 1, varyingCount);
130             varyingCount += 1;
131         }
132 
133         for (GLint i = 0; i < floatArrayCount; i++)
134         {
135             varyingDeclaration += GenerateVectorVaryingDeclaration(1, 2, varyingCount);
136             varyingCount += 1;
137         }
138 
139         for (GLint i = 0; i < vec2Count; i++)
140         {
141             varyingDeclaration += GenerateVectorVaryingDeclaration(2, 1, varyingCount);
142             varyingCount += 1;
143         }
144 
145         for (GLint i = 0; i < vec2ArrayCount; i++)
146         {
147             varyingDeclaration += GenerateVectorVaryingDeclaration(2, 2, varyingCount);
148             varyingCount += 1;
149         }
150 
151         for (GLint i = 0; i < vec3Count; i++)
152         {
153             varyingDeclaration += GenerateVectorVaryingDeclaration(3, 1, varyingCount);
154             varyingCount += 1;
155         }
156 
157         for (GLint i = 0; i < vec3ArrayCount; i++)
158         {
159             varyingDeclaration += GenerateVectorVaryingDeclaration(3, 2, varyingCount);
160             varyingCount += 1;
161         }
162 
163         for (GLint i = 0; i < vec4Count; i++)
164         {
165             varyingDeclaration += GenerateVectorVaryingDeclaration(4, 1, varyingCount);
166             varyingCount += 1;
167         }
168 
169         for (GLint i = 0; i < vec4ArrayCount; i++)
170         {
171             varyingDeclaration += GenerateVectorVaryingDeclaration(4, 2, varyingCount);
172             varyingCount += 1;
173         }
174 
175         // Generate the vertex shader
176         vertexShader->clear();
177         vertexShader->append(varyingDeclaration);
178         vertexShader->append("\nvoid main()\n{\n");
179 
180         unsigned int currentVSVarying = 0;
181 
182         for (GLint i = 0; i < floatCount; i++)
183         {
184             vertexShader->append(GenerateVectorVaryingSettingCode(1, 1, currentVSVarying));
185             currentVSVarying += 1;
186         }
187 
188         for (GLint i = 0; i < floatArrayCount; i++)
189         {
190             vertexShader->append(GenerateVectorVaryingSettingCode(1, 2, currentVSVarying));
191             currentVSVarying += 1;
192         }
193 
194         for (GLint i = 0; i < vec2Count; i++)
195         {
196             vertexShader->append(GenerateVectorVaryingSettingCode(2, 1, currentVSVarying));
197             currentVSVarying += 1;
198         }
199 
200         for (GLint i = 0; i < vec2ArrayCount; i++)
201         {
202             vertexShader->append(GenerateVectorVaryingSettingCode(2, 2, currentVSVarying));
203             currentVSVarying += 1;
204         }
205 
206         for (GLint i = 0; i < vec3Count; i++)
207         {
208             vertexShader->append(GenerateVectorVaryingSettingCode(3, 1, currentVSVarying));
209             currentVSVarying += 1;
210         }
211 
212         for (GLint i = 0; i < vec3ArrayCount; i++)
213         {
214             vertexShader->append(GenerateVectorVaryingSettingCode(3, 2, currentVSVarying));
215             currentVSVarying += 1;
216         }
217 
218         for (GLint i = 0; i < vec4Count; i++)
219         {
220             vertexShader->append(GenerateVectorVaryingSettingCode(4, 1, currentVSVarying));
221             currentVSVarying += 1;
222         }
223 
224         for (GLint i = 0; i < vec4ArrayCount; i++)
225         {
226             vertexShader->append(GenerateVectorVaryingSettingCode(4, 2, currentVSVarying));
227             currentVSVarying += 1;
228         }
229 
230         if (usePointSize)
231         {
232             vertexShader->append("gl_PointSize = 1.0;\n");
233         }
234 
235         vertexShader->append("}\n");
236 
237         // Generate the fragment shader
238         fragmentShader->clear();
239         fragmentShader->append("precision highp float;\n");
240         fragmentShader->append(varyingDeclaration);
241         fragmentShader->append("\nvoid main() \n{ \n\tvec4 retColor = vec4(0,0,0,0);\n");
242 
243         unsigned int currentFSVarying = 0;
244 
245         // Make use of the float varyings
246         fragmentShader->append("\tretColor += vec4(");
247 
248         for (GLint i = 0; i < floatCount; i++)
249         {
250             fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying));
251             currentFSVarying += 1;
252         }
253 
254         for (GLint i = 0; i < floatArrayCount; i++)
255         {
256             fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying));
257             currentFSVarying += 1;
258         }
259 
260         fragmentShader->append("0.0, 0.0, 0.0, 0.0);\n");
261 
262         // Make use of the vec2 varyings
263         fragmentShader->append("\tretColor += vec4(");
264 
265         for (GLint i = 0; i < vec2Count; i++)
266         {
267             fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying));
268             currentFSVarying += 1;
269         }
270 
271         for (GLint i = 0; i < vec2ArrayCount; i++)
272         {
273             fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying));
274             currentFSVarying += 1;
275         }
276 
277         fragmentShader->append("vec2(0.0, 0.0), 0.0, 0.0);\n");
278 
279         // Make use of the vec3 varyings
280         fragmentShader->append("\tretColor += vec4(");
281 
282         for (GLint i = 0; i < vec3Count; i++)
283         {
284             fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying));
285             currentFSVarying += 1;
286         }
287 
288         for (GLint i = 0; i < vec3ArrayCount; i++)
289         {
290             fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying));
291             currentFSVarying += 1;
292         }
293 
294         fragmentShader->append("vec3(0.0, 0.0, 0.0), 0.0);\n");
295 
296         // Make use of the vec4 varyings
297         fragmentShader->append("\tretColor += ");
298 
299         for (GLint i = 0; i < vec4Count; i++)
300         {
301             fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying));
302             currentFSVarying += 1;
303         }
304 
305         for (GLint i = 0; i < vec4ArrayCount; i++)
306         {
307             fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying));
308             currentFSVarying += 1;
309         }
310 
311         fragmentShader->append("vec4(0.0, 0.0, 0.0, 0.0);\n");
312 
313         // Set gl_FragColor, and use special variables if requested
314         fragmentShader->append("\tgl_FragColor = retColor");
315 
316         if (useFragCoord)
317         {
318             fragmentShader->append(" + gl_FragCoord");
319         }
320 
321         if (usePointCoord)
322         {
323             fragmentShader->append(" + vec4(gl_PointCoord, 0.0, 0.0)");
324         }
325 
326         fragmentShader->append(";\n}");
327     }
328 
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)329     void VaryingTestBase(GLint floatCount,
330                          GLint floatArrayCount,
331                          GLint vec2Count,
332                          GLint vec2ArrayCount,
333                          GLint vec3Count,
334                          GLint vec3ArrayCount,
335                          GLint vec4Count,
336                          GLint vec4ArrayCount,
337                          bool useFragCoord,
338                          bool usePointCoord,
339                          bool usePointSize,
340                          bool expectSuccess)
341     {
342         std::string fragmentShaderSource;
343         std::string vertexShaderSource;
344 
345         GenerateGLSLWithVaryings(floatCount, floatArrayCount, vec2Count, vec2ArrayCount, vec3Count,
346                                  vec3ArrayCount, vec4Count, vec4ArrayCount, useFragCoord,
347                                  usePointCoord, usePointSize, &fragmentShaderSource,
348                                  &vertexShaderSource);
349 
350         GLuint program = CompileProgram(vertexShaderSource.c_str(), fragmentShaderSource.c_str());
351 
352         if (expectSuccess)
353         {
354             EXPECT_NE(0u, program);
355         }
356         else
357         {
358             EXPECT_EQ(0u, program);
359         }
360     }
361 
CompileGLSLWithUniformsAndSamplers(GLint vertexUniformCount,GLint fragmentUniformCount,GLint vertexSamplersCount,GLint fragmentSamplersCount,bool expectSuccess)362     void CompileGLSLWithUniformsAndSamplers(GLint vertexUniformCount,
363                                             GLint fragmentUniformCount,
364                                             GLint vertexSamplersCount,
365                                             GLint fragmentSamplersCount,
366                                             bool expectSuccess)
367     {
368         std::stringstream vertexShader;
369         std::stringstream fragmentShader;
370 
371         // Generate the vertex shader
372         vertexShader << "precision mediump float;\n";
373 
374         for (int i = 0; i < vertexUniformCount; i++)
375         {
376             vertexShader << "uniform vec4 v" << i << ";\n";
377         }
378 
379         for (int i = 0; i < vertexSamplersCount; i++)
380         {
381             vertexShader << "uniform sampler2D s" << i << ";\n";
382         }
383 
384         vertexShader << "void main()\n{\n";
385 
386         for (int i = 0; i < vertexUniformCount; i++)
387         {
388             vertexShader << "    gl_Position +=  v" << i << ";\n";
389         }
390 
391         for (int i = 0; i < vertexSamplersCount; i++)
392         {
393             vertexShader << "    gl_Position +=  texture2D(s" << i << ", vec2(0.0, 0.0));\n";
394         }
395 
396         if (vertexUniformCount == 0 && vertexSamplersCount == 0)
397         {
398             vertexShader << "   gl_Position = vec4(0.0);\n";
399         }
400 
401         vertexShader << "}\n";
402 
403         // Generate the fragment shader
404         fragmentShader << "precision mediump float;\n";
405 
406         for (int i = 0; i < fragmentUniformCount; i++)
407         {
408             fragmentShader << "uniform vec4 v" << i << ";\n";
409         }
410 
411         for (int i = 0; i < fragmentSamplersCount; i++)
412         {
413             fragmentShader << "uniform sampler2D s" << i << ";\n";
414         }
415 
416         fragmentShader << "void main()\n{\n";
417 
418         for (int i = 0; i < fragmentUniformCount; i++)
419         {
420             fragmentShader << "    gl_FragColor +=  v" << i << ";\n";
421         }
422 
423         for (int i = 0; i < fragmentSamplersCount; i++)
424         {
425             fragmentShader << "    gl_FragColor +=  texture2D(s" << i << ", vec2(0.0, 0.0));\n";
426         }
427 
428         if (fragmentUniformCount == 0 && fragmentSamplersCount == 0)
429         {
430             fragmentShader << "    gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n";
431         }
432 
433         fragmentShader << "}\n";
434 
435         GLuint program = CompileProgram(vertexShader.str().c_str(), fragmentShader.str().c_str());
436 
437         if (expectSuccess)
438         {
439             EXPECT_NE(0u, program);
440         }
441         else
442         {
443             EXPECT_EQ(0u, program);
444         }
445     }
446 
QueryErrorMessage(GLuint program)447     std::string QueryErrorMessage(GLuint program)
448     {
449         GLint infoLogLength;
450         glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);
451         EXPECT_GL_NO_ERROR();
452 
453         if (infoLogLength >= 1)
454         {
455             std::vector<GLchar> infoLog(infoLogLength);
456             glGetProgramInfoLog(program, static_cast<GLsizei>(infoLog.size()), nullptr,
457                                 infoLog.data());
458             EXPECT_GL_NO_ERROR();
459             return infoLog.data();
460         }
461 
462         return "";
463     }
464 
validateComponentsInErrorMessage(const char * vertexShader,const char * fragmentShader,const char * expectedErrorType,const char * expectedVariableFullName)465     void validateComponentsInErrorMessage(const char *vertexShader,
466                                           const char *fragmentShader,
467                                           const char *expectedErrorType,
468                                           const char *expectedVariableFullName)
469     {
470         GLuint vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
471         GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);
472 
473         GLuint program = glCreateProgram();
474         glAttachShader(program, vs);
475         glAttachShader(program, fs);
476         glLinkProgram(program);
477 
478         glDetachShader(program, vs);
479         glDetachShader(program, fs);
480         glDeleteShader(vs);
481         glDeleteShader(fs);
482 
483         const std::string &errorMessage = QueryErrorMessage(program);
484         printf("%s\n", errorMessage.c_str());
485 
486         EXPECT_NE(std::string::npos, errorMessage.find(expectedErrorType));
487         EXPECT_NE(std::string::npos, errorMessage.find(expectedVariableFullName));
488 
489         glDeleteProgram(program);
490         ASSERT_GL_NO_ERROR();
491     }
492 
verifyAttachment2DColor(unsigned int index,GLuint textureName,GLenum target,GLint level,GLColor color)493     void verifyAttachment2DColor(unsigned int index,
494                                  GLuint textureName,
495                                  GLenum target,
496                                  GLint level,
497                                  GLColor color)
498     {
499         glReadBuffer(GL_COLOR_ATTACHMENT0 + index);
500         ASSERT_GL_NO_ERROR();
501 
502         EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, color)
503             << "index " << index;
504     }
505 };
506 
507 class GLSLTestNoValidation : public GLSLTest
508 {
509   public:
GLSLTestNoValidation()510     GLSLTestNoValidation() { setNoErrorEnabled(true); }
511 };
512 
513 class GLSLTest_ES3 : public GLSLTest
514 {};
515 
516 class GLSLTest_ES31 : public GLSLTest
517 {};
518 
519 // Tests the "init output variables" ANGLE shader translator option.
520 class GLSLTest_ES31_InitShaderVariables : public GLSLTest
521 {};
522 
BuildBigInitialStackShader(int length)523 std::string BuildBigInitialStackShader(int length)
524 {
525     std::string result;
526     result += "void main() { \n";
527     for (int i = 0; i < length; i++)
528     {
529         result += "  if (true) { \n";
530     }
531     result += "  int temp; \n";
532     for (int i = 0; i <= length; i++)
533     {
534         result += "} \n";
535     }
536     return result;
537 }
538 
TEST_P(GLSLTest,NamelessScopedStructs)539 TEST_P(GLSLTest, NamelessScopedStructs)
540 {
541     constexpr char kFS[] = R"(precision mediump float;
542 void main()
543 {
544     struct
545     {
546         float q;
547     } b;
548 
549     gl_FragColor = vec4(1, 0, 0, 1);
550     gl_FragColor.a += b.q;
551 })";
552 
553     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
554 }
555 
TEST_P(GLSLTest_ES3,CompareEqualityOfArrayOfVectors)556 TEST_P(GLSLTest_ES3, CompareEqualityOfArrayOfVectors)
557 {
558     constexpr char kFS[] = R"(#version 300 es
559 precision mediump float;
560 out vec4 fragColor;
561 uniform vec3 a[3];
562 uniform vec3 b[3];
563 void main() {
564   bool same = a == b;
565   fragColor = vec4(0);
566   if (same) {
567     fragColor = vec4(1);
568   }
569 }
570 )";
571 
572     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
573     glUseProgram(program);
574 
575     GLint aLocation = glGetUniformLocation(program, "a");
576     GLint bLocation = glGetUniformLocation(program, "b");
577     EXPECT_NE(aLocation, -1);
578     EXPECT_NE(bLocation, -1);
579 
580     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
581     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
582 
583     static float almostZeros[] = {0, 0, 0, 0, 0, 0, 0, 1, 0};
584     glUniform3fv(bLocation, 9, almostZeros);
585 
586     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
587     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
588 
589     glUniform3fv(aLocation, 9, almostZeros);
590     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
591     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
592 
593     ASSERT_GL_NO_ERROR();
594 }
595 
TEST_P(GLSLTest_ES3,CompareEqualityOfArrayOfMatrices)596 TEST_P(GLSLTest_ES3, CompareEqualityOfArrayOfMatrices)
597 {
598     constexpr char kFS[] = R"(#version 300 es
599 precision mediump float;
600 out vec4 fragColor;
601 uniform mat3 a[3];
602 uniform mat3 b[3];
603 void main() {
604   bool same = a == b;
605   fragColor = vec4(0);
606   if (same) {
607     fragColor = vec4(1);
608   }
609 }
610 )";
611 
612     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
613     glUseProgram(program);
614 
615     GLint aLocation = glGetUniformLocation(program, "a");
616     GLint bLocation = glGetUniformLocation(program, "b");
617     EXPECT_NE(aLocation, -1);
618     EXPECT_NE(bLocation, -1);
619 
620     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
621     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
622 
623     static float almostZeros[] = {
624         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,
625     };
626     glUniformMatrix3fv(bLocation, 27, false, almostZeros);
627 
628     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
629     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
630 
631     glUniformMatrix3fv(aLocation, 27, false, almostZeros);
632     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
633     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
634 
635     ASSERT_GL_NO_ERROR();
636 }
637 
TEST_P(GLSLTest_ES3,CompareEqualityOfArrayOfFloats)638 TEST_P(GLSLTest_ES3, CompareEqualityOfArrayOfFloats)
639 {
640     constexpr char kFS[] = R"(#version 300 es
641 precision mediump float;
642 out vec4 fragColor;
643 uniform float a[3];
644 uniform float b[3];
645 void main() {
646   bool same = a == b;
647   fragColor = vec4(0);
648   if (same) {
649     fragColor = vec4(1);
650   }
651 }
652 )";
653 
654     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
655     glUseProgram(program);
656 
657     GLint aLocation = glGetUniformLocation(program, "a");
658     GLint bLocation = glGetUniformLocation(program, "b");
659     EXPECT_NE(aLocation, -1);
660     EXPECT_NE(bLocation, -1);
661 
662     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
663     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
664 
665     static float almostZeros[] = {
666         0,
667         0,
668         1,
669     };
670     glUniform1fv(bLocation, 3, almostZeros);
671 
672     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
673     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
674 
675     glUniform1fv(aLocation, 3, almostZeros);
676     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
677     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
678 
679     ASSERT_GL_NO_ERROR();
680 }
681 
TEST_P(GLSLTest_ES3,CompareInequalityOfArrayOfVectors)682 TEST_P(GLSLTest_ES3, CompareInequalityOfArrayOfVectors)
683 {
684     constexpr char kFS[] = R"(#version 300 es
685 precision mediump float;
686 out vec4 fragColor;
687 uniform vec3 a[3];
688 uniform vec3 b[3];
689 void main() {
690   bool notSame = a != b;
691   fragColor = vec4(0);
692   if (notSame) {
693     fragColor = vec4(1);
694   }
695 }
696 )";
697 
698     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
699     glUseProgram(program);
700 
701     GLint aLocation = glGetUniformLocation(program, "a");
702     GLint bLocation = glGetUniformLocation(program, "b");
703     EXPECT_NE(aLocation, -1);
704     EXPECT_NE(bLocation, -1);
705 
706     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
707     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
708 
709     static float almostZeros[] = {0, 0, 0, 0, 0, 0, 0, 1, 0};
710     glUniform3fv(bLocation, 9, almostZeros);
711 
712     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
713     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
714 
715     glUniform3fv(aLocation, 9, almostZeros);
716     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
717     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
718 
719     ASSERT_GL_NO_ERROR();
720 }
721 
TEST_P(GLSLTest_ES3,CompareInequalityOfArrayOfMatrices)722 TEST_P(GLSLTest_ES3, CompareInequalityOfArrayOfMatrices)
723 {
724     constexpr char kFS[] = R"(#version 300 es
725 precision mediump float;
726 out vec4 fragColor;
727 uniform mat3 a[3];
728 uniform mat3 b[3];
729 void main() {
730   bool notSame = a != b;
731   fragColor = vec4(0);
732   if (notSame) {
733     fragColor = vec4(1);
734   }
735 }
736 )";
737 
738     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
739     glUseProgram(program);
740 
741     GLint aLocation = glGetUniformLocation(program, "a");
742     GLint bLocation = glGetUniformLocation(program, "b");
743     EXPECT_NE(aLocation, -1);
744     EXPECT_NE(bLocation, -1);
745 
746     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
747     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
748 
749     static float almostZeros[] = {
750         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,
751     };
752     glUniformMatrix3fv(bLocation, 27, false, almostZeros);
753 
754     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
755     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
756 
757     glUniformMatrix3fv(aLocation, 27, false, almostZeros);
758     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
759     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
760 
761     ASSERT_GL_NO_ERROR();
762 }
763 
TEST_P(GLSLTest_ES3,CompareInequalityOfArrayOfFloats)764 TEST_P(GLSLTest_ES3, CompareInequalityOfArrayOfFloats)
765 {
766     constexpr char kFS[] = R"(#version 300 es
767 precision mediump float;
768 out vec4 fragColor;
769 uniform float a[3];
770 uniform float b[3];
771 void main() {
772   bool notSame = a != b;
773   fragColor = vec4(0);
774   if (notSame) {
775     fragColor = vec4(1);
776   }
777 }
778 )";
779 
780     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
781     glUseProgram(program);
782 
783     GLint aLocation = glGetUniformLocation(program, "a");
784     GLint bLocation = glGetUniformLocation(program, "b");
785     EXPECT_NE(aLocation, -1);
786     EXPECT_NE(bLocation, -1);
787 
788     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
789     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
790 
791     static float almostZeros[] = {
792         0,
793         0,
794         1,
795     };
796     glUniform1fv(bLocation, 3, almostZeros);
797 
798     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
799     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
800 
801     glUniform1fv(aLocation, 3, almostZeros);
802     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
803     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
804 
805     ASSERT_GL_NO_ERROR();
806 }
807 
808 // Test that array of fragment shader outputs is processed properly and draws
809 // E.g. was issue with "out vec4 frag_color[4];"
TEST_P(GLSLTest_ES3,FragmentShaderOutputArray)810 TEST_P(GLSLTest_ES3, FragmentShaderOutputArray)
811 {
812     GLuint fbo;
813     glGenFramebuffers(1, &fbo);
814     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
815 
816     GLuint textures[4];
817     glGenTextures(4, textures);
818 
819     for (size_t texIndex = 0; texIndex < ArraySize(textures); texIndex++)
820     {
821         glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
822         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
823                      GL_UNSIGNED_BYTE, nullptr);
824     }
825 
826     GLint maxDrawBuffers;
827     glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
828     ASSERT_GE(maxDrawBuffers, 4);
829 
830     GLuint readFramebuffer;
831     glGenFramebuffers(1, &readFramebuffer);
832     glBindFramebuffer(GL_READ_FRAMEBUFFER, readFramebuffer);
833 
834     constexpr char kFS[] = R"(#version 300 es
835 precision highp float;
836 
837 out vec4 frag_color[4];
838 
839 void main()
840 {
841     frag_color[0] = vec4(1.0, 0.0, 0.0, 1.0);
842     frag_color[1] = vec4(0.0, 1.0, 0.0, 1.0);
843     frag_color[2] = vec4(0.0, 0.0, 1.0, 1.0);
844     frag_color[3] = vec4(1.0, 1.0, 1.0, 1.0);
845 }
846 )";
847 
848     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
849 
850     GLenum allBufs[4] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2,
851                          GL_COLOR_ATTACHMENT3};
852 
853     constexpr GLuint kMaxBuffers = 4;
854 
855     // Enable all draw buffers.
856     for (GLuint texIndex = 0; texIndex < kMaxBuffers; texIndex++)
857     {
858         glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
859         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
860                                textures[texIndex], 0);
861         glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
862                                textures[texIndex], 0);
863     }
864     glDrawBuffers(kMaxBuffers, allBufs);
865 
866     // Draw with simple program.
867     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
868     ASSERT_GL_NO_ERROR();
869 
870     verifyAttachment2DColor(0, textures[0], GL_TEXTURE_2D, 0, GLColor::red);
871     verifyAttachment2DColor(1, textures[1], GL_TEXTURE_2D, 0, GLColor::green);
872     verifyAttachment2DColor(2, textures[2], GL_TEXTURE_2D, 0, GLColor::blue);
873     verifyAttachment2DColor(3, textures[3], GL_TEXTURE_2D, 0, GLColor::white);
874 }
875 
876 // Test that inactive fragment shader outputs don't cause a crash.
TEST_P(GLSLTest_ES3,InactiveFragmentShaderOutput)877 TEST_P(GLSLTest_ES3, InactiveFragmentShaderOutput)
878 {
879     constexpr char kFS[] = R"(#version 300 es
880 precision highp float;
881 
882 // Make color0 inactive but specify color1 first.  The Vulkan backend assigns bogus locations when
883 // compiling and fixes it up in SPIR-V.  If color0's location is not fixed, it will return location
884 // 1 (aliasing color1).  This will lead to a Vulkan validation warning about attachment 0 not being
885 // written to, which shouldn't be fatal.
886 layout(location = 1) out vec4 color1;
887 layout(location = 0) out vec4 color0;
888 
889 void main()
890 {
891     color1 = vec4(0.0, 1.0, 0.0, 1.0);
892 }
893 )";
894 
895     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
896 
897     constexpr GLint kDrawBufferCount = 2;
898 
899     GLint maxDrawBuffers;
900     glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
901     ASSERT_GE(maxDrawBuffers, kDrawBufferCount);
902 
903     GLTexture textures[kDrawBufferCount];
904 
905     for (GLint texIndex = 0; texIndex < kDrawBufferCount; ++texIndex)
906     {
907         glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
908         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
909                      GL_UNSIGNED_BYTE, nullptr);
910     }
911 
912     GLenum allBufs[kDrawBufferCount] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
913 
914     GLFramebuffer fbo;
915     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
916 
917     // Enable all draw buffers.
918     for (GLint texIndex = 0; texIndex < kDrawBufferCount; ++texIndex)
919     {
920         glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
921         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
922                                textures[texIndex], 0);
923     }
924     glDrawBuffers(kDrawBufferCount, allBufs);
925 
926     // Draw with simple program.
927     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
928     ASSERT_GL_NO_ERROR();
929 }
930 
TEST_P(GLSLTest,ScopedStructsOrderBug)931 TEST_P(GLSLTest, ScopedStructsOrderBug)
932 {
933     constexpr char kFS[] = R"(precision mediump float;
934 
935 struct T
936 {
937     float f;
938 };
939 
940 void main()
941 {
942     T a;
943 
944     struct T
945     {
946         float q;
947     };
948 
949     T b;
950 
951     gl_FragColor = vec4(1, 0, 0, 1);
952     gl_FragColor.a += a.f;
953     gl_FragColor.a += b.q;
954 })";
955 
956     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
957 }
958 
959 // Test that defining a struct together with an inactive uniform, then using it in a scope that has
960 // another struct with the same name declared works.
TEST_P(GLSLTest,ScopedStructsOrderBug2)961 TEST_P(GLSLTest, ScopedStructsOrderBug2)
962 {
963     constexpr char kFS[] = R"(precision mediump float;
964 
965 uniform struct T
966 {
967     float f;
968 } x;
969 
970 void main()
971 {
972     T a;
973 
974     struct T
975     {
976         float q;
977     };
978 
979     T b;
980 
981     gl_FragColor = vec4(1, 0, 0, 1);
982     gl_FragColor.a += a.f;
983     gl_FragColor.a += b.q;
984 })";
985 
986     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
987 }
988 
989 // Regression test based on WebGL's conformance/glsl/misc/empty-declaration.html
TEST_P(GLSLTest,StructEmptyDeclaratorBug)990 TEST_P(GLSLTest, StructEmptyDeclaratorBug)
991 {
992     constexpr char kVS[] = R"(
993 struct S {
994     float member;
995 }, a;
996 void main() {
997     a.member = 0.0;
998     gl_Position = vec4(a.member);
999 })";
1000 
1001     constexpr char kFS[] = R"(precision mediump float;
1002 precision mediump float;
1003 void main()
1004 {
1005     gl_FragColor = vec4(1.0,0.0,0.0,1.0);
1006 })";
1007 
1008     ANGLE_GL_PROGRAM(program, kVS, kFS);
1009 }
1010 
1011 // Regression test based on WebGL's conformance/ogles/GL/build/build_001_to_008.html
TEST_P(GLSLTest,StructConstantFoldingBug)1012 TEST_P(GLSLTest, StructConstantFoldingBug)
1013 {
1014     constexpr char kVS[] = R"(
1015 void main()
1016 {
1017 
1018    const struct s2 {
1019        int i;
1020        vec3 v3;
1021        bvec4 bv4;
1022    } s22  = s2(8, vec3(9, 10, 11), bvec4(true, false, true, false));
1023 
1024    struct s4 {
1025        int ii;
1026        vec4 v4;
1027       };
1028 
1029    const struct s1 {
1030       s2 ss;
1031       int i;
1032       float f;
1033       mat4 m;
1034       s4 s44;
1035    } s11 = s1(s22, 2, 4.0, mat4(5), s4(6, vec4(7, 8, 9, 10))) ;
1036 
1037   const int field3 = s11.i * s11.ss.i;  // constant folding (int * int)
1038   const vec4 field4 = s11.s44.v4 * s11.s44.v4; // constant folding (vec4 * vec4)
1039  // 49, 64, 81, 100
1040   const vec4 v4 = vec4(s11.ss.v3.y, s11.m[3][3], field3, field4[2]);  // 10.0, 5.0, 16.0, 81.0
1041   gl_Position = v4;
1042 })";
1043 
1044     constexpr char kFS[] = R"(precision mediump float;
1045 precision mediump float;
1046 void main()
1047 {
1048     gl_FragColor = vec4(1.0,0.0,0.0,1.0);
1049 })";
1050 
1051     ANGLE_GL_PROGRAM(program, kVS, kFS);
1052 }
1053 
1054 // Test that constant folding doesn't remove struct declaration.
TEST_P(GLSLTest,StructConstantFoldingBug2)1055 TEST_P(GLSLTest, StructConstantFoldingBug2)
1056 {
1057     constexpr char kVS[] = R"(
1058 uniform vec4 u;
1059 
1060 void main()
1061 {
1062 
1063    const struct s2 {
1064        int i;
1065        vec3 v3;
1066        bvec4 bv4;
1067    } s22  = s2(8, vec3(9, 10, 11), bvec4(true, false, true, false));
1068 
1069    s2 x;
1070    x.v3 = u.xyz;
1071 
1072    gl_Position = vec4(x.v3, float(s22.i));
1073 })";
1074 
1075     constexpr char kFS[] = R"(precision mediump float;
1076 precision mediump float;
1077 void main()
1078 {
1079     gl_FragColor = vec4(1.0,0.0,0.0,1.0);
1080 })";
1081 
1082     ANGLE_GL_PROGRAM(program, kVS, kFS);
1083 }
1084 
TEST_P(GLSLTest,ScopedStructsBug)1085 TEST_P(GLSLTest, ScopedStructsBug)
1086 {
1087     constexpr char kFS[] = R"(precision mediump float;
1088 
1089 struct T_0
1090 {
1091     float f;
1092 };
1093 
1094 void main()
1095 {
1096     gl_FragColor = vec4(1, 0, 0, 1);
1097 
1098     struct T
1099     {
1100         vec2 v;
1101     };
1102 
1103     T_0 a;
1104     T b;
1105 
1106     gl_FragColor.a += a.f;
1107     gl_FragColor.a += b.v.x;
1108 })";
1109 
1110     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
1111 }
1112 
TEST_P(GLSLTest,DxPositionBug)1113 TEST_P(GLSLTest, DxPositionBug)
1114 {
1115     constexpr char kVS[] = R"(attribute vec4 inputAttribute;
1116 varying float dx_Position;
1117 void main()
1118 {
1119     gl_Position = vec4(inputAttribute);
1120     dx_Position = 0.0;
1121 })";
1122 
1123     constexpr char kFS[] = R"(precision mediump float;
1124 
1125 varying float dx_Position;
1126 
1127 void main()
1128 {
1129     gl_FragColor = vec4(dx_Position, 0, 0, 1);
1130 })";
1131 
1132     ANGLE_GL_PROGRAM(program, kVS, kFS);
1133 }
1134 
1135 // Draw an array of points with the first vertex offset at 0 using gl_VertexID
TEST_P(GLSLTest_ES3,GLVertexIDOffsetZeroDrawArray)1136 TEST_P(GLSLTest_ES3, GLVertexIDOffsetZeroDrawArray)
1137 {
1138     // http://anglebug.com/4092
1139     ANGLE_SKIP_TEST_IF(isSwiftshader());
1140     constexpr int kStartIndex  = 0;
1141     constexpr int kArrayLength = 5;
1142     constexpr char kVS[]       = R"(#version 300 es
1143 precision highp float;
1144 void main() {
1145     gl_Position = vec4(float(gl_VertexID)/10.0, 0, 0, 1);
1146     gl_PointSize = 3.0;
1147 })";
1148 
1149     constexpr char kFS[] = R"(#version 300 es
1150 precision highp float;
1151 out vec4 outColor;
1152 void main() {
1153     outColor = vec4(1.0, 0.0, 0.0, 1.0);
1154 })";
1155 
1156     ANGLE_GL_PROGRAM(program, kVS, kFS);
1157 
1158     glUseProgram(program);
1159     glDrawArrays(GL_POINTS, kStartIndex, kArrayLength);
1160 
1161     double pointCenterX = static_cast<double>(getWindowWidth()) / 2.0;
1162     double pointCenterY = static_cast<double>(getWindowHeight()) / 2.0;
1163     for (int i = kStartIndex; i < kStartIndex + kArrayLength; i++)
1164     {
1165         double pointOffsetX = static_cast<double>(i * getWindowWidth()) / 20.0;
1166         EXPECT_PIXEL_COLOR_EQ(static_cast<int>(pointCenterX + pointOffsetX),
1167                               static_cast<int>(pointCenterY), GLColor::red);
1168     }
1169 }
1170 
GetFirstIntPixelRedValue()1171 GLint GetFirstIntPixelRedValue()
1172 {
1173     GLint pixel[4];
1174     glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_INT, pixel);
1175     return pixel[0];
1176 }
1177 
TEST_P(GLSLTest_ES3,GLVertexIDIntegerTextureDrawElements)1178 TEST_P(GLSLTest_ES3, GLVertexIDIntegerTextureDrawElements)
1179 {
1180     constexpr char kVS[] = R"(#version 300 es
1181     flat out highp int vVertexID;
1182 
1183     void main() {
1184         vVertexID = gl_VertexID;
1185         gl_PointSize = 1.0;
1186         gl_Position = vec4(0,0,0,1);
1187     })";
1188 
1189     constexpr char kFS[] = R"(#version 300 es
1190     flat in highp int vVertexID;
1191     out highp int oVertexID;
1192     void main() {
1193         oVertexID = vVertexID;
1194     })";
1195 
1196     ANGLE_GL_PROGRAM(program, kVS, kFS);
1197     glUseProgram(program);
1198     glViewport(0, 0, 1, 1);
1199 
1200     GLTexture tex;
1201     glBindTexture(GL_TEXTURE_2D, tex);
1202     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, 1, 1);
1203     GLFramebuffer fb;
1204     glBindFramebuffer(GL_FRAMEBUFFER, fb);
1205     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
1206 
1207     EXPECT_GL_NO_ERROR();
1208 
1209     GLint clearData[4] = {42};
1210     glClearBufferiv(GL_COLOR, 0, clearData);
1211     EXPECT_EQ(42, GetFirstIntPixelRedValue());
1212 
1213     const int kIndexDataSize = 5;
1214     GLushort indexData[]     = {1, 2, 5, 3, 10000};
1215     GLBuffer indexBuffer;
1216     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1217     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_STATIC_DRAW);
1218 
1219     for (size_t first = 0; first < kIndexDataSize; ++first)
1220     {
1221         for (size_t count = 1; first + count <= kIndexDataSize; ++count)
1222         {
1223             glDrawElements(GL_POINTS, count, GL_UNSIGNED_SHORT,
1224                            reinterpret_cast<const void *>(first * 2u));
1225             GLint expected = indexData[first + count - 1];
1226             GLint actual   = GetFirstIntPixelRedValue();
1227             EXPECT_EQ(expected, actual);
1228         }
1229     }
1230     EXPECT_GL_NO_ERROR();
1231 }
1232 
TEST_P(GLSLTest_ES3,GLVertexIDIntegerTextureDrawElementsU8)1233 TEST_P(GLSLTest_ES3, GLVertexIDIntegerTextureDrawElementsU8)
1234 {
1235     constexpr char kVS[] = R"(#version 300 es
1236     flat out highp int vVertexID;
1237 
1238     void main() {
1239         vVertexID = gl_VertexID;
1240         gl_PointSize = 1.0;
1241         gl_Position = vec4(0,0,0,1);
1242     })";
1243 
1244     constexpr char kFS[] = R"(#version 300 es
1245     flat in highp int vVertexID;
1246     out highp int oVertexID;
1247     void main() {
1248         oVertexID = vVertexID;
1249     })";
1250 
1251     ANGLE_GL_PROGRAM(program, kVS, kFS);
1252     glUseProgram(program);
1253     glViewport(0, 0, 1, 1);
1254 
1255     GLTexture tex;
1256     glBindTexture(GL_TEXTURE_2D, tex);
1257     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, 1, 1);
1258     GLFramebuffer fb;
1259     glBindFramebuffer(GL_FRAMEBUFFER, fb);
1260     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
1261 
1262     EXPECT_GL_NO_ERROR();
1263 
1264     GLint clearData[4] = {42};
1265     glClearBufferiv(GL_COLOR, 0, clearData);
1266     EXPECT_EQ(42, GetFirstIntPixelRedValue());
1267 
1268     const int kIndexDataSize = 5;
1269     GLubyte indexData[]      = {1, 2, 5, 3, 100};
1270     GLBuffer indexBuffer;
1271     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1272     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_STATIC_DRAW);
1273 
1274     for (size_t first = 0; first < kIndexDataSize; ++first)
1275     {
1276         for (size_t count = 1; first + count <= kIndexDataSize; ++count)
1277         {
1278             glDrawElements(GL_POINTS, count, GL_UNSIGNED_BYTE,
1279                            reinterpret_cast<const void *>(first));
1280             GLint expected = indexData[first + count - 1];
1281             GLint actual   = GetFirstIntPixelRedValue();
1282             EXPECT_EQ(expected, actual);
1283         }
1284     }
1285     EXPECT_GL_NO_ERROR();
1286 }
1287 
GLVertexIDIntegerTextureDrawElementsU8Line_Helper(size_t first,const GLubyte * indices)1288 void GLVertexIDIntegerTextureDrawElementsU8Line_Helper(size_t first, const GLubyte *indices)
1289 {
1290     glDrawElements(GL_LINES, 2, GL_UNSIGNED_BYTE, reinterpret_cast<const void *>(first));
1291 
1292     GLint pixels[8];
1293     glReadPixels(0, 0, 2, 1, GL_RGBA_INTEGER, GL_INT, pixels);
1294 
1295     GLint expected = indices[first + 1];
1296     EXPECT_EQ(expected, pixels[0]);
1297     EXPECT_EQ(expected, pixels[4]);
1298 }
1299 
TEST_P(GLSLTest_ES3,GLVertexIDIntegerTextureDrawElementsU8Line)1300 TEST_P(GLSLTest_ES3, GLVertexIDIntegerTextureDrawElementsU8Line)
1301 {
1302     constexpr char kVS[] = R"(#version 300 es
1303     flat out highp int vVertexID;
1304     layout(location = 0) in vec4 position;
1305 
1306     void main() {
1307         vVertexID = gl_VertexID;
1308         gl_Position = position;
1309     })";
1310 
1311     constexpr char kFS[] = R"(#version 300 es
1312     flat in highp int vVertexID;
1313     out highp int oVertexID;
1314     void main() {
1315         oVertexID = vVertexID;
1316     })";
1317 
1318     ANGLE_GL_PROGRAM(program, kVS, kFS);
1319     glUseProgram(program);
1320     glViewport(0, 0, 2, 1);
1321 
1322     GLTexture tex;
1323     glBindTexture(GL_TEXTURE_2D, tex);
1324     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, 2, 1);
1325     GLFramebuffer fb;
1326     glBindFramebuffer(GL_FRAMEBUFFER, fb);
1327     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
1328 
1329     EXPECT_GL_NO_ERROR();
1330 
1331     struct LR
1332     {
1333         LR() : X0(-1.0f), X1(1.0f) {}
1334         float X0;
1335         float X1;
1336     };
1337     constexpr int kNumVertices = 100;
1338     LR vertData[kNumVertices];
1339     GLBuffer buf;
1340     glBindBuffer(GL_ARRAY_BUFFER, buf);
1341     glBufferData(GL_ARRAY_BUFFER, sizeof(vertData), vertData, GL_STATIC_DRAW);
1342     glEnableVertexAttribArray(0);
1343     glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
1344 
1345     GLint clearData[4] = {42};
1346     glClearBufferiv(GL_COLOR, 0, clearData);
1347     EXPECT_EQ(42, GetFirstIntPixelRedValue());
1348 
1349     GLubyte indexData[] = {1, 4, 5, 2, 50, 61};
1350     GLBuffer indexBuffer;
1351     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1352     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_STATIC_DRAW);
1353 
1354     GLVertexIDIntegerTextureDrawElementsU8Line_Helper(0, indexData);
1355     GLVertexIDIntegerTextureDrawElementsU8Line_Helper(1, indexData);
1356     GLVertexIDIntegerTextureDrawElementsU8Line_Helper(2, indexData);
1357     GLVertexIDIntegerTextureDrawElementsU8Line_Helper(4, indexData);
1358 
1359     EXPECT_GL_NO_ERROR();
1360 }
1361 
1362 // Test gl_VertexID works with lines
TEST_P(GLSLTest_ES3,GLVertexIDIntegerTextureDrawElementsU8LineIds)1363 TEST_P(GLSLTest_ES3, GLVertexIDIntegerTextureDrawElementsU8LineIds)
1364 {
1365     // Draws lines via indices (glDrawElements). Each pair of indices
1366     // draws the next consecutive pixel. For 2 points, because we're
1367     // using int attributes, they must be "flat" and so the spec
1368     // says for a given line the value should come from the second
1369     // of the 2 points. (see: OpenGL ES 3.0.2 spec Table 2.12)
1370     // Each line is only 1 pixel long so every other pixel should
1371     // be the default value.
1372     constexpr char kVS[] = R"(#version 300 es
1373     flat out highp int vVertexID;
1374     layout(location = 0) in float position;
1375     uniform float width;
1376 
1377     void main() {
1378         vVertexID = gl_VertexID;
1379         gl_Position = vec4(position / width * 2.0 - 1.0, 0, 0, 1);
1380     })";
1381 
1382     constexpr char kFS[] = R"(#version 300 es
1383     flat in highp int vVertexID;
1384     out highp int oVertexID;
1385     void main() {
1386         oVertexID = vVertexID;
1387     })";
1388 
1389     GLubyte indexData[]          = {1, 4, 5, 2, 50, 61, 32, 33};
1390     constexpr size_t kNumIndices = sizeof(indexData) / sizeof(indexData[0]);
1391     GLBuffer indexBuffer;
1392     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1393     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_STATIC_DRAW);
1394 
1395     ANGLE_GL_PROGRAM(program, kVS, kFS);
1396     glUseProgram(program);
1397     glUniform1f(glGetUniformLocation(program, "width"), kNumIndices);
1398     glViewport(0, 0, kNumIndices, 1);
1399 
1400     GLTexture tex;
1401     glBindTexture(GL_TEXTURE_2D, tex);
1402     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, kNumIndices, 1);
1403     GLFramebuffer fb;
1404     glBindFramebuffer(GL_FRAMEBUFFER, fb);
1405     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
1406 
1407     constexpr int kNumVertices = 100;
1408     std::vector<float> vertData(kNumVertices, -1.0f);
1409     {
1410         int i = 0;
1411         for (GLubyte ndx : indexData)
1412         {
1413             vertData[ndx] = i++;
1414         }
1415     }
1416     GLBuffer buf;
1417     glBindBuffer(GL_ARRAY_BUFFER, buf);
1418     glBufferData(GL_ARRAY_BUFFER, vertData.size() * sizeof(float), vertData.data(), GL_STATIC_DRAW);
1419     glEnableVertexAttribArray(0);
1420     glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
1421 
1422     GLint kDefaultValue = 42;
1423     GLint clearData[4]  = {kDefaultValue};
1424     glClearBufferiv(GL_COLOR, 0, clearData);
1425     EXPECT_EQ(kDefaultValue, GetFirstIntPixelRedValue());
1426 
1427     EXPECT_GL_NO_ERROR();
1428 
1429     glDrawElements(GL_LINES, kNumIndices, GL_UNSIGNED_BYTE, 0);
1430 
1431     GLint pixels[kNumIndices * 4];
1432     glReadPixels(0, 0, kNumIndices, 1, GL_RGBA_INTEGER, GL_INT, pixels);
1433 
1434     for (size_t i = 0; i < kNumIndices; ++i)
1435     {
1436         const int expected = i % 2 ? kDefaultValue : indexData[i + 1];
1437         const int actual   = pixels[i * 4];
1438         EXPECT_EQ(expected, actual);
1439     }
1440 
1441     EXPECT_GL_NO_ERROR();
1442 }
1443 
1444 // Helper function for the GLVertexIDIntegerTextureDrawArrays test
GLVertexIDIntegerTextureDrawArrays_helper(int first,int count,GLenum err)1445 void GLVertexIDIntegerTextureDrawArrays_helper(int first, int count, GLenum err)
1446 {
1447     glDrawArrays(GL_POINTS, first, count);
1448 
1449     int pixel[4];
1450     glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_INT, pixel);
1451     // If we call this function with err as GL_NO_ERROR, then we expect no error and check the
1452     // pixels.
1453     if (err == static_cast<GLenum>(GL_NO_ERROR))
1454     {
1455         EXPECT_GL_NO_ERROR();
1456         EXPECT_EQ(pixel[0], first + count - 1);
1457     }
1458     else
1459     {
1460         // If we call this function with err set, we will allow the error, but check the pixels if
1461         // the error hasn't occurred.
1462         GLenum glError = glGetError();
1463         if (glError == err || glError == static_cast<GLenum>(GL_NO_ERROR))
1464         {
1465             EXPECT_EQ(pixel[0], first + count - 1);
1466         }
1467     }
1468 }
1469 
1470 // Ensure gl_VertexID gets passed to an integer texture properly when drawArrays is called. This
1471 // is based off the WebGL test:
1472 // https://github.com/KhronosGroup/WebGL/blob/master/sdk/tests/conformance2/rendering/vertex-id.html
TEST_P(GLSLTest_ES3,GLVertexIDIntegerTextureDrawArrays)1473 TEST_P(GLSLTest_ES3, GLVertexIDIntegerTextureDrawArrays)
1474 {
1475     constexpr char kVS[] = R"(#version 300 es
1476 flat out highp int vVertexID;
1477 void main() {
1478     vVertexID = gl_VertexID;
1479     gl_Position = vec4(0,0,0,1);
1480     gl_PointSize = 1.0;
1481 })";
1482 
1483     constexpr char kFS[] = R"(#version 300 es
1484 flat in highp int vVertexID;
1485 out highp int oVertexID;
1486 void main() {
1487     oVertexID = vVertexID;
1488 })";
1489 
1490     ANGLE_GL_PROGRAM(program, kVS, kFS);
1491     glUseProgram(program);
1492     glViewport(0, 0, 1, 1);
1493 
1494     GLTexture texture;
1495     glBindTexture(GL_TEXTURE_2D, texture);
1496     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, 1, 1);
1497     GLFramebuffer fbo;
1498     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1499     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1500     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1501     EXPECT_GL_NO_ERROR();
1502 
1503     // Clear the texture to 42 to ensure the first test case doesn't accidentally pass
1504     GLint val[4] = {42};
1505     glClearBufferiv(GL_COLOR, 0, val);
1506     int pixel[4];
1507     glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_INT, pixel);
1508     EXPECT_EQ(pixel[0], val[0]);
1509 
1510     GLVertexIDIntegerTextureDrawArrays_helper(0, 1, GL_NO_ERROR);
1511     GLVertexIDIntegerTextureDrawArrays_helper(1, 1, GL_NO_ERROR);
1512     GLVertexIDIntegerTextureDrawArrays_helper(10000, 1, GL_NO_ERROR);
1513     GLVertexIDIntegerTextureDrawArrays_helper(100000, 1, GL_NO_ERROR);
1514     GLVertexIDIntegerTextureDrawArrays_helper(1000000, 1, GL_NO_ERROR);
1515     GLVertexIDIntegerTextureDrawArrays_helper(0, 2, GL_NO_ERROR);
1516     GLVertexIDIntegerTextureDrawArrays_helper(1, 2, GL_NO_ERROR);
1517     GLVertexIDIntegerTextureDrawArrays_helper(10000, 2, GL_NO_ERROR);
1518     GLVertexIDIntegerTextureDrawArrays_helper(100000, 2, GL_NO_ERROR);
1519     GLVertexIDIntegerTextureDrawArrays_helper(1000000, 2, GL_NO_ERROR);
1520 
1521     int32_t int32Max = 0x7FFFFFFF;
1522     GLVertexIDIntegerTextureDrawArrays_helper(int32Max - 2, 1, GL_OUT_OF_MEMORY);
1523     GLVertexIDIntegerTextureDrawArrays_helper(int32Max - 1, 1, GL_OUT_OF_MEMORY);
1524 }
1525 
1526 // Draw an array of points with the first vertex offset at 5 using gl_VertexID
TEST_P(GLSLTest_ES3,GLVertexIDOffsetFiveDrawArray)1527 TEST_P(GLSLTest_ES3, GLVertexIDOffsetFiveDrawArray)
1528 {
1529     // http://anglebug.com/4092
1530     ANGLE_SKIP_TEST_IF(isSwiftshader());
1531     // Bug in Nexus drivers, offset does not work. (anglebug.com/3264)
1532     ANGLE_SKIP_TEST_IF(IsNexus5X() && IsOpenGLES());
1533 
1534     constexpr int kStartIndex  = 5;
1535     constexpr int kArrayLength = 5;
1536     constexpr char kVS[]       = R"(#version 300 es
1537 precision highp float;
1538 void main() {
1539     gl_Position = vec4(float(gl_VertexID)/10.0, 0, 0, 1);
1540     gl_PointSize = 3.0;
1541 })";
1542 
1543     constexpr char kFS[] = R"(#version 300 es
1544 precision highp float;
1545 out vec4 outColor;
1546 void main() {
1547     outColor = vec4(1.0, 0.0, 0.0, 1.0);
1548 })";
1549 
1550     ANGLE_GL_PROGRAM(program, kVS, kFS);
1551 
1552     glUseProgram(program);
1553     glDrawArrays(GL_POINTS, kStartIndex, kArrayLength);
1554 
1555     double pointCenterX = static_cast<double>(getWindowWidth()) / 2.0;
1556     double pointCenterY = static_cast<double>(getWindowHeight()) / 2.0;
1557     for (int i = kStartIndex; i < kStartIndex + kArrayLength; i++)
1558     {
1559         double pointOffsetX = static_cast<double>(i * getWindowWidth()) / 20.0;
1560         EXPECT_PIXEL_COLOR_EQ(static_cast<int>(pointCenterX + pointOffsetX),
1561                               static_cast<int>(pointCenterY), GLColor::red);
1562     }
1563 }
1564 
TEST_P(GLSLTest,ElseIfRewriting)1565 TEST_P(GLSLTest, ElseIfRewriting)
1566 {
1567     constexpr char kVS[] =
1568         "attribute vec4 a_position;\n"
1569         "varying float v;\n"
1570         "void main() {\n"
1571         "  gl_Position = a_position;\n"
1572         "  v = 1.0;\n"
1573         "  if (a_position.x <= 0.5) {\n"
1574         "    v = 0.0;\n"
1575         "  } else if (a_position.x >= 0.5) {\n"
1576         "    v = 2.0;\n"
1577         "  }\n"
1578         "}\n";
1579 
1580     constexpr char kFS[] =
1581         "precision highp float;\n"
1582         "varying float v;\n"
1583         "void main() {\n"
1584         "  vec4 color = vec4(1.0, 0.0, 0.0, 1.0);\n"
1585         "  if (v >= 1.0) color = vec4(0.0, 1.0, 0.0, 1.0);\n"
1586         "  if (v >= 2.0) color = vec4(0.0, 0.0, 1.0, 1.0);\n"
1587         "  gl_FragColor = color;\n"
1588         "}\n";
1589 
1590     ANGLE_GL_PROGRAM(program, kVS, kFS);
1591 
1592     drawQuad(program, "a_position", 0.5f);
1593 
1594     EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
1595     EXPECT_PIXEL_EQ(getWindowWidth() - 1, 0, 0, 255, 0, 255);
1596 }
1597 
TEST_P(GLSLTest,TwoElseIfRewriting)1598 TEST_P(GLSLTest, TwoElseIfRewriting)
1599 {
1600     constexpr char kVS[] =
1601         "attribute vec4 a_position;\n"
1602         "varying float v;\n"
1603         "void main() {\n"
1604         "  gl_Position = a_position;\n"
1605         "  if (a_position.x == 0.0) {\n"
1606         "    v = 1.0;\n"
1607         "  } else if (a_position.x > 0.5) {\n"
1608         "    v = 0.0;\n"
1609         "  } else if (a_position.x > 0.75) {\n"
1610         "    v = 0.5;\n"
1611         "  }\n"
1612         "}\n";
1613 
1614     constexpr char kFS[] =
1615         "precision highp float;\n"
1616         "varying float v;\n"
1617         "void main() {\n"
1618         "  gl_FragColor = vec4(v, 0.0, 0.0, 1.0);\n"
1619         "}\n";
1620 
1621     ANGLE_GL_PROGRAM(program, kVS, kFS);
1622 }
1623 
TEST_P(GLSLTest,FrontFacingAndVarying)1624 TEST_P(GLSLTest, FrontFacingAndVarying)
1625 {
1626     EGLPlatformParameters platform = GetParam().eglParameters;
1627 
1628     constexpr char kVS[] = R"(attribute vec4 a_position;
1629 varying float v_varying;
1630 void main()
1631 {
1632     v_varying = a_position.x;
1633     gl_Position = a_position;
1634 })";
1635 
1636     constexpr char kFS[] = R"(precision mediump float;
1637 varying float v_varying;
1638 void main()
1639 {
1640     vec4 c;
1641 
1642     if (gl_FrontFacing)
1643     {
1644         c = vec4(v_varying, 0, 0, 1.0);
1645     }
1646     else
1647     {
1648         c = vec4(0, v_varying, 0, 1.0);
1649     }
1650     gl_FragColor = c;
1651 })";
1652 
1653     GLuint program = CompileProgram(kVS, kFS);
1654 
1655     // Compilation should fail on D3D11 feature level 9_3, since gl_FrontFacing isn't supported.
1656     if (platform.renderer == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
1657     {
1658         if (platform.majorVersion == 9 && platform.minorVersion == 3)
1659         {
1660             EXPECT_EQ(0u, program);
1661             return;
1662         }
1663     }
1664 
1665     // Otherwise, compilation should succeed
1666     EXPECT_NE(0u, program);
1667 }
1668 
1669 // Test that we can release the shader compiler and still compile things properly.
TEST_P(GLSLTest,ReleaseCompilerThenCompile)1670 TEST_P(GLSLTest, ReleaseCompilerThenCompile)
1671 {
1672     // Draw with the first program.
1673     ANGLE_GL_PROGRAM(program1, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
1674     drawQuad(program1, essl1_shaders::PositionAttrib(), 0.5f);
1675     ASSERT_GL_NO_ERROR();
1676     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1677 
1678     // Clear and release shader compiler.
1679     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
1680     glClear(GL_COLOR_BUFFER_BIT);
1681     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1682     glReleaseShaderCompiler();
1683     ASSERT_GL_NO_ERROR();
1684 
1685     // Draw with a second program.
1686     ANGLE_GL_PROGRAM(program2, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
1687     drawQuad(program2, essl1_shaders::PositionAttrib(), 0.5f);
1688     ASSERT_GL_NO_ERROR();
1689     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1690 }
1691 
1692 // Verify that linking shaders declaring different shading language versions fails.
TEST_P(GLSLTest_ES3,VersionMismatch)1693 TEST_P(GLSLTest_ES3, VersionMismatch)
1694 {
1695     GLuint program = CompileProgram(essl3_shaders::vs::Simple(), essl1_shaders::fs::Red());
1696     EXPECT_EQ(0u, program);
1697 
1698     program = CompileProgram(essl1_shaders::vs::Simple(), essl3_shaders::fs::Red());
1699     EXPECT_EQ(0u, program);
1700 }
1701 
1702 // Verify that declaring varying as invariant only in vertex shader fails in ESSL 1.00.
TEST_P(GLSLTest,InvariantVaryingOut)1703 TEST_P(GLSLTest, InvariantVaryingOut)
1704 {
1705     constexpr char kFS[] =
1706         "precision mediump float;\n"
1707         "varying float v_varying;\n"
1708         "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1709 
1710     constexpr char kVS[] =
1711         "attribute vec4 a_position;\n"
1712         "invariant varying float v_varying;\n"
1713         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1714 
1715     GLuint program = CompileProgram(kVS, kFS);
1716     EXPECT_EQ(0u, program);
1717 }
1718 
1719 // Verify that declaring varying as invariant only in vertex shader succeeds in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantVaryingOut)1720 TEST_P(GLSLTest_ES3, InvariantVaryingOut)
1721 {
1722     // TODO: ESSL 3.00 -> GLSL 1.20 translation should add "invariant" in fragment shader
1723     // for varyings which are invariant in vertex shader (http://anglebug.com/1293)
1724     ANGLE_SKIP_TEST_IF(IsDesktopOpenGL());
1725 
1726     constexpr char kFS[] =
1727         "#version 300 es\n"
1728         "precision mediump float;\n"
1729         "in float v_varying;\n"
1730         "out vec4 my_FragColor;\n"
1731         "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1732 
1733     constexpr char kVS[] =
1734         "#version 300 es\n"
1735         "in vec4 a_position;\n"
1736         "invariant out float v_varying;\n"
1737         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1738 
1739     GLuint program = CompileProgram(kVS, kFS);
1740     EXPECT_NE(0u, program);
1741 }
1742 
1743 // Verify that declaring varying as invariant only in fragment shader fails in ESSL 1.00.
TEST_P(GLSLTest,InvariantVaryingIn)1744 TEST_P(GLSLTest, InvariantVaryingIn)
1745 {
1746     constexpr char kFS[] =
1747         "precision mediump float;\n"
1748         "invariant varying float v_varying;\n"
1749         "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1750 
1751     constexpr char kVS[] =
1752         "attribute vec4 a_position;\n"
1753         "varying float v_varying;\n"
1754         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1755 
1756     GLuint program = CompileProgram(kVS, kFS);
1757     EXPECT_EQ(0u, program);
1758 }
1759 
1760 // Verify that declaring varying as invariant only in fragment shader fails in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantVaryingIn)1761 TEST_P(GLSLTest_ES3, InvariantVaryingIn)
1762 {
1763     constexpr char kFS[] =
1764         "#version 300 es\n"
1765         "precision mediump float;\n"
1766         "invariant in float v_varying;\n"
1767         "out vec4 my_FragColor;\n"
1768         "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1769 
1770     constexpr char kVS[] =
1771         "#version 300 es\n"
1772         "in vec4 a_position;\n"
1773         "out float v_varying;\n"
1774         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1775 
1776     GLuint program = CompileProgram(kVS, kFS);
1777     EXPECT_EQ(0u, program);
1778 }
1779 
1780 // Verify that declaring varying as invariant in both shaders succeeds in ESSL 1.00.
TEST_P(GLSLTest,InvariantVaryingBoth)1781 TEST_P(GLSLTest, InvariantVaryingBoth)
1782 {
1783     constexpr char kFS[] =
1784         "precision mediump float;\n"
1785         "invariant varying float v_varying;\n"
1786         "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1787 
1788     constexpr char kVS[] =
1789         "attribute vec4 a_position;\n"
1790         "invariant varying float v_varying;\n"
1791         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1792 
1793     GLuint program = CompileProgram(kVS, kFS);
1794     EXPECT_NE(0u, program);
1795 }
1796 
1797 // Verify that declaring varying as invariant in both shaders fails in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantVaryingBoth)1798 TEST_P(GLSLTest_ES3, InvariantVaryingBoth)
1799 {
1800     constexpr char kFS[] =
1801         "#version 300 es\n"
1802         "precision mediump float;\n"
1803         "invariant in float v_varying;\n"
1804         "out vec4 my_FragColor;\n"
1805         "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1806 
1807     constexpr char kVS[] =
1808         "#version 300 es\n"
1809         "in vec4 a_position;\n"
1810         "invariant out float v_varying;\n"
1811         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1812 
1813     GLuint program = CompileProgram(kVS, kFS);
1814     EXPECT_EQ(0u, program);
1815 }
1816 
1817 // Verify that declaring gl_Position as invariant succeeds in ESSL 1.00.
TEST_P(GLSLTest,InvariantGLPosition)1818 TEST_P(GLSLTest, InvariantGLPosition)
1819 {
1820     constexpr char kFS[] =
1821         "precision mediump float;\n"
1822         "varying float v_varying;\n"
1823         "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1824 
1825     constexpr char kVS[] =
1826         "attribute vec4 a_position;\n"
1827         "invariant gl_Position;\n"
1828         "varying float v_varying;\n"
1829         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1830 
1831     GLuint program = CompileProgram(kVS, kFS);
1832     EXPECT_NE(0u, program);
1833 }
1834 
1835 // Verify that declaring gl_Position as invariant succeeds in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantGLPosition)1836 TEST_P(GLSLTest_ES3, InvariantGLPosition)
1837 {
1838     constexpr char kFS[] =
1839         "#version 300 es\n"
1840         "precision mediump float;\n"
1841         "in float v_varying;\n"
1842         "out vec4 my_FragColor;\n"
1843         "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1844 
1845     constexpr char kVS[] =
1846         "#version 300 es\n"
1847         "in vec4 a_position;\n"
1848         "invariant gl_Position;\n"
1849         "out float v_varying;\n"
1850         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1851 
1852     GLuint program = CompileProgram(kVS, kFS);
1853     EXPECT_NE(0u, program);
1854 }
1855 
1856 // Verify that using invariant(all) in both shaders fails in ESSL 1.00.
TEST_P(GLSLTest,InvariantAllBoth)1857 TEST_P(GLSLTest, InvariantAllBoth)
1858 {
1859     constexpr char kFS[] =
1860         "#pragma STDGL invariant(all)\n"
1861         "precision mediump float;\n"
1862         "varying float v_varying;\n"
1863         "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1864 
1865     constexpr char kVS[] =
1866         "#pragma STDGL invariant(all)\n"
1867         "attribute vec4 a_position;\n"
1868         "varying float v_varying;\n"
1869         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1870 
1871     GLuint program = CompileProgram(kVS, kFS);
1872     EXPECT_EQ(0u, program);
1873 }
1874 
1875 // Verify that using a struct as both invariant and non-invariant output works.
TEST_P(GLSLTest_ES31,StructBothInvariantAndNot)1876 TEST_P(GLSLTest_ES31, StructBothInvariantAndNot)
1877 {
1878     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
1879 
1880     constexpr char kVS[] = R"(#version 310 es
1881 #extension GL_EXT_shader_io_blocks : require
1882 
1883 struct S
1884 {
1885     vec4 s;
1886 };
1887 
1888 out Output
1889 {
1890     vec4 x;
1891     invariant S s;
1892 };
1893 
1894 out S s2;
1895 
1896 void main(){
1897     x = vec4(0);
1898     s.s = vec4(1);
1899     s2.s = vec4(2);
1900     S s3 = s;
1901     s.s = s3.s;
1902 })";
1903 
1904     GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
1905     EXPECT_NE(0u, shader);
1906     glDeleteShader(shader);
1907 }
1908 
1909 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnFloat)1910 TEST_P(GLSLTest, MissingReturnFloat)
1911 {
1912     constexpr char kVS[] =
1913         "varying float v_varying;\n"
1914         "float f() { if (v_varying > 0.0) return 1.0; }\n"
1915         "void main() { gl_Position = vec4(f(), 0, 0, 1); }\n";
1916 
1917     GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
1918     EXPECT_NE(0u, program);
1919 }
1920 
1921 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnVec2)1922 TEST_P(GLSLTest, MissingReturnVec2)
1923 {
1924     constexpr char kVS[] =
1925         "varying float v_varying;\n"
1926         "vec2 f() { if (v_varying > 0.0) return vec2(1.0, 1.0); }\n"
1927         "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
1928 
1929     GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
1930     EXPECT_NE(0u, program);
1931 }
1932 
1933 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnVec3)1934 TEST_P(GLSLTest, MissingReturnVec3)
1935 {
1936     constexpr char kVS[] =
1937         "varying float v_varying;\n"
1938         "vec3 f() { if (v_varying > 0.0) return vec3(1.0, 1.0, 1.0); }\n"
1939         "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
1940 
1941     GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
1942     EXPECT_NE(0u, program);
1943 }
1944 
1945 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnVec4)1946 TEST_P(GLSLTest, MissingReturnVec4)
1947 {
1948     constexpr char kVS[] =
1949         "varying float v_varying;\n"
1950         "vec4 f() { if (v_varying > 0.0) return vec4(1.0, 1.0, 1.0, 1.0); }\n"
1951         "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
1952 
1953     GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
1954     EXPECT_NE(0u, program);
1955 }
1956 
1957 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnIVec4)1958 TEST_P(GLSLTest, MissingReturnIVec4)
1959 {
1960     constexpr char kVS[] =
1961         "varying float v_varying;\n"
1962         "ivec4 f() { if (v_varying > 0.0) return ivec4(1, 1, 1, 1); }\n"
1963         "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
1964 
1965     GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
1966     EXPECT_NE(0u, program);
1967 }
1968 
1969 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnMat4)1970 TEST_P(GLSLTest, MissingReturnMat4)
1971 {
1972     constexpr char kVS[] =
1973         "varying float v_varying;\n"
1974         "mat4 f() { if (v_varying > 0.0) return mat4(1.0); }\n"
1975         "void main() { gl_Position = vec4(f()[0][0], 0, 0, 1); }\n";
1976 
1977     GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
1978     EXPECT_NE(0u, program);
1979 }
1980 
1981 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnStruct)1982 TEST_P(GLSLTest, MissingReturnStruct)
1983 {
1984     constexpr char kVS[] =
1985         "varying float v_varying;\n"
1986         "struct s { float a; int b; vec2 c; };\n"
1987         "s f() { if (v_varying > 0.0) return s(1.0, 1, vec2(1.0, 1.0)); }\n"
1988         "void main() { gl_Position = vec4(f().a, 0, 0, 1); }\n";
1989 
1990     GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
1991     EXPECT_NE(0u, program);
1992 }
1993 
1994 // Verify that functions without return statements still compile
TEST_P(GLSLTest_ES3,MissingReturnArray)1995 TEST_P(GLSLTest_ES3, MissingReturnArray)
1996 {
1997     constexpr char kVS[] =
1998         "#version 300 es\n"
1999         "in float v_varying;\n"
2000         "vec2[2] f() { if (v_varying > 0.0) { return vec2[2](vec2(1.0, 1.0), vec2(1.0, 1.0)); } }\n"
2001         "void main() { gl_Position = vec4(f()[0].x, 0, 0, 1); }\n";
2002 
2003     GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
2004     EXPECT_NE(0u, program);
2005 }
2006 
2007 // Verify that functions without return statements still compile
TEST_P(GLSLTest_ES3,MissingReturnArrayOfStructs)2008 TEST_P(GLSLTest_ES3, MissingReturnArrayOfStructs)
2009 {
2010     constexpr char kVS[] =
2011         "#version 300 es\n"
2012         "in float v_varying;\n"
2013         "struct s { float a; int b; vec2 c; };\n"
2014         "s[2] f() { if (v_varying > 0.0) { return s[2](s(1.0, 1, vec2(1.0, 1.0)), s(1.0, 1, "
2015         "vec2(1.0, 1.0))); } }\n"
2016         "void main() { gl_Position = vec4(f()[0].a, 0, 0, 1); }\n";
2017 
2018     GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
2019     EXPECT_NE(0u, program);
2020 }
2021 
2022 // Verify that functions without return statements still compile
TEST_P(GLSLTest_ES3,MissingReturnStructOfArrays)2023 TEST_P(GLSLTest_ES3, MissingReturnStructOfArrays)
2024 {
2025     // TODO(crbug.com/998505): Test failing on Android FYI Release (NVIDIA Shield TV)
2026     ANGLE_SKIP_TEST_IF(IsNVIDIAShield());
2027 
2028     constexpr char kVS[] =
2029         "#version 300 es\n"
2030         "in float v_varying;\n"
2031         "struct s { float a[2]; int b[2]; vec2 c[2]; };\n"
2032         "s f() { if (v_varying > 0.0) { return s(float[2](1.0, 1.0), int[2](1, 1),"
2033         "vec2[2](vec2(1.0, 1.0), vec2(1.0, 1.0))); } }\n"
2034         "void main() { gl_Position = vec4(f().a[0], 0, 0, 1); }\n";
2035 
2036     GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
2037     EXPECT_NE(0u, program);
2038 }
2039 
2040 // Verify that non-const index used on an array returned by a function compiles
TEST_P(GLSLTest_ES3,ReturnArrayOfStructsThenNonConstIndex)2041 TEST_P(GLSLTest_ES3, ReturnArrayOfStructsThenNonConstIndex)
2042 {
2043     constexpr char kVS[] = R"(#version 300 es
2044 in float v_varying;
2045 struct s { float a; int b; vec2 c; };
2046 s[2] f()
2047 {
2048     return s[2](s(v_varying, 1, vec2(1.0, 1.0)), s(v_varying / 2.0, 1, vec2(1.0, 1.0)));
2049 }
2050 void main()
2051 {
2052     gl_Position = vec4(f()[uint(v_varying)].a, 0, 0, 1);
2053 })";
2054 
2055     GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
2056     EXPECT_NE(0u, program);
2057 }
2058 
2059 // Verify that using invariant(all) in both shaders fails in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantAllBoth)2060 TEST_P(GLSLTest_ES3, InvariantAllBoth)
2061 {
2062     constexpr char kFS[] =
2063         "#version 300 es\n"
2064         "#pragma STDGL invariant(all)\n"
2065         "precision mediump float;\n"
2066         "in float v_varying;\n"
2067         "out vec4 my_FragColor;\n"
2068         "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
2069 
2070     constexpr char kVS[] =
2071         "#version 300 es\n"
2072         "#pragma STDGL invariant(all)\n"
2073         "in vec4 a_position;\n"
2074         "out float v_varying;\n"
2075         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
2076 
2077     GLuint program = CompileProgram(kVS, kFS);
2078     EXPECT_EQ(0u, program);
2079 }
2080 
2081 // Verify that using invariant(all) only in fragment shader succeeds in ESSL 1.00.
TEST_P(GLSLTest,InvariantAllIn)2082 TEST_P(GLSLTest, InvariantAllIn)
2083 {
2084     constexpr char kFS[] =
2085         "#pragma STDGL invariant(all)\n"
2086         "precision mediump float;\n"
2087         "varying float v_varying;\n"
2088         "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
2089 
2090     constexpr char kVS[] =
2091         "attribute vec4 a_position;\n"
2092         "varying float v_varying;\n"
2093         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
2094 
2095     GLuint program = CompileProgram(kVS, kFS);
2096     EXPECT_NE(0u, program);
2097 }
2098 
2099 // Verify that using invariant(all) only in fragment shader fails in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantAllIn)2100 TEST_P(GLSLTest_ES3, InvariantAllIn)
2101 {
2102     constexpr char kFS[] =
2103         "#version 300 es\n"
2104         "#pragma STDGL invariant(all)\n"
2105         "precision mediump float;\n"
2106         "in float v_varying;\n"
2107         "out vec4 my_FragColor;\n"
2108         "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
2109 
2110     constexpr char kVS[] =
2111         "#version 300 es\n"
2112         "in vec4 a_position;\n"
2113         "out float v_varying;\n"
2114         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
2115 
2116     GLuint program = CompileProgram(kVS, kFS);
2117     EXPECT_EQ(0u, program);
2118 }
2119 
2120 // Verify that using invariant(all) only in vertex shader fails in ESSL 1.00.
TEST_P(GLSLTest,InvariantAllOut)2121 TEST_P(GLSLTest, InvariantAllOut)
2122 {
2123     constexpr char kFS[] =
2124         "precision mediump float;\n"
2125         "varying float v_varying;\n"
2126         "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
2127 
2128     constexpr char kVS[] =
2129         "#pragma STDGL invariant(all)\n"
2130         "attribute vec4 a_position;\n"
2131         "varying float v_varying;\n"
2132         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
2133 
2134     GLuint program = CompileProgram(kVS, kFS);
2135     EXPECT_EQ(0u, program);
2136 }
2137 
2138 // Verify that using invariant(all) only in vertex shader succeeds in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantAllOut)2139 TEST_P(GLSLTest_ES3, InvariantAllOut)
2140 {
2141     // TODO: ESSL 3.00 -> GLSL 1.20 translation should add "invariant" in fragment shader
2142     // for varyings which are invariant in vertex shader,
2143     // because of invariant(all) being used in vertex shader (http://anglebug.com/1293)
2144     ANGLE_SKIP_TEST_IF(IsDesktopOpenGL());
2145 
2146     constexpr char kFS[] =
2147         "#version 300 es\n"
2148         "precision mediump float;\n"
2149         "in float v_varying;\n"
2150         "out vec4 my_FragColor;\n"
2151         "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
2152 
2153     constexpr char kVS[] =
2154         "#version 300 es\n"
2155         "#pragma STDGL invariant(all)\n"
2156         "in vec4 a_position;\n"
2157         "out float v_varying;\n"
2158         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
2159 
2160     GLuint program = CompileProgram(kVS, kFS);
2161     EXPECT_NE(0u, program);
2162 }
2163 
TEST_P(GLSLTest,MaxVaryingVec4)2164 TEST_P(GLSLTest, MaxVaryingVec4)
2165 {
2166     // TODO(geofflang): Find out why this doesn't compile on Apple AMD OpenGL drivers
2167     // (http://anglebug.com/1291)
2168     ANGLE_SKIP_TEST_IF(IsOSX() && IsAMD() && IsOpenGL());
2169 
2170     GLint maxVaryings = 0;
2171     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2172 
2173     VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, false, false, false, true);
2174 }
2175 
2176 // Verify we can pack registers with one builtin varying.
TEST_P(GLSLTest,MaxVaryingVec4_OneBuiltin)2177 TEST_P(GLSLTest, MaxVaryingVec4_OneBuiltin)
2178 {
2179     GLint maxVaryings = 0;
2180     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2181 
2182     // Generate shader code that uses gl_FragCoord.
2183     VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 1, 0, true, false, false, true);
2184 }
2185 
2186 // Verify we can pack registers with two builtin varyings.
TEST_P(GLSLTest,MaxVaryingVec4_TwoBuiltins)2187 TEST_P(GLSLTest, MaxVaryingVec4_TwoBuiltins)
2188 {
2189     GLint maxVaryings = 0;
2190     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2191 
2192     // Generate shader code that uses gl_FragCoord and gl_PointCoord.
2193     VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 2, 0, true, true, false, true);
2194 }
2195 
2196 // Verify we can pack registers with three builtin varyings.
TEST_P(GLSLTest,MaxVaryingVec4_ThreeBuiltins)2197 TEST_P(GLSLTest, MaxVaryingVec4_ThreeBuiltins)
2198 {
2199     GLint maxVaryings = 0;
2200     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2201 
2202     // Generate shader code that uses gl_FragCoord, gl_PointCoord and gl_PointSize.
2203     VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 3, 0, true, true, true, true);
2204 }
2205 
2206 // This covers a problematic case in D3D9 - we are limited by the number of available semantics,
2207 // rather than total register use.
TEST_P(GLSLTest,MaxVaryingsSpecialCases)2208 TEST_P(GLSLTest, MaxVaryingsSpecialCases)
2209 {
2210     ANGLE_SKIP_TEST_IF(!IsD3D9());
2211 
2212     GLint maxVaryings = 0;
2213     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2214 
2215     VaryingTestBase(maxVaryings, 0, 0, 0, 0, 0, 0, 0, true, false, false, false);
2216     VaryingTestBase(maxVaryings - 1, 0, 0, 0, 0, 0, 0, 0, true, true, false, false);
2217     VaryingTestBase(maxVaryings - 2, 0, 0, 0, 0, 0, 0, 0, true, true, false, true);
2218 
2219     // Special case for gl_PointSize: we get it for free on D3D9.
2220     VaryingTestBase(maxVaryings - 2, 0, 0, 0, 0, 0, 0, 0, true, true, true, true);
2221 }
2222 
2223 // This covers a problematic case in D3D9 - we are limited by the number of available semantics,
2224 // rather than total register use.
TEST_P(GLSLTest,MaxMinusTwoVaryingVec2PlusOneSpecialVariable)2225 TEST_P(GLSLTest, MaxMinusTwoVaryingVec2PlusOneSpecialVariable)
2226 {
2227     GLint maxVaryings = 0;
2228     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2229 
2230     // Generate shader code that uses gl_FragCoord.
2231     VaryingTestBase(0, 0, maxVaryings, 0, 0, 0, 0, 0, true, false, false, !IsD3D9());
2232 }
2233 
TEST_P(GLSLTest,MaxVaryingVec3)2234 TEST_P(GLSLTest, MaxVaryingVec3)
2235 {
2236     GLint maxVaryings = 0;
2237     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2238 
2239     VaryingTestBase(0, 0, 0, 0, maxVaryings, 0, 0, 0, false, false, false, true);
2240 }
2241 
TEST_P(GLSLTest,MaxVaryingVec3Array)2242 TEST_P(GLSLTest, MaxVaryingVec3Array)
2243 {
2244     GLint maxVaryings = 0;
2245     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2246 
2247     VaryingTestBase(0, 0, 0, 0, 0, maxVaryings / 2, 0, 0, false, false, false, true);
2248 }
2249 
2250 // Only fails on D3D9 because of packing limitations.
TEST_P(GLSLTest,MaxVaryingVec3AndOneFloat)2251 TEST_P(GLSLTest, MaxVaryingVec3AndOneFloat)
2252 {
2253     GLint maxVaryings = 0;
2254     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2255 
2256     VaryingTestBase(1, 0, 0, 0, maxVaryings, 0, 0, 0, false, false, false, !IsD3D9());
2257 }
2258 
2259 // Only fails on D3D9 because of packing limitations.
TEST_P(GLSLTest,MaxVaryingVec3ArrayAndOneFloatArray)2260 TEST_P(GLSLTest, MaxVaryingVec3ArrayAndOneFloatArray)
2261 {
2262     GLint maxVaryings = 0;
2263     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2264 
2265     VaryingTestBase(0, 1, 0, 0, 0, maxVaryings / 2, 0, 0, false, false, false, !IsD3D9());
2266 }
2267 
2268 // Only fails on D3D9 because of packing limitations.
TEST_P(GLSLTest,TwiceMaxVaryingVec2)2269 TEST_P(GLSLTest, TwiceMaxVaryingVec2)
2270 {
2271     // TODO(geofflang): Figure out why this fails on NVIDIA's GLES driver
2272     // (http://anglebug.com/3849)
2273     ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGLES());
2274 
2275     // TODO(geofflang): Find out why this doesn't compile on Apple AMD OpenGL drivers
2276     // (http://anglebug.com/1291)
2277     ANGLE_SKIP_TEST_IF(IsOSX() && IsAMD() && IsOpenGL());
2278 
2279     GLint maxVaryings = 0;
2280     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2281 
2282     VaryingTestBase(0, 0, 2 * maxVaryings, 0, 0, 0, 0, 0, false, false, false, !IsD3D9());
2283 }
2284 
2285 // Disabled because of a failure in D3D9
TEST_P(GLSLTest,MaxVaryingVec2Arrays)2286 TEST_P(GLSLTest, MaxVaryingVec2Arrays)
2287 {
2288     ANGLE_SKIP_TEST_IF(IsD3D9());
2289 
2290     // TODO(geofflang): Figure out why this fails on NVIDIA's GLES driver
2291     ANGLE_SKIP_TEST_IF(IsOpenGLES());
2292 
2293     // TODO(geofflang): Find out why this doesn't compile on Apple AMD OpenGL drivers
2294     // (http://anglebug.com/1291)
2295     ANGLE_SKIP_TEST_IF(IsOSX() && IsAMD() && IsOpenGL());
2296 
2297     GLint maxVaryings = 0;
2298     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2299 
2300     // Special case: because arrays of mat2 are packed as small grids of two rows by two columns,
2301     // we should be aware that when we're packing into an odd number of varying registers the
2302     // last row will be empty and can not fit the final vec2 arrary.
2303     GLint maxVec2Arrays = (maxVaryings >> 1) << 1;
2304 
2305     VaryingTestBase(0, 0, 0, maxVec2Arrays, 0, 0, 0, 0, false, false, false, true);
2306 }
2307 
2308 // Verify max varying with feedback and gl_line enabled
TEST_P(GLSLTest_ES3,MaxVaryingWithFeedbackAndGLline)2309 TEST_P(GLSLTest_ES3, MaxVaryingWithFeedbackAndGLline)
2310 {
2311     // (http://anglebug.com/4439)
2312     ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsVulkan());
2313 
2314     // http://anglebug.com/4446
2315     ANGLE_SKIP_TEST_IF(IsOSX() && IsOpenGL());
2316 
2317     GLint maxVaryings = 0;
2318     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2319 
2320     std::stringstream vertexShaderSource;
2321     std::stringstream fragmentShaderSource;
2322 
2323     // substract 1 here for gl_PointSize
2324     const GLint vec4Count     = maxVaryings - 1;
2325     unsigned int varyingCount = 0;
2326     std::string varyingDeclaration;
2327     for (GLint i = 0; i < vec4Count; i++)
2328     {
2329         varyingDeclaration += GenerateVectorVaryingDeclaration(4, 1, varyingCount);
2330         varyingCount += 1;
2331     }
2332     // Generate the vertex shader
2333     vertexShaderSource.clear();
2334     vertexShaderSource << varyingDeclaration;
2335     vertexShaderSource << "\nattribute vec4 a_position;\n";
2336     vertexShaderSource << "\nvoid main()\n{\n";
2337     unsigned int currentVSVarying = 0;
2338     for (GLint i = 0; i < vec4Count; i++)
2339     {
2340         vertexShaderSource << GenerateVectorVaryingSettingCode(4, 1, currentVSVarying);
2341         currentVSVarying += 1;
2342     }
2343     vertexShaderSource << "\tgl_Position = vec4(a_position.rgb, 1);\n";
2344     vertexShaderSource << "\tgl_PointSize = 1.0;\n";
2345     vertexShaderSource << "}\n";
2346 
2347     // Generate the fragment shader
2348     fragmentShaderSource.clear();
2349     fragmentShaderSource << "precision highp float;\n";
2350     fragmentShaderSource << varyingDeclaration;
2351     fragmentShaderSource << "\nvoid main() \n{ \n\tvec4 retColor = vec4(0,0,0,0);\n";
2352     unsigned int currentFSVarying = 0;
2353     // Make use of the vec4 varyings
2354     fragmentShaderSource << "\tretColor += ";
2355     for (GLint i = 0; i < vec4Count; i++)
2356     {
2357         fragmentShaderSource << GenerateVectorVaryingUseCode(1, currentFSVarying);
2358         currentFSVarying += 1;
2359     }
2360     fragmentShaderSource << "vec4(0.0, 0.0, 0.0, 0.0);\n";
2361     constexpr GLuint testValue = 234;
2362     fragmentShaderSource << "\tgl_FragColor = (retColor/vec4(" << std::to_string(currentFSVarying)
2363                          << ")) /255.0*" << std::to_string(testValue) << ".0;\n";
2364     fragmentShaderSource << "}\n";
2365 
2366     std::vector<std::string> tfVaryings = {"gl_Position", "gl_PointSize"};
2367     ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(program1, vertexShaderSource.str().c_str(),
2368                                         fragmentShaderSource.str().c_str(), tfVaryings,
2369                                         GL_INTERLEAVED_ATTRIBS);
2370 
2371     GLBuffer xfbBuffer;
2372     glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfbBuffer);
2373     glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 6 * (sizeof(float[4]) + sizeof(float)), nullptr,
2374                  GL_STATIC_DRAW);
2375 
2376     GLTransformFeedback xfb;
2377     glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, xfb);
2378     glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, xfbBuffer);
2379 
2380     glUseProgram(program1);
2381 
2382     const GLint positionLocation = glGetAttribLocation(program1, essl1_shaders::PositionAttrib());
2383     GLBuffer vertexBuffer;
2384     // need to shift half pixel to make sure the line covers the center of the pixel
2385     const Vector3 vertices[2] = {
2386         {-1.0f, -1.0f + 0.5f / static_cast<float>(getWindowHeight()), 0.0f},
2387         {1.0f, -1.0f + 0.5f / static_cast<float>(getWindowHeight()), 0.0f}};
2388     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
2389     glBufferData(GL_ARRAY_BUFFER, sizeof(*vertices) * 2, vertices, GL_STATIC_DRAW);
2390     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
2391     glEnableVertexAttribArray(positionLocation);
2392 
2393     glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
2394     glClear(GL_COLOR_BUFFER_BIT);
2395 
2396     glBeginTransformFeedback(GL_LINES);
2397     glDrawArrays(GL_LINES, 0, 2);
2398     glEndTransformFeedback();
2399 
2400     ASSERT_GL_NO_ERROR();
2401 
2402     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(testValue, testValue, testValue, testValue));
2403 }
2404 
2405 // Verify shader source with a fixed length that is less than the null-terminated length will
2406 // compile.
TEST_P(GLSLTest,FixedShaderLength)2407 TEST_P(GLSLTest, FixedShaderLength)
2408 {
2409     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
2410 
2411     const std::string appendGarbage = "abcdefghijklmnopqrstuvwxyz";
2412     const std::string source   = "void main() { gl_FragColor = vec4(0, 0, 0, 0); }" + appendGarbage;
2413     const char *sourceArray[1] = {source.c_str()};
2414     GLint lengths[1]           = {static_cast<GLint>(source.length() - appendGarbage.length())};
2415     glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
2416     glCompileShader(shader);
2417 
2418     GLint compileResult;
2419     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
2420     EXPECT_NE(compileResult, 0);
2421 }
2422 
2423 // Verify that a negative shader source length is treated as a null-terminated length.
TEST_P(GLSLTest,NegativeShaderLength)2424 TEST_P(GLSLTest, NegativeShaderLength)
2425 {
2426     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
2427 
2428     const char *sourceArray[1] = {essl1_shaders::fs::Red()};
2429     GLint lengths[1]           = {-10};
2430     glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
2431     glCompileShader(shader);
2432 
2433     GLint compileResult;
2434     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
2435     EXPECT_NE(compileResult, 0);
2436 }
2437 
2438 // Check that having an invalid char after the "." doesn't cause an assert.
TEST_P(GLSLTest,InvalidFieldFirstChar)2439 TEST_P(GLSLTest, InvalidFieldFirstChar)
2440 {
2441     GLuint shader      = glCreateShader(GL_VERTEX_SHADER);
2442     const char *source = "void main() {vec4 x; x.}";
2443     glShaderSource(shader, 1, &source, 0);
2444     glCompileShader(shader);
2445 
2446     GLint compileResult;
2447     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
2448     EXPECT_EQ(0, compileResult);
2449 }
2450 
2451 // Verify that a length array with mixed positive and negative values compiles.
TEST_P(GLSLTest,MixedShaderLengths)2452 TEST_P(GLSLTest, MixedShaderLengths)
2453 {
2454     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
2455 
2456     const char *sourceArray[] = {
2457         "void main()",
2458         "{",
2459         "    gl_FragColor = vec4(0, 0, 0, 0);",
2460         "}",
2461     };
2462     GLint lengths[] = {
2463         -10,
2464         1,
2465         static_cast<GLint>(strlen(sourceArray[2])),
2466         -1,
2467     };
2468     ASSERT_EQ(ArraySize(sourceArray), ArraySize(lengths));
2469 
2470     glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
2471     glCompileShader(shader);
2472 
2473     GLint compileResult;
2474     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
2475     EXPECT_NE(compileResult, 0);
2476 }
2477 
2478 // Verify that zero-length shader source does not affect shader compilation.
TEST_P(GLSLTest,ZeroShaderLength)2479 TEST_P(GLSLTest, ZeroShaderLength)
2480 {
2481     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
2482 
2483     const char *sourceArray[] = {
2484         "abcdefg", "34534", "void main() { gl_FragColor = vec4(0, 0, 0, 0); }", "", "abcdefghijklm",
2485     };
2486     GLint lengths[] = {
2487         0, 0, -1, 0, 0,
2488     };
2489     ASSERT_EQ(ArraySize(sourceArray), ArraySize(lengths));
2490 
2491     glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
2492     glCompileShader(shader);
2493 
2494     GLint compileResult;
2495     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
2496     EXPECT_NE(compileResult, 0);
2497 }
2498 
2499 // Tests that bad index expressions don't crash ANGLE's translator.
2500 // https://code.google.com/p/angleproject/issues/detail?id=857
TEST_P(GLSLTest,BadIndexBug)2501 TEST_P(GLSLTest, BadIndexBug)
2502 {
2503     constexpr char kFSSourceVec[] =
2504         "precision mediump float;\n"
2505         "uniform vec4 uniformVec;\n"
2506         "void main()\n"
2507         "{\n"
2508         "    gl_FragColor = vec4(uniformVec[int()]);\n"
2509         "}";
2510 
2511     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFSSourceVec);
2512     EXPECT_EQ(0u, shader);
2513 
2514     if (shader != 0)
2515     {
2516         glDeleteShader(shader);
2517     }
2518 
2519     constexpr char kFSSourceMat[] =
2520         "precision mediump float;\n"
2521         "uniform mat4 uniformMat;\n"
2522         "void main()\n"
2523         "{\n"
2524         "    gl_FragColor = vec4(uniformMat[int()]);\n"
2525         "}";
2526 
2527     shader = CompileShader(GL_FRAGMENT_SHADER, kFSSourceMat);
2528     EXPECT_EQ(0u, shader);
2529 
2530     if (shader != 0)
2531     {
2532         glDeleteShader(shader);
2533     }
2534 
2535     constexpr char kFSSourceArray[] =
2536         "precision mediump float;\n"
2537         "uniform vec4 uniformArray;\n"
2538         "void main()\n"
2539         "{\n"
2540         "    gl_FragColor = vec4(uniformArray[int()]);\n"
2541         "}";
2542 
2543     shader = CompileShader(GL_FRAGMENT_SHADER, kFSSourceArray);
2544     EXPECT_EQ(0u, shader);
2545 
2546     if (shader != 0)
2547     {
2548         glDeleteShader(shader);
2549     }
2550 }
2551 
2552 // Test that structs defined in uniforms are translated correctly.
TEST_P(GLSLTest,StructSpecifiersUniforms)2553 TEST_P(GLSLTest, StructSpecifiersUniforms)
2554 {
2555     constexpr char kFS[] = R"(precision mediump float;
2556 
2557 uniform struct S { float field; } s;
2558 
2559 void main()
2560 {
2561     gl_FragColor = vec4(1, 0, 0, 1);
2562     gl_FragColor.a += s.field;
2563 })";
2564 
2565     GLuint program = CompileProgram(essl1_shaders::vs::Simple(), kFS);
2566     EXPECT_NE(0u, program);
2567 }
2568 
2569 // Test that structs declaration followed directly by an initialization is translated correctly.
TEST_P(GLSLTest,StructWithInitializer)2570 TEST_P(GLSLTest, StructWithInitializer)
2571 {
2572     constexpr char kFS[] = R"(precision mediump float;
2573 
2574 struct S { float a; } s = S(1.0);
2575 
2576 void main()
2577 {
2578     gl_FragColor = vec4(0, 0, 0, 1);
2579     gl_FragColor.r += s.a;
2580 })";
2581 
2582     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
2583     glUseProgram(program);
2584 
2585     // Test drawing, should be red.
2586     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
2587 
2588     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2589     EXPECT_GL_NO_ERROR();
2590 }
2591 
2592 // Test that structs without initializer, followed by a uniform usage works as expected.
TEST_P(GLSLTest,UniformStructWithoutInitializer)2593 TEST_P(GLSLTest, UniformStructWithoutInitializer)
2594 {
2595     constexpr char kFS[] = R"(precision mediump float;
2596 
2597 struct S { float a; };
2598 uniform S u_s;
2599 
2600 void main()
2601 {
2602     gl_FragColor = vec4(u_s.a);
2603 })";
2604 
2605     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
2606     glUseProgram(program);
2607 
2608     // Test drawing, should be red.
2609     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
2610 
2611     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
2612     EXPECT_GL_NO_ERROR();
2613 }
2614 
2615 // Test that structs declaration followed directly by an initialization in a uniform.
TEST_P(GLSLTest,StructWithUniformInitializer)2616 TEST_P(GLSLTest, StructWithUniformInitializer)
2617 {
2618     constexpr char kFS[] = R"(precision mediump float;
2619 
2620 struct S { float a; } s = S(1.0);
2621 uniform S us;
2622 
2623 void main()
2624 {
2625     gl_FragColor = vec4(0, 0, 0, 1);
2626     gl_FragColor.r += s.a;
2627     gl_FragColor.g += us.a;
2628 })";
2629 
2630     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
2631     glUseProgram(program);
2632 
2633     // Test drawing, should be red.
2634     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
2635 
2636     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2637     EXPECT_GL_NO_ERROR();
2638 }
2639 
2640 // Test that gl_DepthRange is not stored as a uniform location. Since uniforms
2641 // beginning with "gl_" are filtered out by our validation logic, we must
2642 // bypass the validation to test the behaviour of the implementation.
2643 // (note this test is still Impl-independent)
TEST_P(GLSLTestNoValidation,DepthRangeUniforms)2644 TEST_P(GLSLTestNoValidation, DepthRangeUniforms)
2645 {
2646     constexpr char kFS[] = R"(precision mediump float;
2647 
2648 void main()
2649 {
2650     gl_FragColor = vec4(gl_DepthRange.near, gl_DepthRange.far, gl_DepthRange.diff, 1);
2651 })";
2652 
2653     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
2654 
2655     // We need to bypass validation for this call.
2656     GLint nearIndex = glGetUniformLocation(program.get(), "gl_DepthRange.near");
2657     EXPECT_EQ(-1, nearIndex);
2658 
2659     // Test drawing does not throw an exception.
2660     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
2661 
2662     EXPECT_GL_NO_ERROR();
2663 }
2664 
GenerateSmallPowShader(double base,double exponent)2665 std::string GenerateSmallPowShader(double base, double exponent)
2666 {
2667     std::stringstream stream;
2668 
2669     stream.precision(8);
2670 
2671     double result = pow(base, exponent);
2672 
2673     stream << "precision highp float;\n"
2674            << "float fun(float arg)\n"
2675            << "{\n"
2676            << "    return pow(arg, " << std::fixed << exponent << ");\n"
2677            << "}\n"
2678            << "\n"
2679            << "void main()\n"
2680            << "{\n"
2681            << "    const float a = " << std::scientific << base << ";\n"
2682            << "    float b = fun(a);\n"
2683            << "    if (abs(" << result << " - b) < " << std::abs(result * 0.001) << ")\n"
2684            << "    {\n"
2685            << "        gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
2686            << "    }\n"
2687            << "    else\n"
2688            << "    {\n"
2689            << "        gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
2690            << "    }\n"
2691            << "}\n";
2692 
2693     return stream.str();
2694 }
2695 
2696 // Covers the WebGL test 'glsl/bugs/pow-of-small-constant-in-user-defined-function'
2697 // See http://anglebug.com/851
TEST_P(GLSLTest,PowOfSmallConstant)2698 TEST_P(GLSLTest, PowOfSmallConstant)
2699 {
2700     // Test with problematic exponents that are close to an integer.
2701     std::vector<double> testExponents;
2702     std::array<double, 5> epsilonMultipliers = {-100.0, -1.0, 0.0, 1.0, 100.0};
2703     for (double epsilonMultiplier : epsilonMultipliers)
2704     {
2705         for (int i = -4; i <= 5; ++i)
2706         {
2707             if (i >= -1 && i <= 1)
2708                 continue;
2709             const double epsilon = 1.0e-8;
2710             double bad           = static_cast<double>(i) + epsilonMultiplier * epsilon;
2711             testExponents.push_back(bad);
2712         }
2713     }
2714 
2715     // Also test with a few exponents that are not close to an integer.
2716     testExponents.push_back(3.6);
2717     testExponents.push_back(3.4);
2718 
2719     for (double testExponent : testExponents)
2720     {
2721         const std::string &fragmentShaderSource = GenerateSmallPowShader(1.0e-6, testExponent);
2722 
2723         ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), fragmentShaderSource.c_str());
2724 
2725         drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
2726 
2727         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2728         EXPECT_GL_NO_ERROR();
2729     }
2730 }
2731 
2732 // Test fragment shaders which contain non-constant loop indexers
TEST_P(GLSLTest,LoopIndexingValidation)2733 TEST_P(GLSLTest, LoopIndexingValidation)
2734 {
2735     constexpr char kFS[] = R"(precision mediump float;
2736 
2737 uniform float loopMax;
2738 
2739 void main()
2740 {
2741     gl_FragColor = vec4(1, 0, 0, 1);
2742     for (float l = 0.0; l < loopMax; l++)
2743     {
2744         if (loopMax > 3.0)
2745         {
2746             gl_FragColor.a += 0.1;
2747         }
2748     }
2749 })";
2750 
2751     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
2752 
2753     const char *sourceArray[1] = {kFS};
2754     glShaderSource(shader, 1, sourceArray, nullptr);
2755     glCompileShader(shader);
2756 
2757     GLint compileResult;
2758     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
2759 
2760     // If the test is configured to run limited to Feature Level 9_3, then it is
2761     // assumed that shader compilation will fail with an expected error message containing
2762     // "Loop index cannot be compared with non-constant expression"
2763     if (GetParam() == ES2_D3D9())
2764     {
2765         if (compileResult != 0)
2766         {
2767             FAIL() << "Shader compilation succeeded, expected failure";
2768         }
2769         else
2770         {
2771             GLint infoLogLength;
2772             glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
2773 
2774             std::string infoLog;
2775             infoLog.resize(infoLogLength);
2776             glGetShaderInfoLog(shader, static_cast<GLsizei>(infoLog.size()), nullptr, &infoLog[0]);
2777 
2778             if (infoLog.find("Loop index cannot be compared with non-constant expression") ==
2779                 std::string::npos)
2780             {
2781                 FAIL() << "Shader compilation failed with unexpected error message";
2782             }
2783         }
2784     }
2785     else
2786     {
2787         EXPECT_NE(0, compileResult);
2788     }
2789 
2790     if (shader != 0)
2791     {
2792         glDeleteShader(shader);
2793     }
2794 }
2795 
2796 // Tests that the maximum uniforms count returned from querying GL_MAX_VERTEX_UNIFORM_VECTORS
2797 // can actually be used.
TEST_P(GLSLTest,VerifyMaxVertexUniformVectors)2798 TEST_P(GLSLTest, VerifyMaxVertexUniformVectors)
2799 {
2800     // crbug.com/680631
2801     ANGLE_SKIP_TEST_IF(IsOzone() && IsIntel());
2802 
2803     int maxUniforms = 10000;
2804     glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
2805     EXPECT_GL_NO_ERROR();
2806     std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS = " << maxUniforms << std::endl;
2807 
2808     CompileGLSLWithUniformsAndSamplers(maxUniforms, 0, 0, 0, true);
2809 }
2810 
2811 // Tests that the maximum uniforms count returned from querying GL_MAX_VERTEX_UNIFORM_VECTORS
2812 // can actually be used along with the maximum number of texture samplers.
TEST_P(GLSLTest,VerifyMaxVertexUniformVectorsWithSamplers)2813 TEST_P(GLSLTest, VerifyMaxVertexUniformVectorsWithSamplers)
2814 {
2815     ANGLE_SKIP_TEST_IF(IsOpenGL() || IsOpenGLES());
2816 
2817     // Times out on D3D11 on test infra. http://anglebug.com/5076
2818     ANGLE_SKIP_TEST_IF(IsD3D11() && IsIntel());
2819 
2820     int maxUniforms = 10000;
2821     glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
2822     EXPECT_GL_NO_ERROR();
2823     std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS = " << maxUniforms << std::endl;
2824 
2825     int maxTextureImageUnits = 0;
2826     glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
2827 
2828     CompileGLSLWithUniformsAndSamplers(maxUniforms, 0, maxTextureImageUnits, 0, true);
2829 }
2830 
2831 // Tests that the maximum uniforms count + 1 from querying GL_MAX_VERTEX_UNIFORM_VECTORS
2832 // fails shader compilation.
TEST_P(GLSLTest,VerifyMaxVertexUniformVectorsExceeded)2833 TEST_P(GLSLTest, VerifyMaxVertexUniformVectorsExceeded)
2834 {
2835     int maxUniforms = 10000;
2836     glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
2837     EXPECT_GL_NO_ERROR();
2838     std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS + 1 = " << maxUniforms + 1 << std::endl;
2839 
2840     CompileGLSLWithUniformsAndSamplers(maxUniforms + 1, 0, 0, 0, false);
2841 }
2842 
2843 // Tests that the maximum uniforms count returned from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
2844 // can actually be used.
TEST_P(GLSLTest,VerifyMaxFragmentUniformVectors)2845 TEST_P(GLSLTest, VerifyMaxFragmentUniformVectors)
2846 {
2847     // crbug.com/680631
2848     ANGLE_SKIP_TEST_IF(IsOzone() && IsIntel());
2849 
2850     int maxUniforms = 10000;
2851     glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
2852     EXPECT_GL_NO_ERROR();
2853     std::cout << "Validating GL_MAX_FRAGMENT_UNIFORM_VECTORS = " << maxUniforms << std::endl;
2854 
2855     CompileGLSLWithUniformsAndSamplers(0, maxUniforms, 0, 0, true);
2856 }
2857 
2858 // Tests that the maximum uniforms count returned from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
2859 // can actually be used along with the maximum number of texture samplers.
TEST_P(GLSLTest,VerifyMaxFragmentUniformVectorsWithSamplers)2860 TEST_P(GLSLTest, VerifyMaxFragmentUniformVectorsWithSamplers)
2861 {
2862     ANGLE_SKIP_TEST_IF(IsOpenGL() || IsOpenGLES());
2863 
2864     int maxUniforms = 10000;
2865     glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
2866     EXPECT_GL_NO_ERROR();
2867 
2868     int maxTextureImageUnits = 0;
2869     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
2870 
2871     CompileGLSLWithUniformsAndSamplers(0, maxUniforms, 0, maxTextureImageUnits, true);
2872 }
2873 
2874 // Tests that the maximum uniforms count + 1 from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
2875 // fails shader compilation.
TEST_P(GLSLTest,VerifyMaxFragmentUniformVectorsExceeded)2876 TEST_P(GLSLTest, VerifyMaxFragmentUniformVectorsExceeded)
2877 {
2878     int maxUniforms = 10000;
2879     glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
2880     EXPECT_GL_NO_ERROR();
2881     std::cout << "Validating GL_MAX_FRAGMENT_UNIFORM_VECTORS + 1 = " << maxUniforms + 1
2882               << std::endl;
2883 
2884     CompileGLSLWithUniformsAndSamplers(0, maxUniforms + 1, 0, 0, false);
2885 }
2886 
2887 // Test compiling shaders using the GL_EXT_shader_texture_lod extension
TEST_P(GLSLTest,TextureLOD)2888 TEST_P(GLSLTest, TextureLOD)
2889 {
2890     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_texture_lod"));
2891 
2892     constexpr char kFS[] =
2893         "#extension GL_EXT_shader_texture_lod : require\n"
2894         "uniform sampler2D u_texture;\n"
2895         "void main() {\n"
2896         "    gl_FragColor = texture2DGradEXT(u_texture, vec2(0.0, 0.0), vec2(0.0, 0.0), vec2(0.0, "
2897         "0.0));\n"
2898         "}\n";
2899 
2900     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
2901     ASSERT_NE(0u, shader);
2902     glDeleteShader(shader);
2903 }
2904 
2905 // HLSL generates extra lod0 variants of functions. There was a bug that incorrectly reworte
2906 // function calls to use them in vertex shaders.  http://anglebug.com/3471
TEST_P(GLSLTest,TextureLODRewriteInVertexShader)2907 TEST_P(GLSLTest, TextureLODRewriteInVertexShader)
2908 {
2909     constexpr char kVS[] = R"(
2910   precision highp float;
2911   uniform int uni;
2912   uniform sampler2D texture;
2913 
2914   vec4 A();
2915 
2916   vec4 B() {
2917     vec4 a;
2918     for(int r=0; r<14; r++){
2919       if (r < uni) return vec4(0.0);
2920       a = A();
2921     }
2922     return a;
2923   }
2924 
2925   vec4 A() {
2926     return texture2D(texture, vec2(0.0, 0.0));
2927   }
2928 
2929   void main() {
2930     gl_Position = B();
2931   })";
2932 
2933     constexpr char kFS[] = R"(
2934 void main() { gl_FragColor = vec4(gl_FragCoord.x / 640.0, gl_FragCoord.y / 480.0, 0, 1); }
2935 )";
2936 
2937     ANGLE_GL_PROGRAM(program, kVS, kFS);
2938 }
2939 
2940 // Test to verify the a shader can have a sampler unused in a vertex shader
2941 // but used in the fragment shader.
TEST_P(GLSLTest,VerifySamplerInBothVertexAndFragmentShaders)2942 TEST_P(GLSLTest, VerifySamplerInBothVertexAndFragmentShaders)
2943 {
2944     constexpr char kVS[] = R"(
2945 attribute vec2 position;
2946 varying mediump vec2 texCoord;
2947 uniform sampler2D tex;
2948 void main()
2949 {
2950     gl_Position = vec4(position, 0, 1);
2951     texCoord = position * 0.5 + vec2(0.5);
2952 })";
2953 
2954     constexpr char kFS[] = R"(
2955 varying mediump vec2 texCoord;
2956 uniform sampler2D tex;
2957 void main()
2958 {
2959     gl_FragColor = texture2D(tex, texCoord);
2960 })";
2961 
2962     ANGLE_GL_PROGRAM(program, kVS, kFS);
2963 
2964     // Initialize basic red texture.
2965     const std::vector<GLColor> redColors(4, GLColor::red);
2966     GLTexture texture;
2967     glBindTexture(GL_TEXTURE_2D, texture);
2968     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, redColors.data());
2969     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2970     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2971     ASSERT_GL_NO_ERROR();
2972 
2973     drawQuad(program, "position", 0.0f);
2974 
2975     EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::red);
2976 }
2977 
2978 // Test that array of structs containing array of samplers work as expected.
TEST_P(GLSLTest,ArrayOfStructContainingArrayOfSamplers)2979 TEST_P(GLSLTest, ArrayOfStructContainingArrayOfSamplers)
2980 {
2981     constexpr char kFS[] =
2982         "precision mediump float;\n"
2983         "struct Data { mediump sampler2D data[2]; };\n"
2984         "uniform Data test[2];\n"
2985         "void main() {\n"
2986         "    gl_FragColor = vec4(texture2D(test[1].data[1], vec2(0.0, 0.0)).r,\n"
2987         "                        texture2D(test[1].data[0], vec2(0.0, 0.0)).r,\n"
2988         "                        texture2D(test[0].data[1], vec2(0.0, 0.0)).r,\n"
2989         "                        texture2D(test[0].data[0], vec2(0.0, 0.0)).r);\n"
2990         "}\n";
2991 
2992     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
2993     glUseProgram(program.get());
2994     GLTexture textures[4];
2995     GLColor expected = MakeGLColor(32, 64, 96, 255);
2996     GLubyte data[8]  = {};  // 4 bytes of padding, so that texture can be initialized with 4 bytes
2997     memcpy(data, expected.data(), sizeof(expected));
2998     for (int i = 0; i < 4; i++)
2999     {
3000         int outerIdx = i % 2;
3001         int innerIdx = i / 2;
3002         glActiveTexture(GL_TEXTURE0 + i);
3003         glBindTexture(GL_TEXTURE_2D, textures[i]);
3004         // Each element provides two components.
3005         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data + i);
3006         std::stringstream uniformName;
3007         uniformName << "test[" << innerIdx << "].data[" << outerIdx << "]";
3008         // Then send it as a uniform
3009         GLint uniformLocation = glGetUniformLocation(program.get(), uniformName.str().c_str());
3010         // The uniform should be active.
3011         EXPECT_NE(uniformLocation, -1);
3012 
3013         glUniform1i(uniformLocation, 3 - i);
3014     }
3015     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
3016     EXPECT_PIXEL_COLOR_EQ(0, 0, expected);
3017 }
3018 
3019 // Test that if a non-preprocessor token is seen in a disabled if-block then it does not disallow
3020 // extension pragmas later
TEST_P(GLSLTest,NonPreprocessorTokensInIfBlocks)3021 TEST_P(GLSLTest, NonPreprocessorTokensInIfBlocks)
3022 {
3023     constexpr const char *kFS = R"(
3024 #if __VERSION__ >= 300
3025     inout mediump vec4 fragData;
3026 #else
3027     #extension GL_EXT_shader_texture_lod :enable
3028 #endif
3029 
3030 void main()
3031 {
3032 }
3033     )";
3034 
3035     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
3036     EXPECT_NE(0u, shader);
3037 }
3038 
3039 // Test that two constructors which have vec4 and mat2 parameters get disambiguated (issue in
3040 // HLSL).
TEST_P(GLSLTest_ES3,AmbiguousConstructorCall2x2)3041 TEST_P(GLSLTest_ES3, AmbiguousConstructorCall2x2)
3042 {
3043     constexpr char kVS[] =
3044         "#version 300 es\n"
3045         "precision highp float;\n"
3046         "in vec4 a_vec;\n"
3047         "in mat2 a_mat;\n"
3048         "void main()\n"
3049         "{\n"
3050         "    gl_Position = vec4(a_vec) + vec4(a_mat);\n"
3051         "}";
3052 
3053     GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
3054     EXPECT_NE(0u, program);
3055 }
3056 
3057 // Test that two constructors which have mat2x3 and mat3x2 parameters get disambiguated.
3058 // This was suspected to be an issue in HLSL, but HLSL seems to be able to natively choose between
3059 // the function signatures in this case.
TEST_P(GLSLTest_ES3,AmbiguousConstructorCall2x3)3060 TEST_P(GLSLTest_ES3, AmbiguousConstructorCall2x3)
3061 {
3062     constexpr char kVS[] =
3063         "#version 300 es\n"
3064         "precision highp float;\n"
3065         "in mat3x2 a_matA;\n"
3066         "in mat2x3 a_matB;\n"
3067         "void main()\n"
3068         "{\n"
3069         "    gl_Position = vec4(a_matA) + vec4(a_matB);\n"
3070         "}";
3071 
3072     GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
3073     EXPECT_NE(0u, program);
3074 }
3075 
3076 // Test that two functions which have vec4 and mat2 parameters get disambiguated (issue in HLSL).
TEST_P(GLSLTest_ES3,AmbiguousFunctionCall2x2)3077 TEST_P(GLSLTest_ES3, AmbiguousFunctionCall2x2)
3078 {
3079     constexpr char kVS[] =
3080         "#version 300 es\n"
3081         "precision highp float;\n"
3082         "in vec4 a_vec;\n"
3083         "in mat2 a_mat;\n"
3084         "vec4 foo(vec4 a)\n"
3085         "{\n"
3086         "    return a;\n"
3087         "}\n"
3088         "vec4 foo(mat2 a)\n"
3089         "{\n"
3090         "    return vec4(a[0][0]);\n"
3091         "}\n"
3092         "void main()\n"
3093         "{\n"
3094         "    gl_Position = foo(a_vec) + foo(a_mat);\n"
3095         "}";
3096 
3097     GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
3098     EXPECT_NE(0u, program);
3099 }
3100 
3101 // Test that constructing matrices from non-float types works.
TEST_P(GLSLTest_ES3,ConstructMatrixFromNonFloat)3102 TEST_P(GLSLTest_ES3, ConstructMatrixFromNonFloat)
3103 {
3104     constexpr char kFS[] = R"(#version 300 es
3105 precision highp float;
3106 out vec4 color;
3107 
3108 uniform int i;
3109 uniform uint u;
3110 uniform bool b;
3111 
3112 void main()
3113 {
3114     mat3x2 mi = mat3x2(i);
3115     mat4 mu = mat4(u);
3116     mat2x4 mb = mat2x4(b);
3117 
3118     mat3x2 m = mat3x2(ivec2(i), uvec2(u), bvec2(b));
3119 
3120     color = vec4(mi[0][0] == float(i) ? 1 : 0,
3121                  mu[2][2] == float(u) ? 1 : 0,
3122                  mb[1][1] == float(b) ? 1 : 0,
3123                  m[0][1] == float(i) && m[1][0] == float(u) && m[2][0] == float(b) ? 1 : 0);
3124 })";
3125 
3126     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3127     glUseProgram(program);
3128 
3129     GLint iloc = glGetUniformLocation(program, "i");
3130     GLint uloc = glGetUniformLocation(program, "u");
3131     GLint bloc = glGetUniformLocation(program, "b");
3132     ASSERT_NE(iloc, -1);
3133     ASSERT_NE(uloc, -1);
3134     ASSERT_NE(bloc, -1);
3135     glUniform1i(iloc, -123);
3136     glUniform1ui(uloc, 456);
3137     glUniform1ui(bloc, 1);
3138 
3139     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3140     EXPECT_GL_NO_ERROR();
3141 
3142     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
3143 }
3144 
3145 // Test that constructing vectors from non-float types works.
TEST_P(GLSLTest_ES3,ConstructVectorFromNonFloat)3146 TEST_P(GLSLTest_ES3, ConstructVectorFromNonFloat)
3147 {
3148     constexpr char kFS[] = R"(#version 300 es
3149 precision highp float;
3150 out vec4 color;
3151 
3152 uniform ivec2 i;
3153 uniform uvec2 u;
3154 uniform bvec2 b;
3155 
3156 void main()
3157 {
3158     vec2 v2 = vec2(i.x, b);
3159     vec3 v3 = vec3(b, u);
3160     vec4 v4 = vec4(i, u);
3161 
3162     color = vec4(v2.x == float(i.x) && v2.y == float(b.x) ? 1 : 0,
3163                  v3.x == float(b.x) && v3.y == float(b.y) && v3.z == float(u.x) ? 1 : 0,
3164                  v4.x == float(i.x) && v4.y == float(i.y) && v4.z == float(u.x) && v4.w == float(u.y) ? 1 : 0,
3165                  1);
3166 })";
3167 
3168     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3169     glUseProgram(program);
3170 
3171     GLint iloc = glGetUniformLocation(program, "i");
3172     GLint uloc = glGetUniformLocation(program, "u");
3173     GLint bloc = glGetUniformLocation(program, "b");
3174     ASSERT_NE(iloc, -1);
3175     ASSERT_NE(uloc, -1);
3176     ASSERT_NE(bloc, -1);
3177     glUniform2i(iloc, -123, -23);
3178     glUniform2ui(uloc, 456, 76);
3179     glUniform2ui(bloc, 1, 0);
3180 
3181     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3182     EXPECT_GL_NO_ERROR();
3183 
3184     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
3185 }
3186 
3187 // Test that constructing non-float vectors from matrix types works.
TEST_P(GLSLTest_ES3,ConstructNonFloatVectorFromMatrix)3188 TEST_P(GLSLTest_ES3, ConstructNonFloatVectorFromMatrix)
3189 {
3190     constexpr char kFS[] = R"(#version 300 es
3191 precision highp float;
3192 out vec4 color;
3193 
3194 uniform float f;
3195 
3196 void main()
3197 {
3198     mat4 m = mat4(f);
3199     ivec3 vi = ivec3(m);
3200     uvec2 vu = uvec2(m);
3201     bvec4 vb = bvec4(m);
3202     bvec2 vb2 = bvec2(vi.x, m);
3203 
3204     color = vec4(vi.x == int(f) ? 1 : 0,
3205                  vu.x == uint(f) ? 1 : 0,
3206                  vb.x == bool(f) ? 1 : 0,
3207                  vb2.x == bool(f) && vb2.y == bool(f) ? 1 : 0);
3208 })";
3209 
3210     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3211     glUseProgram(program);
3212 
3213     GLint floc = glGetUniformLocation(program, "f");
3214     ASSERT_NE(floc, -1);
3215     glUniform1f(floc, 123);
3216 
3217     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3218     EXPECT_GL_NO_ERROR();
3219 
3220     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
3221 }
3222 
3223 // Test that == and != for vector and matrix types work.
TEST_P(GLSLTest_ES3,NonScalarEqualOperator)3224 TEST_P(GLSLTest_ES3, NonScalarEqualOperator)
3225 {
3226     constexpr char kFS[] = R"(#version 300 es
3227 precision highp float;
3228 out vec4 color;
3229 
3230 uniform float f;
3231 uniform int i;
3232 uniform uint u;
3233 
3234 void main()
3235 {
3236     mat3x2 m32_1 = mat3x2(vec2(f), vec2(i), vec2(u));
3237     mat3x2 m32_2 = mat3x2(m32_1);
3238     mat3x2 m32_3 = mat3x2(vec2(i), vec2(u), vec2(f));
3239     mat2x3 m23_1 = mat2x3(vec3(f), vec3(i));
3240     mat2x3 m23_2 = mat2x3(m23_1);
3241     mat2x3 m23_3 = mat2x3(vec3(i), vec3(u));
3242     vec2 v2_1 = m32_1[0];
3243     vec2 v2_2 = m32_2[0];
3244     ivec3 v3_1 = ivec3(transpose(m32_1)[0]);
3245     ivec3 v3_2 = ivec3(transpose(m32_2)[0]);
3246     uvec4 v4_1 = uvec4(m32_1[1], m32_1[2]);
3247     uvec4 v4_2 = uvec4(m32_2[1], m32_2[2]);
3248 
3249     color = vec4((m32_1 == m32_2 ? 0.5 : 0.0) + (m23_1 == m23_2 ? 0.5 : 0.0),
3250                  v2_1 == v2_2 ? 1 : 0,
3251                  (v3_1 == v3_2 ? 0.5 : 0.0) +
3252                     (v4_1 == v4_2 ? 0.5 : 0.0),
3253                  (m32_1 != m32_3 ? 0.125 : 0.0) +
3254                     (m23_1 != m23_3 ? 0.125 : 0.0) +
3255                     (v2_1 != vec2(v3_2) ? 0.25 : 0.0) +
3256                     (v3_1 != ivec3(v4_2) ? 0.25 : 0.0) +
3257                     (v4_1 != uvec4(v2_1, v2_2) ? 0.25 : 0.0));
3258 })";
3259 
3260     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3261     glUseProgram(program);
3262 
3263     GLint floc = glGetUniformLocation(program, "f");
3264     GLint iloc = glGetUniformLocation(program, "i");
3265     GLint uloc = glGetUniformLocation(program, "u");
3266     ASSERT_NE(floc, -1);
3267     ASSERT_NE(iloc, -1);
3268     ASSERT_NE(uloc, -1);
3269     glUniform1f(floc, 1.5);
3270     glUniform1i(iloc, -123);
3271     glUniform1ui(uloc, 456);
3272 
3273     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3274     EXPECT_GL_NO_ERROR();
3275 
3276     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
3277 }
3278 
3279 // Test that == and != for structs and array types work.
TEST_P(GLSLTest_ES31,StructAndArrayEqualOperator)3280 TEST_P(GLSLTest_ES31, StructAndArrayEqualOperator)
3281 {
3282     constexpr char kFS[] = R"(#version 310 es
3283 precision highp float;
3284 out vec4 color;
3285 
3286 uniform float f;
3287 uniform int i;
3288 uniform uint u;
3289 
3290 struct S
3291 {
3292     float f;
3293     int i;
3294     uint u;
3295     vec4 v;
3296     ivec3 iv;
3297     uvec2 uv;
3298     mat3x2 m32;
3299     mat2x3 m23;
3300     float fa[3][4][5];
3301     int ia[4];
3302     uint ua[6][2];
3303 };
3304 
3305 struct T
3306 {
3307     S s1;
3308     S s2[3][2];
3309 };
3310 
3311 void main()
3312 {
3313     float fa[5] = float[5](f, f, f, f, f);
3314     int ia[4] = int[4](i, i, i, i);
3315     uint ua[2] = uint[2](u, u);
3316 
3317     S s1 = S(f, i, u, vec4(f), ivec3(i), uvec2(u),
3318              mat3x2(vec2(f), vec2(i), vec2(u)),
3319              mat2x3(vec3(f), vec3(i)),
3320              float[3][4][5](
3321                             float[4][5](fa, fa, fa, fa),
3322                             float[4][5](fa, fa, fa, fa),
3323                             float[4][5](fa, fa, fa, fa)),
3324              ia,
3325              uint[6][2](ua, ua, ua, ua, ua, ua));
3326 
3327     S s2[2] = S[2](s1, s1);
3328     s2[1].fa[0][1][2] = float(i);
3329 
3330     T t1 = T(s1, S[3][2](s2, s2, s2));
3331     T t2 = T(s2[1], S[3][2](s2, s2, s2));
3332 
3333     T ta1[2] = T[2](t1, t2);
3334     T ta2[2] = T[2](t1, t2);
3335     T ta3[2] = T[2](t2, t1);
3336 
3337     color = vec4((s1 == s2[0] ? 0.5 : 0.0) + (s1 != s2[1] ? 0.5 : 0.0),
3338                  (s1.fa[0] == s2[0].fa[0] ? 0.5 : 0.0) + (s1.fa[0] != s2[1].fa[0] ? 0.5 : 0.0),
3339                  (ta1[0] == t1 ? 0.5 : 0.0) + (ta1[1] != t1 ? 0.5 : 0.0),
3340                  (ta1 == ta2 ? 0.5 : 0.0) + (ta1 != ta3 ? 0.5 : 0.0));
3341 })";
3342 
3343     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
3344     glUseProgram(program);
3345 
3346     GLint floc = glGetUniformLocation(program, "f");
3347     GLint iloc = glGetUniformLocation(program, "i");
3348     GLint uloc = glGetUniformLocation(program, "u");
3349     ASSERT_NE(floc, -1);
3350     ASSERT_NE(iloc, -1);
3351     ASSERT_NE(uloc, -1);
3352     glUniform1f(floc, 1.5);
3353     glUniform1i(iloc, -123);
3354     glUniform1ui(uloc, 456);
3355 
3356     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3357     EXPECT_GL_NO_ERROR();
3358 
3359     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
3360 }
3361 
3362 // Test that an user-defined function with a large number of float4 parameters doesn't fail due to
3363 // the function name being too long.
TEST_P(GLSLTest_ES3,LargeNumberOfFloat4Parameters)3364 TEST_P(GLSLTest_ES3, LargeNumberOfFloat4Parameters)
3365 {
3366     std::stringstream vertexShaderStream;
3367     // Note: SPIR-V doesn't allow more than 255 parameters to a function.
3368     const unsigned int paramCount = (IsVulkan() || IsMetal()) ? 255u : 1024u;
3369 
3370     vertexShaderStream << "#version 300 es\n"
3371                           "precision highp float;\n"
3372                           "in vec4 a_vec;\n"
3373                           "vec4 lotsOfVec4Parameters(";
3374     for (unsigned int i = 0; i < paramCount - 1; ++i)
3375     {
3376         vertexShaderStream << "vec4 a" << i << ", ";
3377     }
3378     vertexShaderStream << "vec4 aLast)\n"
3379                           "{\n"
3380                           "    vec4 sum = vec4(0.0, 0.0, 0.0, 0.0);\n";
3381     for (unsigned int i = 0; i < paramCount - 1; ++i)
3382     {
3383         vertexShaderStream << "    sum += a" << i << ";\n";
3384     }
3385     vertexShaderStream << "    sum += aLast;\n"
3386                           "    return sum;\n "
3387                           "}\n"
3388                           "void main()\n"
3389                           "{\n"
3390                           "    gl_Position = lotsOfVec4Parameters(";
3391     for (unsigned int i = 0; i < paramCount - 1; ++i)
3392     {
3393         vertexShaderStream << "a_vec, ";
3394     }
3395     vertexShaderStream << "a_vec);\n"
3396                           "}";
3397 
3398     GLuint program = CompileProgram(vertexShaderStream.str().c_str(), essl3_shaders::fs::Red());
3399     EXPECT_NE(0u, program);
3400 }
3401 
3402 // This test was written specifically to stress DeferGlobalInitializers AST transformation.
3403 // Test a shader where a global constant array is initialized with an expression containing array
3404 // indexing. This initializer is tricky to constant fold, so if it's not constant folded it needs to
3405 // be handled in a way that doesn't generate statements in the global scope in HLSL output.
3406 // Also includes multiple array initializers in one declaration, where only the second one has
3407 // array indexing. This makes sure that the qualifier for the declaration is set correctly if
3408 // transformations are applied to the declaration also in the case of ESSL output.
TEST_P(GLSLTest_ES3,InitGlobalArrayWithArrayIndexing)3409 TEST_P(GLSLTest_ES3, InitGlobalArrayWithArrayIndexing)
3410 {
3411     // TODO(ynovikov): re-enable once root cause of http://anglebug.com/1428 is fixed
3412     ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
3413 
3414     constexpr char kFS[] =
3415         "#version 300 es\n"
3416         "precision highp float;\n"
3417         "out vec4 my_FragColor;\n"
3418         "const highp float f[2] = float[2](0.1, 0.2);\n"
3419         "const highp float[2] g = float[2](0.3, 0.4), h = float[2](0.5, f[1]);\n"
3420         "void main()\n"
3421         "{\n"
3422         "    my_FragColor = vec4(h[1]);\n"
3423         "}";
3424 
3425     GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS);
3426     EXPECT_NE(0u, program);
3427 }
3428 
3429 // Test that index-constant sampler array indexing is supported.
TEST_P(GLSLTest,IndexConstantSamplerArrayIndexing)3430 TEST_P(GLSLTest, IndexConstantSamplerArrayIndexing)
3431 {
3432     constexpr char kFS[] =
3433         "precision mediump float;\n"
3434         "uniform sampler2D uni[2];\n"
3435         "\n"
3436         "float zero(int x)\n"
3437         "{\n"
3438         "    return float(x) - float(x);\n"
3439         "}\n"
3440         "\n"
3441         "void main()\n"
3442         "{\n"
3443         "    vec4 c = vec4(0,0,0,0);\n"
3444         "    for (int ii = 1; ii < 3; ++ii) {\n"
3445         "        if (c.x > 255.0) {\n"
3446         "            c.x = 255.0 + zero(ii);\n"
3447         "            break;\n"
3448         "        }\n"
3449         // Index the sampler array with a predictable loop index (index-constant) as opposed to
3450         // a true constant. This is valid in OpenGL ES but isn't in many Desktop OpenGL versions,
3451         // without an extension.
3452         "        c += texture2D(uni[ii - 1], vec2(0.5, 0.5));\n"
3453         "    }\n"
3454         "    gl_FragColor = c;\n"
3455         "}";
3456 
3457     GLuint program = CompileProgram(essl1_shaders::vs::Simple(), kFS);
3458     EXPECT_NE(0u, program);
3459 }
3460 
3461 // Test that the #pragma directive is supported and doesn't trigger a compilation failure on the
3462 // native driver. The only pragma that gets passed to the OpenGL driver is "invariant" but we don't
3463 // want to test its behavior, so don't use any varyings.
TEST_P(GLSLTest,PragmaDirective)3464 TEST_P(GLSLTest, PragmaDirective)
3465 {
3466     constexpr char kVS[] =
3467         "#pragma STDGL invariant(all)\n"
3468         "void main()\n"
3469         "{\n"
3470         "    gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
3471         "}\n";
3472 
3473     GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
3474     EXPECT_NE(0u, program);
3475 }
3476 
3477 // Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
3478 // The function call that returns the array needs to be evaluated after ++j for the expression to
3479 // return the correct value (true).
TEST_P(GLSLTest_ES3,SequenceOperatorEvaluationOrderArray)3480 TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderArray)
3481 {
3482     constexpr char kFS[] =
3483         "#version 300 es\n"
3484         "precision mediump float;\n"
3485         "out vec4 my_FragColor; \n"
3486         "int[2] func(int param) {\n"
3487         "    return int[2](param, param);\n"
3488         "}\n"
3489         "void main() {\n"
3490         "    int a[2]; \n"
3491         "    for (int i = 0; i < 2; ++i) {\n"
3492         "        a[i] = 1;\n"
3493         "    }\n"
3494         "    int j = 0; \n"
3495         "    bool result = ((++j), (a == func(j)));\n"
3496         "    my_FragColor = vec4(0.0, (result ? 1.0 : 0.0), 0.0, 1.0);\n"
3497         "}\n";
3498 
3499     GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS);
3500     ASSERT_NE(0u, program);
3501 
3502     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3503 
3504     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3505 }
3506 
3507 // Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
3508 // The short-circuiting expression needs to be evaluated after ++j for the expression to return the
3509 // correct value (true).
TEST_P(GLSLTest_ES3,SequenceOperatorEvaluationOrderShortCircuit)3510 TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderShortCircuit)
3511 {
3512     constexpr char kFS[] =
3513         "#version 300 es\n"
3514         "precision mediump float;\n"
3515         "out vec4 my_FragColor; \n"
3516         "void main() {\n"
3517         "    int j = 0; \n"
3518         "    bool result = ((++j), (j == 1 ? true : (++j == 3)));\n"
3519         "    my_FragColor = vec4(0.0, ((result && j == 1) ? 1.0 : 0.0), 0.0, 1.0);\n"
3520         "}\n";
3521 
3522     GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS);
3523     ASSERT_NE(0u, program);
3524 
3525     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3526 
3527     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3528 }
3529 
3530 // Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
3531 // Indexing the vector needs to be evaluated after func() for the right result.
TEST_P(GLSLTest_ES3,SequenceOperatorEvaluationOrderDynamicVectorIndexingInLValue)3532 TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderDynamicVectorIndexingInLValue)
3533 {
3534     constexpr char kFS[] =
3535         "#version 300 es\n"
3536         "precision mediump float;\n"
3537         "out vec4 my_FragColor;\n"
3538         "uniform int u_zero;\n"
3539         "int sideEffectCount = 0;\n"
3540         "float func() {\n"
3541         "    ++sideEffectCount;\n"
3542         "    return -1.0;\n"
3543         "}\n"
3544         "void main() {\n"
3545         "    vec4 v = vec4(0.0, 2.0, 4.0, 6.0); \n"
3546         "    float f = (func(), (++v[u_zero + sideEffectCount]));\n"
3547         "    bool green = abs(f - 3.0) < 0.01 && abs(v[1] - 3.0) < 0.01 && sideEffectCount == 1;\n"
3548         "    my_FragColor = vec4(0.0, (green ? 1.0 : 0.0), 0.0, 1.0);\n"
3549         "}\n";
3550 
3551     GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS);
3552     ASSERT_NE(0u, program);
3553 
3554     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3555 
3556     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3557 }
3558 
3559 // Test that using gl_PointCoord with GL_TRIANGLES doesn't produce a link error.
3560 // From WebGL test conformance/rendering/point-specific-shader-variables.html
3561 // See http://anglebug.com/1380
TEST_P(GLSLTest,RenderTrisWithPointCoord)3562 TEST_P(GLSLTest, RenderTrisWithPointCoord)
3563 {
3564     constexpr char kVS[] =
3565         "attribute vec2 aPosition;\n"
3566         "void main()\n"
3567         "{\n"
3568         "    gl_Position = vec4(aPosition, 0, 1);\n"
3569         "    gl_PointSize = 1.0;\n"
3570         "}";
3571     constexpr char kFS[] =
3572         "void main()\n"
3573         "{\n"
3574         "    gl_FragColor = vec4(gl_PointCoord.xy, 0, 1);\n"
3575         "    gl_FragColor = vec4(0, 1, 0, 1);\n"
3576         "}";
3577 
3578     ANGLE_GL_PROGRAM(prog, kVS, kFS);
3579     drawQuad(prog.get(), "aPosition", 0.5f);
3580     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3581 }
3582 
3583 // Convers a bug with the integer pow statement workaround.
TEST_P(GLSLTest,NestedPowStatements)3584 TEST_P(GLSLTest, NestedPowStatements)
3585 {
3586     // https://crbug.com/1127866 - possible NVIDIA driver issue
3587     ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsVulkan() && IsWindows());
3588 
3589     constexpr char kFS[] =
3590         "precision mediump float;\n"
3591         "float func(float v)\n"
3592         "{\n"
3593         "   float f1 = pow(v, 2.0);\n"
3594         "   return pow(f1 + v, 2.0);\n"
3595         "}\n"
3596         "void main()\n"
3597         "{\n"
3598         "    float v = func(2.0);\n"
3599         "    gl_FragColor = abs(v - 36.0) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
3600         "}";
3601 
3602     ANGLE_GL_PROGRAM(prog, essl1_shaders::vs::Simple(), kFS);
3603     drawQuad(prog.get(), essl1_shaders::PositionAttrib(), 0.5f);
3604     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3605 }
3606 
3607 // Test that -float calculation is correct.
TEST_P(GLSLTest_ES3,UnaryMinusOperatorFloat)3608 TEST_P(GLSLTest_ES3, UnaryMinusOperatorFloat)
3609 {
3610     constexpr char kFS[] =
3611         "#version 300 es\n"
3612         "out highp vec4 o_color;\n"
3613         "void main() {\n"
3614         "    highp float f = -1.0;\n"
3615         "    // atan(tan(0.5), -f) should be 0.5.\n"
3616         "    highp float v = atan(tan(0.5), -f);\n"
3617         "    o_color = abs(v - 0.5) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
3618         "}\n";
3619 
3620     ANGLE_GL_PROGRAM(prog, essl3_shaders::vs::Simple(), kFS);
3621     drawQuad(prog.get(), essl3_shaders::PositionAttrib(), 0.5f);
3622     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3623 }
3624 
3625 // Test that atan(vec2, vec2) calculation is correct.
TEST_P(GLSLTest_ES3,AtanVec2)3626 TEST_P(GLSLTest_ES3, AtanVec2)
3627 {
3628     constexpr char kFS[] =
3629         "#version 300 es\n"
3630         "out highp vec4 o_color;\n"
3631         "void main() {\n"
3632         "    highp float f = 1.0;\n"
3633         "    // atan(tan(0.5), f) should be 0.5.\n"
3634         "    highp vec2 v = atan(vec2(tan(0.5)), vec2(f));\n"
3635         "    o_color = (abs(v[0] - 0.5) < 0.001 && abs(v[1] - 0.5) < 0.001) ? vec4(0, 1, 0, 1) : "
3636         "vec4(1, 0, 0, 1);\n"
3637         "}\n";
3638 
3639     ANGLE_GL_PROGRAM(prog, essl3_shaders::vs::Simple(), kFS);
3640     drawQuad(prog.get(), essl3_shaders::PositionAttrib(), 0.5f);
3641     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3642 }
3643 
3644 // Convers a bug with the unary minus operator on signed integer workaround.
TEST_P(GLSLTest_ES3,UnaryMinusOperatorSignedInt)3645 TEST_P(GLSLTest_ES3, UnaryMinusOperatorSignedInt)
3646 {
3647     constexpr char kVS[] =
3648         "#version 300 es\n"
3649         "in highp vec4 position;\n"
3650         "out mediump vec4 v_color;\n"
3651         "uniform int ui_one;\n"
3652         "uniform int ui_two;\n"
3653         "uniform int ui_three;\n"
3654         "void main() {\n"
3655         "    int s[3];\n"
3656         "    s[0] = ui_one;\n"
3657         "    s[1] = -(-(-ui_two + 1) + 1);\n"  // s[1] = -ui_two
3658         "    s[2] = ui_three;\n"
3659         "    int result = 0;\n"
3660         "    for (int i = 0; i < ui_three; i++) {\n"
3661         "        result += s[i];\n"
3662         "    }\n"
3663         "    v_color = (result == 2) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
3664         "    gl_Position = position;\n"
3665         "}\n";
3666     constexpr char kFS[] =
3667         "#version 300 es\n"
3668         "in mediump vec4 v_color;\n"
3669         "layout(location=0) out mediump vec4 o_color;\n"
3670         "void main() {\n"
3671         "    o_color = v_color;\n"
3672         "}\n";
3673 
3674     ANGLE_GL_PROGRAM(prog, kVS, kFS);
3675 
3676     GLint oneIndex = glGetUniformLocation(prog.get(), "ui_one");
3677     ASSERT_NE(-1, oneIndex);
3678     GLint twoIndex = glGetUniformLocation(prog.get(), "ui_two");
3679     ASSERT_NE(-1, twoIndex);
3680     GLint threeIndex = glGetUniformLocation(prog.get(), "ui_three");
3681     ASSERT_NE(-1, threeIndex);
3682     glUseProgram(prog.get());
3683     glUniform1i(oneIndex, 1);
3684     glUniform1i(twoIndex, 2);
3685     glUniform1i(threeIndex, 3);
3686 
3687     drawQuad(prog.get(), "position", 0.5f);
3688     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3689 }
3690 
3691 // Convers a bug with the unary minus operator on unsigned integer workaround.
TEST_P(GLSLTest_ES3,UnaryMinusOperatorUnsignedInt)3692 TEST_P(GLSLTest_ES3, UnaryMinusOperatorUnsignedInt)
3693 {
3694     constexpr char kVS[] =
3695         "#version 300 es\n"
3696         "in highp vec4 position;\n"
3697         "out mediump vec4 v_color;\n"
3698         "uniform uint ui_one;\n"
3699         "uniform uint ui_two;\n"
3700         "uniform uint ui_three;\n"
3701         "void main() {\n"
3702         "    uint s[3];\n"
3703         "    s[0] = ui_one;\n"
3704         "    s[1] = -(-(-ui_two + 1u) + 1u);\n"  // s[1] = -ui_two
3705         "    s[2] = ui_three;\n"
3706         "    uint result = 0u;\n"
3707         "    for (uint i = 0u; i < ui_three; i++) {\n"
3708         "        result += s[i];\n"
3709         "    }\n"
3710         "    v_color = (result == 2u) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
3711         "    gl_Position = position;\n"
3712         "}\n";
3713     constexpr char kFS[] =
3714         "#version 300 es\n"
3715         "in mediump vec4 v_color;\n"
3716         "layout(location=0) out mediump vec4 o_color;\n"
3717         "void main() {\n"
3718         "    o_color = v_color;\n"
3719         "}\n";
3720 
3721     ANGLE_GL_PROGRAM(prog, kVS, kFS);
3722 
3723     GLint oneIndex = glGetUniformLocation(prog.get(), "ui_one");
3724     ASSERT_NE(-1, oneIndex);
3725     GLint twoIndex = glGetUniformLocation(prog.get(), "ui_two");
3726     ASSERT_NE(-1, twoIndex);
3727     GLint threeIndex = glGetUniformLocation(prog.get(), "ui_three");
3728     ASSERT_NE(-1, threeIndex);
3729     glUseProgram(prog.get());
3730     glUniform1ui(oneIndex, 1u);
3731     glUniform1ui(twoIndex, 2u);
3732     glUniform1ui(threeIndex, 3u);
3733 
3734     drawQuad(prog.get(), "position", 0.5f);
3735     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3736 }
3737 
3738 // Test a nested sequence operator with a ternary operator inside. The ternary operator is
3739 // intended to be such that it gets converted to an if statement on the HLSL backend.
TEST_P(GLSLTest,NestedSequenceOperatorWithTernaryInside)3740 TEST_P(GLSLTest, NestedSequenceOperatorWithTernaryInside)
3741 {
3742     // Note that the uniform keep_flop_positive doesn't need to be set - the test expects it to have
3743     // its default value false.
3744     constexpr char kFS[] =
3745         "precision mediump float;\n"
3746         "uniform bool keep_flop_positive;\n"
3747         "float flop;\n"
3748         "void main() {\n"
3749         "    flop = -1.0,\n"
3750         "    (flop *= -1.0,\n"
3751         "    keep_flop_positive ? 0.0 : flop *= -1.0),\n"
3752         "    gl_FragColor = vec4(0, -flop, 0, 1);\n"
3753         "}";
3754 
3755     ANGLE_GL_PROGRAM(prog, essl1_shaders::vs::Simple(), kFS);
3756     drawQuad(prog.get(), essl1_shaders::PositionAttrib(), 0.5f);
3757     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3758 }
3759 
3760 // Test that nesting ternary and short-circuitting operators work.
TEST_P(GLSLTest,NestedTernaryAndShortCircuit)3761 TEST_P(GLSLTest, NestedTernaryAndShortCircuit)
3762 {
3763     // Note that the uniform doesn't need to be set, and will contain the default value of false.
3764     constexpr char kFS[] = R"(
3765 precision mediump float;
3766 uniform bool u;
3767 void main()
3768 {
3769     int a = u ? 12345 : 2;      // will be 2
3770     int b = u ? 12345 : 4;      // will be 4
3771     int c = u ? 12345 : 0;      // will be 0
3772 
3773     if (a == 2                  // true path is taken
3774         ? (b == 3               // false path is taken
3775             ? (a=0) != 0
3776             : b != 0            // true
3777           ) && (                // short-circuit evaluates RHS
3778             (a=7) == 7          // true, modifies a
3779             ||                  // short-circuit doesn't evaluate RHS
3780             (b=8) == 8
3781           )
3782         : (a == 0 && b == 0
3783             ? (c += int((a=0) == 0 && (b=0) == 0)) != 0
3784             : (c += int((a=0) != 0 && (b=0) != 0)) != 0))
3785     {
3786         c += 15;                // will execute
3787     }
3788 
3789     // Verify that a is 7, b is 4 and c is 15.
3790     gl_FragColor = vec4(a == 7, b == 4, c == 15, 1);
3791 })";
3792 
3793     ANGLE_GL_PROGRAM(prog, essl1_shaders::vs::Simple(), kFS);
3794     drawQuad(prog.get(), essl1_shaders::PositionAttrib(), 0.5f);
3795     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
3796 }
3797 
3798 // Test that uniform bvecN passed to functions work.
TEST_P(GLSLTest_ES3,UniformBoolVectorPassedToFunctions)3799 TEST_P(GLSLTest_ES3, UniformBoolVectorPassedToFunctions)
3800 {
3801     constexpr char kFS[] = R"(#version 300 es
3802 precision mediump float;
3803 uniform bvec4 u;
3804 out vec4 color;
3805 
3806 bool f(bvec4 bv)
3807 {
3808     return all(bv.xz) && !any(bv.yw);
3809 }
3810 
3811 void main() {
3812     color = f(u) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
3813 })";
3814 
3815     ANGLE_GL_PROGRAM(prog, essl3_shaders::vs::Simple(), kFS);
3816     glUseProgram(prog);
3817 
3818     GLint uloc = glGetUniformLocation(prog, "u");
3819     ASSERT_NE(uloc, -1);
3820     glUniform4ui(uloc, true, false, true, false);
3821 
3822     drawQuad(prog.get(), essl3_shaders::PositionAttrib(), 0.5f);
3823     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3824 }
3825 
3826 // Test that bvecN in storage buffer passed to functions work.
TEST_P(GLSLTest_ES31,StorageBufferBoolVectorPassedToFunctions)3827 TEST_P(GLSLTest_ES31, StorageBufferBoolVectorPassedToFunctions)
3828 {
3829     constexpr char kCS[] = R"(#version 310 es
3830 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
3831 layout(binding = 0, std430) buffer Output {
3832     bvec4 b;
3833     bool valid;
3834 } outbuf;
3835 
3836 bool f_in(bvec4 bv)
3837 {
3838     return all(bv.xz) && !any(bv.yw);
3839 }
3840 
3841 bool f_inout(inout bvec4 bv)
3842 {
3843     bool ok = all(bv.xz) && !any(bv.yw);
3844     bv.xw = bvec2(false, true);
3845     return ok;
3846 }
3847 
3848 void f_out(out bvec4 bv)
3849 {
3850     bv = bvec4(false, true, false, true);
3851 }
3852 
3853 void main() {
3854     bool valid = f_in(outbuf.b);
3855     valid = f_inout(outbuf.b) && valid;
3856     f_out(outbuf.b);
3857     outbuf.valid = valid;
3858 })";
3859 
3860     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
3861     glUseProgram(program);
3862 
3863     constexpr std::array<GLuint, 5> kOutputInitData = {true, false, true, false, false};
3864     GLBuffer outputBuffer;
3865     glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
3866     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kOutputInitData), kOutputInitData.data(),
3867                  GL_STATIC_DRAW);
3868     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, outputBuffer);
3869     EXPECT_GL_NO_ERROR();
3870 
3871     glDispatchCompute(1, 1, 1);
3872     EXPECT_GL_NO_ERROR();
3873 
3874     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3875 
3876     const GLuint *ptr = reinterpret_cast<const GLuint *>(
3877         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kOutputInitData), GL_MAP_READ_BIT));
3878     fprintf(stderr, "%d %d %d %d %d\n", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4]);
3879     EXPECT_FALSE(ptr[0]);
3880     EXPECT_TRUE(ptr[1]);
3881     EXPECT_FALSE(ptr[2]);
3882     EXPECT_TRUE(ptr[3]);
3883     EXPECT_TRUE(ptr[4]);
3884     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3885 }
3886 
3887 // Test that using a sampler2D and samplerExternalOES in the same shader works (anglebug.com/1534)
TEST_P(GLSLTest,ExternalAnd2DSampler)3888 TEST_P(GLSLTest, ExternalAnd2DSampler)
3889 {
3890     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_EGL_image_external"));
3891 
3892     constexpr char kFS[] = R"(#extension GL_OES_EGL_image_external : enable
3893 precision mediump float;
3894 uniform samplerExternalOES tex0;
3895 uniform sampler2D tex1;
3896 void main(void)
3897 {
3898     vec2 uv = vec2(0.0, 0.0);
3899     gl_FragColor = texture2D(tex0, uv) + texture2D(tex1, uv);
3900 })";
3901 
3902     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
3903 }
3904 
3905 // Test that using a varying matrix array is supported.
TEST_P(GLSLTest,VaryingMatrixArray)3906 TEST_P(GLSLTest, VaryingMatrixArray)
3907 {
3908     constexpr char kVS[] =
3909         "uniform vec2 u_a1;\n"
3910         "uniform vec2 u_a2;\n"
3911         "attribute vec4 a_position;\n"
3912         "varying mat2 v_mat[2];\n"
3913         "void main() {\n"
3914         "    v_mat[0] = mat2(u_a1, u_a2);\n"
3915         "    v_mat[1] = mat2(1.0 - u_a2, 1.0 - u_a1);\n"
3916         "    gl_Position = a_position;\n"
3917         "}";
3918 
3919     constexpr char kFS[] =
3920         "precision mediump float;\n"
3921         "varying mat2 v_mat[2];\n"
3922         "void main(void)\n"
3923         "{\n"
3924         "    gl_FragColor = vec4(v_mat[0][0].x, v_mat[0][0].y, v_mat[1][0].x, 1.0);\n"
3925         "}";
3926 
3927     ANGLE_GL_PROGRAM(program, kVS, kFS);
3928 
3929     GLint oneIndex = glGetUniformLocation(program, "u_a1");
3930     ASSERT_NE(-1, oneIndex);
3931     GLint twoIndex = glGetUniformLocation(program, "u_a2");
3932     ASSERT_NE(-1, twoIndex);
3933     glUseProgram(program);
3934     glUniform2f(oneIndex, 1, 0.5f);
3935     glUniform2f(twoIndex, 0.25f, 0.125f);
3936 
3937     drawQuad(program, "a_position", 0.5f);
3938     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 127, 255 - 63, 255), 1.0);
3939 }
3940 
3941 // Test that using a centroid varying matrix array is supported.
TEST_P(GLSLTest_ES3,CentroidVaryingMatrixArray)3942 TEST_P(GLSLTest_ES3, CentroidVaryingMatrixArray)
3943 {
3944     // TODO(anglebug.com/5491): Skipping initial failures so we can set up a passing iOS test bot.
3945     ANGLE_SKIP_TEST_IF(IsIOS() && IsOpenGLES());
3946 
3947     constexpr char kVS[] =
3948         "#version 300 es\n"
3949         "uniform vec2 u_a1;\n"
3950         "uniform vec2 u_a2;\n"
3951         "in vec4 a_position;\n"
3952         "centroid out mat3x2 v_mat[2];\n"
3953         "void main() {\n"
3954         "    v_mat[0] = mat3x2(u_a1, u_a2, vec2(0.0));\n"
3955         "    v_mat[1] = mat3x2(vec2(0.0), 1.0 - u_a2, 1.0 - u_a1);\n"
3956         "    gl_Position = a_position;\n"
3957         "}";
3958 
3959     constexpr char kFS[] =
3960         "#version 300 es\n"
3961         "precision mediump float;\n"
3962         "centroid in mat3x2 v_mat[2];\n"
3963         "layout(location = 0) out vec4 out_color;\n"
3964         "void main(void)\n"
3965         "{\n"
3966         "    out_color = vec4(v_mat[0][0].x, v_mat[0][0].y, v_mat[1][1].x, 1.0);\n"
3967         "}";
3968 
3969     ANGLE_GL_PROGRAM(program, kVS, kFS);
3970 
3971     GLint oneIndex = glGetUniformLocation(program, "u_a1");
3972     ASSERT_NE(-1, oneIndex);
3973     GLint twoIndex = glGetUniformLocation(program, "u_a2");
3974     ASSERT_NE(-1, twoIndex);
3975     glUseProgram(program);
3976     glUniform2f(oneIndex, 1, 0.5f);
3977     glUniform2f(twoIndex, 0.25f, 0.125f);
3978 
3979     drawQuad(program, "a_position", 0.5f);
3980     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 127, 255 - 63, 255), 1.0);
3981 }
3982 
3983 // Test that using a flat varying matrix array is supported.
TEST_P(GLSLTest_ES3,FlatVaryingMatrixArray)3984 TEST_P(GLSLTest_ES3, FlatVaryingMatrixArray)
3985 {
3986     constexpr char kVS[] =
3987         "#version 300 es\n"
3988         "uniform vec2 u_a1;\n"
3989         "uniform vec2 u_a2;\n"
3990         "in vec4 a_position;\n"
3991         "flat out mat2 v_mat[2];\n"
3992         "void main() {\n"
3993         "    v_mat[0] = mat2(u_a1, u_a2);\n"
3994         "    v_mat[1] = mat2(u_a2, u_a1);\n"
3995         "    gl_Position = a_position;\n"
3996         "}";
3997 
3998     constexpr char kFS[] =
3999         "#version 300 es\n"
4000         "precision mediump float;\n"
4001         "flat in mat2 v_mat[2];\n"
4002         "layout(location = 0) out vec4 out_color;\n"
4003         "void main(void)\n"
4004         "{\n"
4005         "    out_color = vec4(v_mat[0][0].x, v_mat[0][0].y, v_mat[1][0].x, 1.0);\n"
4006         "}";
4007 
4008     ANGLE_GL_PROGRAM(program, kVS, kFS);
4009 
4010     GLint oneIndex = glGetUniformLocation(program, "u_a1");
4011     ASSERT_NE(-1, oneIndex);
4012     GLint twoIndex = glGetUniformLocation(program, "u_a2");
4013     ASSERT_NE(-1, twoIndex);
4014     glUseProgram(program);
4015     glUniform2f(oneIndex, 1, 0.5f);
4016     glUniform2f(twoIndex, 0.25f, 0.125f);
4017 
4018     drawQuad(program, "a_position", 0.5f);
4019     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 127, 63, 255), 1.0);
4020 }
4021 
4022 // Test that literal infinity can be written out from the shader translator.
4023 // 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)4024 TEST_P(GLSLTest_ES3, LiteralInfinityOutput)
4025 {
4026     constexpr char kFS[] =
4027         "#version 300 es\n"
4028         "precision highp float;\n"
4029         "out vec4 out_color;\n"
4030         "uniform float u;\n"
4031         "void main()\n"
4032         "{\n"
4033         "   float infVar = 1.0e40 - u;\n"
4034         "   bool correct = isinf(infVar) && infVar > 0.0;\n"
4035         "   out_color = correct ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4036         "}\n";
4037 
4038     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4039     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
4040     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4041 }
4042 
4043 // Test that literal negative infinity can be written out from the shader translator.
4044 // 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)4045 TEST_P(GLSLTest_ES3, LiteralNegativeInfinityOutput)
4046 {
4047     constexpr char kFS[] =
4048         "#version 300 es\n"
4049         "precision highp float;\n"
4050         "out vec4 out_color;\n"
4051         "uniform float u;\n"
4052         "void main()\n"
4053         "{\n"
4054         "   float infVar = -1.0e40 + u;\n"
4055         "   bool correct = isinf(infVar) && infVar < 0.0;\n"
4056         "   out_color = correct ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4057         "}\n";
4058 
4059     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4060     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
4061     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4062 }
4063 
4064 // The following MultipleDeclaration* tests are testing TranslatorHLSL specific simplification
4065 // passes. Because the interaction of multiple passes must be tested, it is difficult to write
4066 // a unittest for them. Instead we add the tests as end2end so will in particular test
4067 // TranslatorHLSL when run on Windows.
4068 
4069 // Test that passes splitting multiple declarations and comma operators are correctly ordered.
TEST_P(GLSLTest_ES3,MultipleDeclarationWithCommaOperator)4070 TEST_P(GLSLTest_ES3, MultipleDeclarationWithCommaOperator)
4071 {
4072     constexpr char kFS[] = R"(#version 300 es
4073 precision mediump float;
4074 out vec4 color;
4075 
4076 uniform float u;
4077 float c = 0.0;
4078 float sideEffect()
4079 {
4080     c = u;
4081     return c;
4082 }
4083 
4084 void main(void)
4085 {
4086     float a = 0.0, b = ((gl_FragCoord.x < 0.5 ? a : sideEffect()), a);
4087     color = vec4(b + c);
4088 })";
4089 
4090     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4091 }
4092 
4093 // Test that passes splitting multiple declarations and comma operators and for loops are
4094 // correctly ordered.
TEST_P(GLSLTest_ES3,MultipleDeclarationWithCommaOperatorInForLoop)4095 TEST_P(GLSLTest_ES3, MultipleDeclarationWithCommaOperatorInForLoop)
4096 {
4097     constexpr char kFS[] = R"(#version 300 es
4098 precision mediump float;
4099 out vec4 color;
4100 
4101 uniform float u;
4102 float c = 0.0;
4103 float sideEffect()
4104 {
4105     c = u;
4106     return c;
4107 }
4108 
4109 void main(void)
4110 {
4111     for(float a = 0.0, b = ((gl_FragCoord.x < 0.5 ? a : sideEffect()), a); a < 10.0; a++)
4112     {
4113         b += 1.0;
4114         color = vec4(b);
4115     }
4116 })";
4117 
4118     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4119 }
4120 
4121 // Test that splitting multiple declaration in for loops works with no loop condition
TEST_P(GLSLTest_ES3,MultipleDeclarationInForLoopEmptyCondition)4122 TEST_P(GLSLTest_ES3, MultipleDeclarationInForLoopEmptyCondition)
4123 {
4124     constexpr char kFS[] =
4125         "#version 300 es\n"
4126         "precision mediump float;\n"
4127         "out vec4 color;\n"
4128         "void main(void)\n"
4129         "{\n"
4130         " for(float a = 0.0, b = 1.0;; a++)\n"
4131         " {\n"
4132         "  b += 1.0;\n"
4133         "  if (a > 10.0) {break;}\n"
4134         "  color = vec4(b);\n"
4135         " }\n"
4136         "}\n";
4137 
4138     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4139 }
4140 
4141 // Test that splitting multiple declaration in for loops works with no loop expression
TEST_P(GLSLTest_ES3,MultipleDeclarationInForLoopEmptyExpression)4142 TEST_P(GLSLTest_ES3, MultipleDeclarationInForLoopEmptyExpression)
4143 {
4144     constexpr char kFS[] =
4145         "#version 300 es\n"
4146         "precision mediump float;\n"
4147         "out vec4 color;\n"
4148         "void main(void)\n"
4149         "{\n"
4150         " for(float a = 0.0, b = 1.0; a < 10.0;)\n"
4151         " {\n"
4152         "  b += 1.0;\n"
4153         "  a += 1.0;\n"
4154         "  color = vec4(b);\n"
4155         " }\n"
4156         "}\n";
4157 
4158     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4159 }
4160 
4161 // Test that dynamic indexing of a matrix inside a dynamic indexing of a vector in an l-value works
4162 // correctly.
TEST_P(GLSLTest_ES3,NestedDynamicIndexingInLValue)4163 TEST_P(GLSLTest_ES3, NestedDynamicIndexingInLValue)
4164 {
4165     constexpr char kFS[] =
4166         "#version 300 es\n"
4167         "precision mediump float;\n"
4168         "out vec4 my_FragColor;\n"
4169         "uniform int u_zero;\n"
4170         "void main() {\n"
4171         "    mat2 m = mat2(0.0, 0.0, 0.0, 0.0);\n"
4172         "    m[u_zero + 1][u_zero + 1] = float(u_zero + 1);\n"
4173         "    float f = m[1][1];\n"
4174         "    my_FragColor = vec4(1.0 - f, f, 0.0, 1.0);\n"
4175         "}\n";
4176 
4177     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4178     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
4179     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4180 }
4181 
4182 class WebGLGLSLTest : public GLSLTest
4183 {
4184   protected:
WebGLGLSLTest()4185     WebGLGLSLTest() { setWebGLCompatibilityEnabled(true); }
4186 };
4187 
4188 class WebGL2GLSLTest : public GLSLTest
4189 {
4190   protected:
WebGL2GLSLTest()4191     WebGL2GLSLTest() { setWebGLCompatibilityEnabled(true); }
4192 };
4193 
TEST_P(WebGLGLSLTest,MaxVaryingVec4PlusFragCoord)4194 TEST_P(WebGLGLSLTest, MaxVaryingVec4PlusFragCoord)
4195 {
4196     GLint maxVaryings = 0;
4197     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4198 
4199     // Generate shader code that uses gl_FragCoord, a special fragment shader variables.
4200     // This test should fail, since we are really using (maxVaryings + 1) varyings.
4201     VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, true, false, false, false);
4202 }
4203 
TEST_P(WebGLGLSLTest,MaxVaryingVec4PlusPointCoord)4204 TEST_P(WebGLGLSLTest, MaxVaryingVec4PlusPointCoord)
4205 {
4206     GLint maxVaryings = 0;
4207     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4208 
4209     // Generate shader code that uses gl_FragCoord, a special fragment shader variables.
4210     // This test should fail, since we are really using (maxVaryings + 1) varyings.
4211     VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, false, true, false, false);
4212 }
4213 
TEST_P(WebGLGLSLTest,MaxPlusOneVaryingVec3)4214 TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec3)
4215 {
4216     GLint maxVaryings = 0;
4217     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4218 
4219     VaryingTestBase(0, 0, 0, 0, maxVaryings + 1, 0, 0, 0, false, false, false, false);
4220 }
4221 
TEST_P(WebGLGLSLTest,MaxPlusOneVaryingVec3Array)4222 TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec3Array)
4223 {
4224     GLint maxVaryings = 0;
4225     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4226 
4227     VaryingTestBase(0, 0, 0, 0, 0, maxVaryings / 2 + 1, 0, 0, false, false, false, false);
4228 }
4229 
TEST_P(WebGLGLSLTest,MaxVaryingVec3AndOneVec2)4230 TEST_P(WebGLGLSLTest, MaxVaryingVec3AndOneVec2)
4231 {
4232     GLint maxVaryings = 0;
4233     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4234 
4235     VaryingTestBase(0, 0, 1, 0, maxVaryings, 0, 0, 0, false, false, false, false);
4236 }
4237 
TEST_P(WebGLGLSLTest,MaxPlusOneVaryingVec2)4238 TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec2)
4239 {
4240     GLint maxVaryings = 0;
4241     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4242 
4243     VaryingTestBase(0, 0, 2 * maxVaryings + 1, 0, 0, 0, 0, 0, false, false, false, false);
4244 }
4245 
TEST_P(WebGLGLSLTest,MaxVaryingVec3ArrayAndMaxPlusOneFloatArray)4246 TEST_P(WebGLGLSLTest, MaxVaryingVec3ArrayAndMaxPlusOneFloatArray)
4247 {
4248     GLint maxVaryings = 0;
4249     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4250 
4251     VaryingTestBase(0, maxVaryings / 2 + 1, 0, 0, 0, 0, 0, maxVaryings / 2, false, false, false,
4252                     false);
4253 }
4254 
4255 // Test that FindLSB and FindMSB return correct values in their corner cases.
TEST_P(GLSLTest_ES31,FindMSBAndFindLSBCornerCases)4256 TEST_P(GLSLTest_ES31, FindMSBAndFindLSBCornerCases)
4257 {
4258     // Suspecting AMD driver bug - failure seen on bots running on AMD R5 230.
4259     ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL() && IsLinux());
4260 
4261     // Failing on N5X Oreo http://anglebug.com/2304
4262     ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
4263 
4264     constexpr char kFS[] =
4265         "#version 310 es\n"
4266         "precision mediump float;\n"
4267         "out vec4 my_FragColor;\n"
4268         "uniform int u_zero;\n"
4269         "void main() {\n"
4270         "    if (findLSB(u_zero) == -1 && findMSB(u_zero) == -1 && findMSB(u_zero - 1) == -1)\n"
4271         "    {\n"
4272         "        my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
4273         "    }\n"
4274         "    else\n"
4275         "    {\n"
4276         "        my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
4277         "    }\n"
4278         "}\n";
4279 
4280     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4281     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
4282     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4283 }
4284 
4285 // Test that writing into a swizzled vector that is dynamically indexed succeeds.
TEST_P(GLSLTest_ES3,WriteIntoDynamicIndexingOfSwizzledVector)4286 TEST_P(GLSLTest_ES3, WriteIntoDynamicIndexingOfSwizzledVector)
4287 {
4288     // http://anglebug.com/1924
4289     ANGLE_SKIP_TEST_IF(IsOpenGL());
4290 
4291     // The shader first assigns v.x to v.z (1.0)
4292     // Then v.y to v.y (2.0)
4293     // Then v.z to v.x (1.0)
4294     constexpr char kFS[] =
4295         "#version 300 es\n"
4296         "precision highp float;\n"
4297         "out vec4 my_FragColor;\n"
4298         "void main() {\n"
4299         "    vec3 v = vec3(1.0, 2.0, 3.0);\n"
4300         "    for (int i = 0; i < 3; i++) {\n"
4301         "        v.zyx[i] = v[i];\n"
4302         "    }\n"
4303         "    my_FragColor = distance(v, vec3(1.0, 2.0, 1.0)) < 0.01 ? vec4(0, 1, 0, 1) : vec4(1, "
4304         "0, 0, 1);\n"
4305         "}\n";
4306 
4307     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4308     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
4309     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4310 }
4311 
4312 // Test that the length() method is correctly translated in Vulkan atomic counter buffer emulation.
TEST_P(GLSLTest_ES31,AtomicCounterArrayLength)4313 TEST_P(GLSLTest_ES31, AtomicCounterArrayLength)
4314 {
4315     // Crashes on an assertion.  The driver reports no atomic counter buffers when queried from the
4316     // program, but ANGLE believes there to be one.
4317     //
4318     // This is likely due to the fact that ANGLE generates the following code, as a side effect of
4319     // the code on which .length() is being called:
4320     //
4321     //     _uac1[(_uvalue = _utestSideEffectValue)];
4322     //
4323     // The driver is optimizing the subscription out, and calling the atomic counter inactive.  This
4324     // was observed on nvidia, mesa and amd/windows.
4325     //
4326     // The fix would be for ANGLE to skip uniforms it believes should exist, but when queried, the
4327     // driver says don't.
4328     //
4329     // http://anglebug.com/3782
4330     ANGLE_SKIP_TEST_IF(IsOpenGL());
4331 
4332     constexpr char kCS[] = R"(#version 310 es
4333 precision mediump float;
4334 layout(local_size_x=1) in;
4335 
4336 layout(binding = 0) uniform atomic_uint ac1[2][3][4];
4337 uniform uint testSideEffectValue;
4338 
4339 layout(binding = 1, std140) buffer Result
4340 {
4341     uint value;
4342 } result;
4343 
4344 void main() {
4345     bool passed = true;
4346     if (ac1.length() != 2)
4347     {
4348         passed = false;
4349     }
4350     uint value = 0u;
4351     if (ac1[value = testSideEffectValue].length() != 3)
4352     {
4353         passed = false;
4354     }
4355     if (value != testSideEffectValue)
4356     {
4357         passed = false;
4358     }
4359     if (ac1[1][value = testSideEffectValue + 1u].length() != 4)
4360     {
4361         passed = false;
4362     }
4363     if (value != testSideEffectValue + 1u)
4364     {
4365         passed = false;
4366     }
4367     result.value = passed ? 255u : 127u;
4368 })";
4369 
4370     constexpr unsigned int kUniformTestValue     = 17;
4371     constexpr unsigned int kExpectedSuccessValue = 255;
4372     constexpr unsigned int kAtomicCounterRows    = 2;
4373     constexpr unsigned int kAtomicCounterCols    = 3;
4374 
4375     GLint maxAtomicCounters = 0;
4376     glGetIntegerv(GL_MAX_COMPUTE_ATOMIC_COUNTERS, &maxAtomicCounters);
4377     EXPECT_GL_NO_ERROR();
4378 
4379     // Required minimum is 8 by the spec
4380     EXPECT_GE(maxAtomicCounters, 8);
4381     ANGLE_SKIP_TEST_IF(static_cast<uint32_t>(maxAtomicCounters) <
4382                        kAtomicCounterRows * kAtomicCounterCols);
4383 
4384     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
4385     glUseProgram(program.get());
4386 
4387     constexpr unsigned int kBufferData[kAtomicCounterRows * kAtomicCounterCols] = {};
4388     GLBuffer atomicCounterBuffer;
4389     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
4390     glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(kBufferData), kBufferData, GL_STATIC_DRAW);
4391     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
4392 
4393     constexpr unsigned int kOutputInitValue = 0;
4394     GLBuffer shaderStorageBuffer;
4395     glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer);
4396     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kOutputInitValue), &kOutputInitValue,
4397                  GL_STATIC_DRAW);
4398     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, shaderStorageBuffer);
4399 
4400     GLint uniformLocation = glGetUniformLocation(program, "testSideEffectValue");
4401     EXPECT_NE(uniformLocation, -1);
4402     glUniform1ui(uniformLocation, kUniformTestValue);
4403     EXPECT_GL_NO_ERROR();
4404 
4405     glDispatchCompute(1, 1, 1);
4406 
4407     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4408 
4409     const GLuint *ptr = reinterpret_cast<const GLuint *>(
4410         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(GLuint), GL_MAP_READ_BIT));
4411     EXPECT_EQ(*ptr, kExpectedSuccessValue);
4412     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4413 }
4414 
4415 // Test that inactive images don't cause any errors.
TEST_P(GLSLTest_ES31,InactiveImages)4416 TEST_P(GLSLTest_ES31, InactiveImages)
4417 {
4418     ANGLE_SKIP_TEST_IF(IsD3D11());
4419 
4420     constexpr char kCS[] = R"(#version 310 es
4421 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
4422 layout(rgba32ui) uniform highp readonly uimage2D image1;
4423 layout(rgba32ui) uniform highp readonly uimage2D image2[4];
4424 void main()
4425 {
4426 })";
4427 
4428     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
4429 
4430     glUseProgram(program.get());
4431     glDispatchCompute(1, 1, 1);
4432     EXPECT_GL_NO_ERROR();
4433 
4434     // Verify that the images are indeed inactive.
4435     GLuint index = glGetProgramResourceIndex(program, GL_UNIFORM, "image1");
4436     EXPECT_GL_NO_ERROR();
4437     EXPECT_EQ(GL_INVALID_INDEX, index);
4438 
4439     index = glGetProgramResourceIndex(program, GL_UNIFORM, "image2");
4440     EXPECT_GL_NO_ERROR();
4441     EXPECT_EQ(GL_INVALID_INDEX, index);
4442 }
4443 
4444 // Test that inactive atomic counters don't cause any errors.
TEST_P(GLSLTest_ES31,InactiveAtomicCounters)4445 TEST_P(GLSLTest_ES31, InactiveAtomicCounters)
4446 {
4447     constexpr char kCS[] = R"(#version 310 es
4448 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
4449 layout(binding = 0, offset = 0) uniform atomic_uint ac1;
4450 layout(binding = 0, offset = 4) uniform atomic_uint ac2[5];
4451 void main()
4452 {
4453 })";
4454 
4455     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
4456 
4457     glUseProgram(program.get());
4458     glDispatchCompute(1, 1, 1);
4459     EXPECT_GL_NO_ERROR();
4460 
4461     // Verify that the atomic counters are indeed inactive.
4462     GLuint index = glGetProgramResourceIndex(program, GL_UNIFORM, "ac1");
4463     EXPECT_GL_NO_ERROR();
4464     EXPECT_EQ(GL_INVALID_INDEX, index);
4465 
4466     index = glGetProgramResourceIndex(program, GL_UNIFORM, "ac2");
4467     EXPECT_GL_NO_ERROR();
4468     EXPECT_EQ(GL_INVALID_INDEX, index);
4469 }
4470 
4471 // Test that inactive samplers in structs don't cause any errors.
TEST_P(GLSLTest_ES31,InactiveSamplersInStructCS)4472 TEST_P(GLSLTest_ES31, InactiveSamplersInStructCS)
4473 {
4474     constexpr char kCS[] = R"(#version 310 es
4475 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
4476 struct S
4477 {
4478     vec4 v;
4479     sampler2D t[10];
4480 };
4481 uniform S s;
4482 void main()
4483 {
4484 })";
4485 
4486     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
4487 
4488     glUseProgram(program.get());
4489     glDispatchCompute(1, 1, 1);
4490     EXPECT_GL_NO_ERROR();
4491 }
4492 
4493 // Test that array indices for arrays of arrays of basic types work as expected.
TEST_P(GLSLTest_ES31,ArraysOfArraysBasicType)4494 TEST_P(GLSLTest_ES31, ArraysOfArraysBasicType)
4495 {
4496     constexpr char kFS[] =
4497         "#version 310 es\n"
4498         "precision mediump float;\n"
4499         "out vec4 my_FragColor;\n"
4500         "uniform ivec2 test[2][2];\n"
4501         "void main() {\n"
4502         "    bool passed = true;\n"
4503         "    for (int i = 0; i < 2; i++) {\n"
4504         "        for (int j = 0; j < 2; j++) {\n"
4505         "            if (test[i][j] != ivec2(i + 1, j + 1)) {\n"
4506         "                passed = false;\n"
4507         "            }\n"
4508         "        }\n"
4509         "    }\n"
4510         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4511         "}\n";
4512 
4513     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4514     glUseProgram(program.get());
4515     for (int i = 0; i < 2; i++)
4516     {
4517         for (int j = 0; j < 2; j++)
4518         {
4519             std::stringstream uniformName;
4520             uniformName << "test[" << i << "][" << j << "]";
4521             GLint uniformLocation = glGetUniformLocation(program.get(), uniformName.str().c_str());
4522             // All array indices should be used.
4523             EXPECT_NE(uniformLocation, -1);
4524             glUniform2i(uniformLocation, i + 1, j + 1);
4525         }
4526     }
4527     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
4528     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4529 }
4530 
4531 // Test that array indices for arrays of arrays of basic types work as expected
4532 // inside blocks.
TEST_P(GLSLTest_ES31,ArraysOfArraysBlockBasicType)4533 TEST_P(GLSLTest_ES31, ArraysOfArraysBlockBasicType)
4534 {
4535     // anglebug.com/3821 - fails on AMD Windows
4536     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL());
4537     constexpr char kFS[] =
4538         "#version 310 es\n"
4539         "precision mediump float;\n"
4540         "out vec4 my_FragColor;\n"
4541         "layout(packed) uniform UBO { ivec2 test[2][2]; } ubo_data;\n"
4542         "void main() {\n"
4543         "    bool passed = true;\n"
4544         "    for (int i = 0; i < 2; i++) {\n"
4545         "        for (int j = 0; j < 2; j++) {\n"
4546         "            if (ubo_data.test[i][j] != ivec2(i + 1, j + 1)) {\n"
4547         "                passed = false;\n"
4548         "            }\n"
4549         "        }\n"
4550         "    }\n"
4551         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4552         "}\n";
4553 
4554     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4555     glUseProgram(program.get());
4556     // Use interface queries to determine buffer size and offset
4557     GLuint uboBlockIndex   = glGetProgramResourceIndex(program.get(), GL_UNIFORM_BLOCK, "UBO");
4558     GLenum uboDataSizeProp = GL_BUFFER_DATA_SIZE;
4559     GLint uboDataSize;
4560     glGetProgramResourceiv(program.get(), GL_UNIFORM_BLOCK, uboBlockIndex, 1, &uboDataSizeProp, 1,
4561                            nullptr, &uboDataSize);
4562     std::unique_ptr<char[]> uboData(new char[uboDataSize]);
4563     for (int i = 0; i < 2; i++)
4564     {
4565         std::stringstream resourceName;
4566         resourceName << "UBO.test[" << i << "][0]";
4567         GLenum resourceProps[] = {GL_ARRAY_STRIDE, GL_OFFSET};
4568         struct
4569         {
4570             GLint stride;
4571             GLint offset;
4572         } values;
4573         GLuint resourceIndex =
4574             glGetProgramResourceIndex(program.get(), GL_UNIFORM, resourceName.str().c_str());
4575         ASSERT_NE(resourceIndex, GL_INVALID_INDEX);
4576         glGetProgramResourceiv(program.get(), GL_UNIFORM, resourceIndex, 2, &resourceProps[0], 2,
4577                                nullptr, &values.stride);
4578         for (int j = 0; j < 2; j++)
4579         {
4580             GLint(&dataPtr)[2] =
4581                 *reinterpret_cast<GLint(*)[2]>(&uboData[values.offset + j * values.stride]);
4582             dataPtr[0] = i + 1;
4583             dataPtr[1] = j + 1;
4584         }
4585     }
4586     GLBuffer ubo;
4587     glBindBuffer(GL_UNIFORM_BUFFER, ubo.get());
4588     glBufferData(GL_UNIFORM_BUFFER, uboDataSize, &uboData[0], GL_STATIC_DRAW);
4589     GLuint ubo_index = glGetUniformBlockIndex(program.get(), "UBO");
4590     ASSERT_NE(ubo_index, GL_INVALID_INDEX);
4591     glUniformBlockBinding(program.get(), ubo_index, 5);
4592     glBindBufferBase(GL_UNIFORM_BUFFER, 5, ubo.get());
4593     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
4594     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4595 }
4596 
4597 // Test that arrays of arrays of samplers work as expected.
TEST_P(GLSLTest_ES31,ArraysOfArraysSampler)4598 TEST_P(GLSLTest_ES31, ArraysOfArraysSampler)
4599 {
4600     constexpr char kFS[] =
4601         "#version 310 es\n"
4602         "precision mediump float;\n"
4603         "out vec4 my_FragColor;\n"
4604         "uniform mediump isampler2D test[2][2];\n"
4605         "void main() {\n"
4606         "    bool passed = true;\n"
4607         "#define DO_CHECK(i,j) \\\n"
4608         "    if (texture(test[i][j], vec2(0.0, 0.0)) != ivec4(i + 1, j + 1, 0, 1)) { \\\n"
4609         "        passed = false; \\\n"
4610         "    }\n"
4611         "    DO_CHECK(0, 0)\n"
4612         "    DO_CHECK(0, 1)\n"
4613         "    DO_CHECK(1, 0)\n"
4614         "    DO_CHECK(1, 1)\n"
4615         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4616         "}\n";
4617 
4618     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4619     glUseProgram(program.get());
4620     GLTexture textures[2][2];
4621     for (int i = 0; i < 2; i++)
4622     {
4623         for (int j = 0; j < 2; j++)
4624         {
4625             // First generate the texture
4626             int textureUnit = i * 2 + j;
4627             glActiveTexture(GL_TEXTURE0 + textureUnit);
4628             glBindTexture(GL_TEXTURE_2D, textures[i][j]);
4629             GLint texData[2] = {i + 1, j + 1};
4630             glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32I, 1, 1, 0, GL_RG_INTEGER, GL_INT, &texData[0]);
4631             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4632             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4633             // Then send it as a uniform
4634             std::stringstream uniformName;
4635             uniformName << "test[" << i << "][" << j << "]";
4636             GLint uniformLocation = glGetUniformLocation(program.get(), uniformName.str().c_str());
4637             // All array indices should be used.
4638             EXPECT_NE(uniformLocation, -1);
4639             glUniform1i(uniformLocation, textureUnit);
4640         }
4641     }
4642     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
4643     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4644 }
4645 
4646 // Test that arrays of arrays of images work as expected.
TEST_P(GLSLTest_ES31,ArraysOfArraysImage)4647 TEST_P(GLSLTest_ES31, ArraysOfArraysImage)
4648 {
4649     // http://anglebug.com/5072
4650     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
4651 
4652     // Fails on D3D due to mistranslation.
4653     ANGLE_SKIP_TEST_IF(IsD3D());
4654 
4655     // Fails on Android on GLES.
4656     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
4657 
4658     GLint maxTextures, maxComputeImageUniforms;
4659     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextures);
4660     glGetIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &maxComputeImageUniforms);
4661     ANGLE_SKIP_TEST_IF(maxTextures < 1 * 2 * 3);
4662     ANGLE_SKIP_TEST_IF(maxComputeImageUniforms < 1 * 2 * 3);
4663 
4664     constexpr char kComputeShader[] = R"(#version 310 es
4665         layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
4666         layout(binding = 0, r32ui) uniform highp readonly uimage2D image[1][2][3];
4667         layout(binding = 1, std430) buffer Output {
4668             uint image_value;
4669         } outbuf;
4670 
4671         void main(void)
4672         {
4673             outbuf.image_value = uint(0.0);
4674             outbuf.image_value += imageLoad(image[0][0][0], ivec2(0, 0)).x;
4675             outbuf.image_value += imageLoad(image[0][0][1], ivec2(0, 0)).x;
4676             outbuf.image_value += imageLoad(image[0][0][2], ivec2(0, 0)).x;
4677             outbuf.image_value += imageLoad(image[0][1][0], ivec2(0, 0)).x;
4678             outbuf.image_value += imageLoad(image[0][1][1], ivec2(0, 0)).x;
4679             outbuf.image_value += imageLoad(image[0][1][2], ivec2(0, 0)).x;
4680         })";
4681     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
4682     EXPECT_GL_NO_ERROR();
4683 
4684     glUseProgram(program);
4685 
4686     GLuint outputInitData[1] = {10};
4687     GLBuffer outputBuffer;
4688     glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
4689     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), outputInitData, GL_STATIC_DRAW);
4690     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
4691     EXPECT_GL_NO_ERROR();
4692 
4693     GLuint imageData = 200u;
4694     GLTexture images[1][2][3];
4695     for (int i = 0; i < 1; i++)
4696     {
4697         for (int j = 0; j < 2; j++)
4698         {
4699             for (int k = 0; k < 3; k++)
4700             {
4701                 glBindTexture(GL_TEXTURE_2D, images[i][j][k]);
4702                 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
4703                 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT,
4704                                 &imageData);
4705                 glBindImageTexture(i * 6 + j * 3 + k, images[i][j][k], 0, GL_FALSE, 0, GL_READ_ONLY,
4706                                    GL_R32UI);
4707                 EXPECT_GL_NO_ERROR();
4708             }
4709         }
4710     }
4711 
4712     glDispatchCompute(1, 1, 1);
4713     EXPECT_GL_NO_ERROR();
4714 
4715     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4716 
4717     // read back
4718     const GLuint *ptr = reinterpret_cast<const GLuint *>(
4719         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
4720     memcpy(outputInitData, ptr, sizeof(outputInitData));
4721     EXPECT_EQ(outputInitData[0], imageData * 1 * 2 * 3);
4722     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4723 }
4724 
4725 // Test that multiple arrays of arrays of images work as expected.
TEST_P(GLSLTest_ES31,ConsecutiveArraysOfArraysImage)4726 TEST_P(GLSLTest_ES31, ConsecutiveArraysOfArraysImage)
4727 {
4728     // http://anglebug.com/5072
4729     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
4730 
4731     // Fails on D3D due to mistranslation.
4732     ANGLE_SKIP_TEST_IF(IsD3D());
4733 
4734     constexpr GLsizei kImage1Layers = 3;
4735     constexpr GLsizei kImage1Rows   = 2;
4736     constexpr GLsizei kImage1Cols   = 1;
4737     constexpr GLsizei kImage2Rows   = 2;
4738     constexpr GLsizei kImage2Cols   = 4;
4739 
4740     constexpr GLsizei kImage1Units = kImage1Layers * kImage1Rows * kImage1Cols;
4741     constexpr GLsizei kImage2Units = kImage2Rows * kImage2Cols;
4742     constexpr GLsizei kImage3Units = 1;
4743 
4744     constexpr GLsizei kTotalImageCount = kImage1Units + kImage2Units + kImage3Units;
4745 
4746     GLint maxTextures, maxComputeImageUniforms;
4747     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextures);
4748     glGetIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &maxComputeImageUniforms);
4749     ANGLE_SKIP_TEST_IF(maxTextures < kTotalImageCount);
4750     ANGLE_SKIP_TEST_IF(maxComputeImageUniforms < kTotalImageCount);
4751 
4752     constexpr char kComputeShader[] = R"(#version 310 es
4753         layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
4754         layout(binding = 0, r32ui) uniform highp readonly uimage2D image1[3][2][1];
4755         layout(binding = 6, r32ui) uniform highp readonly uimage2D image2[2][4];
4756         layout(binding = 14, r32ui) uniform highp readonly uimage2D image3;
4757         layout(binding = 0, std430) buffer Output {
4758             uint image_value;
4759         } outbuf;
4760 
4761         void main(void)
4762         {
4763             outbuf.image_value = uint(0.0);
4764 
4765             outbuf.image_value += imageLoad(image1[0][0][0], ivec2(0, 0)).x;
4766             outbuf.image_value += imageLoad(image1[0][1][0], ivec2(0, 0)).x;
4767             outbuf.image_value += imageLoad(image1[1][0][0], ivec2(0, 0)).x;
4768             outbuf.image_value += imageLoad(image1[1][1][0], ivec2(0, 0)).x;
4769             outbuf.image_value += imageLoad(image1[2][0][0], ivec2(0, 0)).x;
4770             outbuf.image_value += imageLoad(image1[2][1][0], ivec2(0, 0)).x;
4771 
4772             outbuf.image_value += imageLoad(image2[0][0], ivec2(0, 0)).x;
4773             outbuf.image_value += imageLoad(image2[0][1], ivec2(0, 0)).x;
4774             outbuf.image_value += imageLoad(image2[0][2], ivec2(0, 0)).x;
4775             outbuf.image_value += imageLoad(image2[0][3], ivec2(0, 0)).x;
4776             outbuf.image_value += imageLoad(image2[1][0], ivec2(0, 0)).x;
4777             outbuf.image_value += imageLoad(image2[1][1], ivec2(0, 0)).x;
4778             outbuf.image_value += imageLoad(image2[1][2], ivec2(0, 0)).x;
4779             outbuf.image_value += imageLoad(image2[1][3], ivec2(0, 0)).x;
4780 
4781             outbuf.image_value += imageLoad(image3, ivec2(0, 0)).x;
4782         })";
4783     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
4784     EXPECT_GL_NO_ERROR();
4785 
4786     glUseProgram(program);
4787 
4788     constexpr GLuint kOutputInitData = 10;
4789     GLBuffer outputBuffer;
4790     glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
4791     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kOutputInitData), &kOutputInitData,
4792                  GL_STATIC_DRAW);
4793     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, outputBuffer);
4794     EXPECT_GL_NO_ERROR();
4795 
4796     constexpr GLsizei kImage1Binding = 0;
4797     constexpr GLsizei kImage2Binding = kImage1Binding + kImage1Units;
4798     constexpr GLsizei kImage3Binding = kImage2Binding + kImage2Units;
4799 
4800     constexpr GLuint kImage1Data = 13;
4801     GLTexture images1[kImage1Layers][kImage1Rows][kImage1Cols];
4802     for (int layer = 0; layer < kImage1Layers; layer++)
4803     {
4804         for (int row = 0; row < kImage1Rows; row++)
4805         {
4806             for (int col = 0; col < kImage1Cols; col++)
4807             {
4808                 glBindTexture(GL_TEXTURE_2D, images1[layer][row][col]);
4809                 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
4810                 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT,
4811                                 &kImage1Data);
4812                 glBindImageTexture(kImage1Binding + (layer * kImage1Rows + row) * kImage1Cols + col,
4813                                    images1[layer][row][col], 0, GL_FALSE, 0, GL_READ_ONLY,
4814                                    GL_R32UI);
4815                 EXPECT_GL_NO_ERROR();
4816             }
4817         }
4818     }
4819 
4820     constexpr GLuint kImage2Data = 17;
4821     GLTexture images2[kImage2Rows][kImage2Cols];
4822     for (int row = 0; row < kImage2Rows; row++)
4823     {
4824         for (int col = 0; col < kImage2Cols; col++)
4825         {
4826             glBindTexture(GL_TEXTURE_2D, images2[row][col]);
4827             glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
4828             glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT,
4829                             &kImage2Data);
4830             glBindImageTexture(kImage2Binding + row * kImage2Cols + col, images2[row][col], 0,
4831                                GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
4832             EXPECT_GL_NO_ERROR();
4833         }
4834     }
4835 
4836     constexpr GLuint kImage3Data = 19;
4837     GLTexture image3;
4838     glBindTexture(GL_TEXTURE_2D, image3);
4839     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
4840     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &kImage3Data);
4841     glBindImageTexture(kImage3Binding, image3, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
4842     EXPECT_GL_NO_ERROR();
4843 
4844     glDispatchCompute(1, 1, 1);
4845     EXPECT_GL_NO_ERROR();
4846 
4847     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4848 
4849     // read back
4850     const GLuint *ptr = reinterpret_cast<const GLuint *>(
4851         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kOutputInitData), GL_MAP_READ_BIT));
4852     EXPECT_EQ(*ptr,
4853               kImage1Data * kImage1Units + kImage2Data * kImage2Units + kImage3Data * kImage3Units);
4854     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4855 }
4856 
4857 // Test that arrays of arrays of images of r32f format work when passed to functions.
TEST_P(GLSLTest_ES31,ArraysOfArraysOfR32fImages)4858 TEST_P(GLSLTest_ES31, ArraysOfArraysOfR32fImages)
4859 {
4860     // Skip if GL_OES_shader_image_atomic is not enabled.
4861     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_image_atomic"));
4862 
4863     // http://anglebug.com/5072
4864     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
4865 
4866     // Fails on D3D due to mistranslation.
4867     ANGLE_SKIP_TEST_IF(IsD3D());
4868 
4869     // Fails on Android on GLES.
4870     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
4871 
4872     // http://anglebug.com/5353
4873     ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGL());
4874 
4875     GLint maxComputeImageUniforms;
4876     glGetIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &maxComputeImageUniforms);
4877     ANGLE_SKIP_TEST_IF(maxComputeImageUniforms < 7);
4878 
4879     constexpr char kComputeShader[] = R"(#version 310 es
4880 #extension GL_OES_shader_image_atomic : require
4881 
4882 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
4883 layout(binding = 0, r32f) uniform highp image2D image1[2][3];
4884 layout(binding = 6, r32f) uniform highp image2D image2;
4885 
4886 void testFunction(highp image2D imageOut[2][3])
4887 {
4888     // image1 is an array of 1x1 images.
4889     // image2 is a 1x4 image with the following data:
4890     //
4891     // (0, 0): 234.5
4892     // (0, 1): 4.0
4893     // (0, 2): 456.0
4894     // (0, 3): 987.0
4895 
4896 
4897     // Write to [0][0]
4898     imageStore(imageOut[0][0], ivec2(0, 0), vec4(1234.5));
4899 
4900     // Write to [0][1]
4901     imageStore(imageOut[0][1], ivec2(0, 0), imageLoad(image2, ivec2(0, 0)));
4902 
4903     // Write to [0][2]
4904     imageStore(imageOut[0][2], ivec2(0, 0), vec4(imageSize(image2).y));
4905 
4906     // Write to [1][0]
4907     imageStore(imageOut[1][0], ivec2(0,
4908                  imageSize(image2).y - int(imageLoad(image2, ivec2(0, 1)).x)
4909                 ), vec4(678.0));
4910 
4911     // Write to [1][1]
4912     imageStore(imageOut[1][1], ivec2(0, 0),
4913                 vec4(imageAtomicExchange(image2, ivec2(0, 2), 135.0)));
4914 
4915     // Write to [1][2]
4916     imageStore(imageOut[1][2], ivec2(0, 0),
4917                     imageLoad(image2, ivec2(imageSize(image2).x - 1, 3)));
4918 }
4919 
4920 void main(void)
4921 {
4922     testFunction(image1);
4923 })";
4924     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
4925     EXPECT_GL_NO_ERROR();
4926 
4927     glUseProgram(program);
4928 
4929     constexpr GLsizei kImageRows = 2;
4930     constexpr GLsizei kImageCols = 3;
4931     constexpr GLfloat kImageData = 0;
4932     GLTexture images[kImageRows][kImageCols];
4933     for (size_t row = 0; row < kImageRows; row++)
4934     {
4935         for (size_t col = 0; col < kImageCols; col++)
4936         {
4937             glBindTexture(GL_TEXTURE_2D, images[row][col]);
4938             glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, 1, 1);
4939             glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED, GL_FLOAT, &kImageData);
4940             glBindImageTexture(row * kImageCols + col, images[row][col], 0, GL_FALSE, 0,
4941                                GL_READ_WRITE, GL_R32F);
4942             EXPECT_GL_NO_ERROR();
4943         }
4944     }
4945 
4946     constexpr GLsizei kImage2Size                          = 4;
4947     constexpr std::array<GLfloat, kImage2Size> kImage2Data = {
4948         234.5f,
4949         4.0f,
4950         456.0f,
4951         987.0f,
4952     };
4953     GLTexture image2;
4954     glBindTexture(GL_TEXTURE_2D, image2);
4955     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, 1, kImage2Size);
4956     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, kImage2Size, GL_RED, GL_FLOAT, kImage2Data.data());
4957     glBindImageTexture(6, image2, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
4958     EXPECT_GL_NO_ERROR();
4959 
4960     glDispatchCompute(1, 1, 1);
4961     EXPECT_GL_NO_ERROR();
4962 
4963     glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4964 
4965     // Verify the previous dispatch with another dispatch
4966     constexpr char kVerifyShader[] = R"(#version 310 es
4967 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
4968 layout(binding = 0, r32f) uniform highp readonly image2D image1[2][3];
4969 layout(binding = 6, r32f) uniform highp readonly image2D image2;
4970 layout(binding = 0, std430) buffer Output {
4971     float image2Data[4];
4972     float image1Data[6];
4973 } outbuf;
4974 
4975 void main(void)
4976 {
4977     for (int i = 0; i < 4; ++i)
4978     {
4979         outbuf.image2Data[i] = imageLoad(image2, ivec2(0, i)).x;
4980     }
4981     outbuf.image1Data[0] = imageLoad(image1[0][0], ivec2(0, 0)).x;
4982     outbuf.image1Data[1] = imageLoad(image1[0][1], ivec2(0, 0)).x;
4983     outbuf.image1Data[2] = imageLoad(image1[0][2], ivec2(0, 0)).x;
4984     outbuf.image1Data[3] = imageLoad(image1[1][0], ivec2(0, 0)).x;
4985     outbuf.image1Data[4] = imageLoad(image1[1][1], ivec2(0, 0)).x;
4986     outbuf.image1Data[5] = imageLoad(image1[1][2], ivec2(0, 0)).x;
4987 })";
4988     ANGLE_GL_COMPUTE_PROGRAM(verifyProgram, kVerifyShader);
4989     EXPECT_GL_NO_ERROR();
4990 
4991     glUseProgram(verifyProgram);
4992 
4993     constexpr std::array<GLfloat, kImage2Size + kImageRows *kImageCols> kOutputInitData = {};
4994     GLBuffer outputBuffer;
4995     glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
4996     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kOutputInitData), kOutputInitData.data(),
4997                  GL_STATIC_DRAW);
4998     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, outputBuffer);
4999     EXPECT_GL_NO_ERROR();
5000 
5001     glDispatchCompute(1, 1, 1);
5002     EXPECT_GL_NO_ERROR();
5003 
5004     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5005 
5006     // Verify
5007     const GLfloat *ptr = reinterpret_cast<const GLfloat *>(
5008         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kOutputInitData), GL_MAP_READ_BIT));
5009 
5010     EXPECT_EQ(ptr[0], kImage2Data[0]);
5011     EXPECT_EQ(ptr[1], kImage2Data[1]);
5012     EXPECT_NEAR(ptr[2], 135.0f, 0.0001f);
5013     EXPECT_EQ(ptr[3], kImage2Data[3]);
5014 
5015     EXPECT_NEAR(ptr[4], 1234.5f, 0.0001f);
5016     EXPECT_NEAR(ptr[5], kImage2Data[0], 0.0001f);
5017     EXPECT_NEAR(ptr[6], kImage2Size, 0.0001f);
5018     EXPECT_NEAR(ptr[7], 678.0f, 0.0001f);
5019     EXPECT_NEAR(ptr[8], kImage2Data[2], 0.0001f);
5020     EXPECT_NEAR(ptr[9], kImage2Data[3], 0.0001f);
5021 
5022     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
5023 }
5024 
5025 // Test that structs containing arrays of samplers work as expected.
TEST_P(GLSLTest_ES31,StructArraySampler)5026 TEST_P(GLSLTest_ES31, StructArraySampler)
5027 {
5028     constexpr char kFS[] =
5029         "#version 310 es\n"
5030         "precision mediump float;\n"
5031         "out vec4 my_FragColor;\n"
5032         "struct Data { mediump sampler2D data[2]; };\n"
5033         "uniform Data test;\n"
5034         "void main() {\n"
5035         "    my_FragColor = vec4(texture(test.data[0], vec2(0.0, 0.0)).rg,\n"
5036         "                        texture(test.data[1], vec2(0.0, 0.0)).rg);\n"
5037         "}\n";
5038 
5039     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5040     glUseProgram(program.get());
5041     GLTexture textures[2];
5042     GLColor expected = MakeGLColor(32, 64, 96, 255);
5043     GLubyte data[6]  = {};  // Two bytes of padding, so that texture can be initialized with 4 bytes
5044     memcpy(data, expected.data(), sizeof(expected));
5045     for (int i = 0; i < 2; i++)
5046     {
5047         glActiveTexture(GL_TEXTURE0 + i);
5048         glBindTexture(GL_TEXTURE_2D, textures[i]);
5049         // Each element provides two components.
5050         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data + 2 * i);
5051         std::stringstream uniformName;
5052         uniformName << "test.data[" << i << "]";
5053         // Then send it as a uniform
5054         GLint uniformLocation = glGetUniformLocation(program.get(), uniformName.str().c_str());
5055         // The uniform should be active.
5056         EXPECT_NE(uniformLocation, -1);
5057         glUniform1i(uniformLocation, i);
5058     }
5059     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
5060     EXPECT_PIXEL_COLOR_EQ(0, 0, expected);
5061 }
5062 
5063 // Test that arrays of arrays of samplers inside structs work as expected.
TEST_P(GLSLTest_ES31,StructArrayArraySampler)5064 TEST_P(GLSLTest_ES31, StructArrayArraySampler)
5065 {
5066     constexpr char kFS[] =
5067         "#version 310 es\n"
5068         "precision mediump float;\n"
5069         "out vec4 my_FragColor;\n"
5070         "struct Data { mediump isampler2D data[2][2]; };\n"
5071         "uniform Data test;\n"
5072         "void main() {\n"
5073         "    bool passed = true;\n"
5074         "#define DO_CHECK(i,j) \\\n"
5075         "    if (texture(test.data[i][j], vec2(0.0, 0.0)) != ivec4(i + 1, j + 1, 0, 1)) { \\\n"
5076         "        passed = false; \\\n"
5077         "    }\n"
5078         "    DO_CHECK(0, 0)\n"
5079         "    DO_CHECK(0, 1)\n"
5080         "    DO_CHECK(1, 0)\n"
5081         "    DO_CHECK(1, 1)\n"
5082         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
5083         "}\n";
5084 
5085     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5086     glUseProgram(program.get());
5087     GLTexture textures[2][2];
5088     for (int i = 0; i < 2; i++)
5089     {
5090         for (int j = 0; j < 2; j++)
5091         {
5092             // First generate the texture
5093             int textureUnit = i * 2 + j;
5094             glActiveTexture(GL_TEXTURE0 + textureUnit);
5095             glBindTexture(GL_TEXTURE_2D, textures[i][j]);
5096             GLint texData[2] = {i + 1, j + 1};
5097             glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32I, 1, 1, 0, GL_RG_INTEGER, GL_INT, &texData[0]);
5098             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5099             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5100             // Then send it as a uniform
5101             std::stringstream uniformName;
5102             uniformName << "test.data[" << i << "][" << j << "]";
5103             GLint uniformLocation = glGetUniformLocation(program.get(), uniformName.str().c_str());
5104             // All array indices should be used.
5105             EXPECT_NE(uniformLocation, -1);
5106             glUniform1i(uniformLocation, textureUnit);
5107         }
5108     }
5109     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
5110     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5111 }
5112 
5113 // Test that an array of structs with arrays of arrays of samplers works.
TEST_P(GLSLTest_ES31,ArrayStructArrayArraySampler)5114 TEST_P(GLSLTest_ES31, ArrayStructArrayArraySampler)
5115 {
5116     GLint numTextures;
5117     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
5118     ANGLE_SKIP_TEST_IF(numTextures < 2 * (2 * 2 + 2 * 2));
5119     constexpr char kFS[] =
5120         "#version 310 es\n"
5121         "precision mediump float;\n"
5122         "out vec4 my_FragColor;\n"
5123         "struct Data { mediump isampler2D data0[2][2]; mediump isampler2D data1[2][2]; };\n"
5124         "uniform Data test[2];\n"
5125         "void main() {\n"
5126         "    bool passed = true;\n"
5127         "#define DO_CHECK_ikl(i,k,l) \\\n"
5128         "    if (texture(test[i].data0[k][l], vec2(0.0, 0.0)) != ivec4(i, 0, k, l)+1) { \\\n"
5129         "        passed = false; \\\n"
5130         "    } \\\n"
5131         "    if (texture(test[i].data1[k][l], vec2(0.0, 0.0)) != ivec4(i, 1, k, l)+1) { \\\n"
5132         "        passed = false; \\\n"
5133         "    }\n"
5134         "#define DO_CHECK_ik(i,k) \\\n"
5135         "    DO_CHECK_ikl(i, k, 0) \\\n"
5136         "    DO_CHECK_ikl(i, k, 1)\n"
5137         "#define DO_CHECK_i(i) \\\n"
5138         "    DO_CHECK_ik(i, 0) \\\n"
5139         "    DO_CHECK_ik(i, 1)\n"
5140         "    DO_CHECK_i(0)\n"
5141         "    DO_CHECK_i(1)\n"
5142         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
5143         "}\n";
5144 
5145     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5146     glUseProgram(program.get());
5147     GLTexture textures[2][2][2][2];
5148     for (int i = 0; i < 2; i++)
5149     {
5150         for (int j = 0; j < 2; j++)
5151         {
5152             for (int k = 0; k < 2; k++)
5153             {
5154                 for (int l = 0; l < 2; l++)
5155                 {
5156                     // First generate the texture
5157                     int textureUnit = l + 2 * (k + 2 * (j + 2 * i));
5158                     glActiveTexture(GL_TEXTURE0 + textureUnit);
5159                     glBindTexture(GL_TEXTURE_2D, textures[i][j][k][l]);
5160                     GLint texData[4] = {i + 1, j + 1, k + 1, l + 1};
5161                     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT,
5162                                  &texData[0]);
5163                     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5164                     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5165                     // Then send it as a uniform
5166                     std::stringstream uniformName;
5167                     uniformName << "test[" << i << "].data" << j << "[" << k << "][" << l << "]";
5168                     GLint uniformLocation =
5169                         glGetUniformLocation(program.get(), uniformName.str().c_str());
5170                     // All array indices should be used.
5171                     EXPECT_NE(uniformLocation, -1);
5172                     glUniform1i(uniformLocation, textureUnit);
5173                 }
5174             }
5175         }
5176     }
5177     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
5178     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5179 }
5180 
5181 // Test that a complex chain of structs and arrays of samplers works as expected.
TEST_P(GLSLTest_ES31,ComplexStructArraySampler)5182 TEST_P(GLSLTest_ES31, ComplexStructArraySampler)
5183 {
5184     GLint numTextures;
5185     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
5186     ANGLE_SKIP_TEST_IF(numTextures < 2 * 3 * (2 + 3));
5187     constexpr char kFS[] =
5188         "#version 310 es\n"
5189         "precision mediump float;\n"
5190         "out vec4 my_FragColor;\n"
5191         "struct Data { mediump isampler2D data0[2]; mediump isampler2D data1[3]; };\n"
5192         "uniform Data test[2][3];\n"
5193         "const vec2 ZERO = vec2(0.0, 0.0);\n"
5194         "void main() {\n"
5195         "    bool passed = true;\n"
5196         "#define DO_CHECK_INNER0(i,j,l) \\\n"
5197         "    if (texture(test[i][j].data0[l], ZERO) != ivec4(i, j, 0, l) + 1) { \\\n"
5198         "        passed = false; \\\n"
5199         "    }\n"
5200         "#define DO_CHECK_INNER1(i,j,l) \\\n"
5201         "    if (texture(test[i][j].data1[l], ZERO) != ivec4(i, j, 1, l) + 1) { \\\n"
5202         "        passed = false; \\\n"
5203         "    }\n"
5204         "#define DO_CHECK(i,j) \\\n"
5205         "    DO_CHECK_INNER0(i, j, 0) \\\n"
5206         "    DO_CHECK_INNER0(i, j, 1) \\\n"
5207         "    DO_CHECK_INNER1(i, j, 0) \\\n"
5208         "    DO_CHECK_INNER1(i, j, 1) \\\n"
5209         "    DO_CHECK_INNER1(i, j, 2)\n"
5210         "    DO_CHECK(0, 0)\n"
5211         "    DO_CHECK(0, 1)\n"
5212         "    DO_CHECK(0, 2)\n"
5213         "    DO_CHECK(1, 0)\n"
5214         "    DO_CHECK(1, 1)\n"
5215         "    DO_CHECK(1, 2)\n"
5216         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
5217         "}\n";
5218 
5219     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5220     glUseProgram(program.get());
5221     struct Data
5222     {
5223         GLTexture data1[2];
5224         GLTexture data2[3];
5225     };
5226     Data textures[2][3];
5227     for (int i = 0; i < 2; i++)
5228     {
5229         for (int j = 0; j < 3; j++)
5230         {
5231             GLTexture *arrays[]     = {&textures[i][j].data1[0], &textures[i][j].data2[0]};
5232             size_t arrayLengths[]   = {2, 3};
5233             size_t arrayOffsets[]   = {0, 2};
5234             size_t totalArrayLength = 5;
5235             for (int k = 0; k < 2; k++)
5236             {
5237                 GLTexture *array   = arrays[k];
5238                 size_t arrayLength = arrayLengths[k];
5239                 size_t arrayOffset = arrayOffsets[k];
5240                 for (int l = 0; l < static_cast<int>(arrayLength); l++)
5241                 {
5242                     // First generate the texture
5243                     int textureUnit = arrayOffset + l + totalArrayLength * (j + 3 * i);
5244                     glActiveTexture(GL_TEXTURE0 + textureUnit);
5245                     glBindTexture(GL_TEXTURE_2D, array[l]);
5246                     GLint texData[4] = {i + 1, j + 1, k + 1, l + 1};
5247                     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT,
5248                                  &texData[0]);
5249                     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5250                     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5251                     // Then send it as a uniform
5252                     std::stringstream uniformName;
5253                     uniformName << "test[" << i << "][" << j << "].data" << k << "[" << l << "]";
5254                     GLint uniformLocation =
5255                         glGetUniformLocation(program.get(), uniformName.str().c_str());
5256                     // All array indices should be used.
5257                     EXPECT_NE(uniformLocation, -1);
5258                     glUniform1i(uniformLocation, textureUnit);
5259                 }
5260             }
5261         }
5262     }
5263     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
5264     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5265 }
5266 
TEST_P(GLSLTest_ES31,ArraysOfArraysStructDifferentTypesSampler)5267 TEST_P(GLSLTest_ES31, ArraysOfArraysStructDifferentTypesSampler)
5268 {
5269     GLint numTextures;
5270     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
5271     ANGLE_SKIP_TEST_IF(numTextures < 3 * (2 + 2));
5272     constexpr char kFS[] =
5273         "#version 310 es\n"
5274         "precision mediump float;\n"
5275         "out vec4 my_FragColor;\n"
5276         "struct Data { mediump isampler2D data0[2]; mediump sampler2D data1[2]; };\n"
5277         "uniform Data test[3];\n"
5278         "ivec4 f2i(vec4 x) { return ivec4(x * 4.0 + 0.5); }"
5279         "void main() {\n"
5280         "    bool passed = true;\n"
5281         "#define DO_CHECK_ik(i,k) \\\n"
5282         "    if (texture(test[i].data0[k], vec2(0.0, 0.0)) != ivec4(i, 0, k, 0)+1) { \\\n"
5283         "        passed = false; \\\n"
5284         "    } \\\n"
5285         "    if (f2i(texture(test[i].data1[k], vec2(0.0, 0.0))) != ivec4(i, 1, k, 0)+1) { \\\n"
5286         "        passed = false; \\\n"
5287         "    }\n"
5288         "#define DO_CHECK_i(i) \\\n"
5289         "    DO_CHECK_ik(i, 0) \\\n"
5290         "    DO_CHECK_ik(i, 1)\n"
5291         "    DO_CHECK_i(0)\n"
5292         "    DO_CHECK_i(1)\n"
5293         "    DO_CHECK_i(2)\n"
5294         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
5295         "}\n";
5296 
5297     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5298     glUseProgram(program.get());
5299     GLTexture textures[3][2][2];
5300     for (int i = 0; i < 3; i++)
5301     {
5302         for (int j = 0; j < 2; j++)
5303         {
5304             for (int k = 0; k < 2; k++)
5305             {
5306                 // First generate the texture
5307                 int textureUnit = k + 2 * (j + 2 * i);
5308                 glActiveTexture(GL_TEXTURE0 + textureUnit);
5309                 glBindTexture(GL_TEXTURE_2D, textures[i][j][k]);
5310                 GLint texData[4]        = {i + 1, j + 1, k + 1, 1};
5311                 GLubyte texDataFloat[4] = {static_cast<GLubyte>((i + 1) * 64 - 1),
5312                                            static_cast<GLubyte>((j + 1) * 64 - 1),
5313                                            static_cast<GLubyte>((k + 1) * 64 - 1), 64};
5314                 if (j == 0)
5315                 {
5316                     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT,
5317                                  &texData[0]);
5318                 }
5319                 else
5320                 {
5321                     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5322                                  &texDataFloat[0]);
5323                 }
5324                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5325                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5326                 // Then send it as a uniform
5327                 std::stringstream uniformName;
5328                 uniformName << "test[" << i << "].data" << j << "[" << k << "]";
5329                 GLint uniformLocation =
5330                     glGetUniformLocation(program.get(), uniformName.str().c_str());
5331                 // All array indices should be used.
5332                 EXPECT_NE(uniformLocation, -1);
5333                 glUniform1i(uniformLocation, textureUnit);
5334             }
5335         }
5336     }
5337     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
5338     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5339 }
5340 
5341 // Test that arrays of arrays of samplers as parameters works as expected.
TEST_P(GLSLTest_ES31,ParameterArraysOfArraysSampler)5342 TEST_P(GLSLTest_ES31, ParameterArraysOfArraysSampler)
5343 {
5344     // anglebug.com/3832 - no sampler array params on Android
5345     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
5346 
5347     constexpr char kFS[] =
5348         "#version 310 es\n"
5349         "precision mediump float;\n"
5350         "out vec4 my_FragColor;\n"
5351         "uniform mediump isampler2D test[2][3];\n"
5352         "const vec2 ZERO = vec2(0.0, 0.0);\n"
5353         "\n"
5354         "bool check(mediump isampler2D data[2][3]);\n"
5355         "bool check(mediump isampler2D data[2][3]) {\n"
5356         "#define DO_CHECK(i,j) \\\n"
5357         "    if (texture(data[i][j], ZERO) != ivec4(i+1, j+1, 0, 1)) { \\\n"
5358         "        return false; \\\n"
5359         "    }\n"
5360         "    DO_CHECK(0, 0)\n"
5361         "    DO_CHECK(0, 1)\n"
5362         "    DO_CHECK(0, 2)\n"
5363         "    DO_CHECK(1, 0)\n"
5364         "    DO_CHECK(1, 1)\n"
5365         "    DO_CHECK(1, 2)\n"
5366         "    return true;\n"
5367         "}\n"
5368         "void main() {\n"
5369         "    bool passed = check(test);\n"
5370         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
5371         "}\n";
5372 
5373     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5374     glUseProgram(program.get());
5375     GLTexture textures[2][3];
5376     for (int i = 0; i < 2; i++)
5377     {
5378         for (int j = 0; j < 3; j++)
5379         {
5380             // First generate the texture
5381             int textureUnit = i * 3 + j;
5382             glActiveTexture(GL_TEXTURE0 + textureUnit);
5383             glBindTexture(GL_TEXTURE_2D, textures[i][j]);
5384             GLint texData[2] = {i + 1, j + 1};
5385             glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32I, 1, 1, 0, GL_RG_INTEGER, GL_INT, &texData[0]);
5386             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5387             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5388             // Then send it as a uniform
5389             std::stringstream uniformName;
5390             uniformName << "test[" << i << "][" << j << "]";
5391             GLint uniformLocation = glGetUniformLocation(program.get(), uniformName.str().c_str());
5392             // All array indices should be used.
5393             EXPECT_NE(uniformLocation, -1);
5394             glUniform1i(uniformLocation, textureUnit);
5395         }
5396     }
5397     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
5398     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5399 }
5400 
5401 // Test that structs with arrays of arrays of samplers as parameters works as expected.
TEST_P(GLSLTest_ES31,ParameterStructArrayArraySampler)5402 TEST_P(GLSLTest_ES31, ParameterStructArrayArraySampler)
5403 {
5404     // anglebug.com/3832 - no sampler array params on Android
5405     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
5406 
5407     constexpr char kFS[] =
5408         "#version 310 es\n"
5409         "precision mediump float;\n"
5410         "out vec4 my_FragColor;\n"
5411         "struct Data { mediump isampler2D data[2][3]; };\n"
5412         "uniform Data test;\n"
5413         "const vec2 ZERO = vec2(0.0, 0.0);\n"
5414         "\n"
5415         "bool check(Data data) {\n"
5416         "#define DO_CHECK(i,j) \\\n"
5417         "    if (texture(data.data[i][j], ZERO) != ivec4(i+1, j+1, 0, 1)) { \\\n"
5418         "        return false; \\\n"
5419         "    }\n"
5420         "    DO_CHECK(0, 0)\n"
5421         "    DO_CHECK(0, 1)\n"
5422         "    DO_CHECK(0, 2)\n"
5423         "    DO_CHECK(1, 0)\n"
5424         "    DO_CHECK(1, 1)\n"
5425         "    DO_CHECK(1, 2)\n"
5426         "    return true;\n"
5427         "}\n"
5428         "void main() {\n"
5429         "    bool passed = check(test);\n"
5430         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
5431         "}\n";
5432 
5433     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5434     glUseProgram(program.get());
5435     GLTexture textures[2][3];
5436     for (int i = 0; i < 2; i++)
5437     {
5438         for (int j = 0; j < 3; j++)
5439         {
5440             // First generate the texture
5441             int textureUnit = i * 3 + j;
5442             glActiveTexture(GL_TEXTURE0 + textureUnit);
5443             glBindTexture(GL_TEXTURE_2D, textures[i][j]);
5444             GLint texData[2] = {i + 1, j + 1};
5445             glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32I, 1, 1, 0, GL_RG_INTEGER, GL_INT, &texData[0]);
5446             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5447             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5448             // Then send it as a uniform
5449             std::stringstream uniformName;
5450             uniformName << "test.data[" << i << "][" << j << "]";
5451             GLint uniformLocation = glGetUniformLocation(program.get(), uniformName.str().c_str());
5452             // All array indices should be used.
5453             EXPECT_NE(uniformLocation, -1);
5454             glUniform1i(uniformLocation, textureUnit);
5455         }
5456     }
5457     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
5458     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5459 }
5460 
5461 // Test that arrays of arrays of structs with arrays of arrays of samplers
5462 // as parameters works as expected.
TEST_P(GLSLTest_ES31,ParameterArrayArrayStructArrayArraySampler)5463 TEST_P(GLSLTest_ES31, ParameterArrayArrayStructArrayArraySampler)
5464 {
5465     // anglebug.com/3832 - no sampler array params on Android
5466     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
5467 
5468     GLint numTextures;
5469     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
5470     ANGLE_SKIP_TEST_IF(numTextures < 3 * 2 * 2 * 2);
5471     constexpr char kFS[] =
5472         "#version 310 es\n"
5473         "precision mediump float;\n"
5474         "out vec4 my_FragColor;\n"
5475         "struct Data { mediump isampler2D data[2][2]; };\n"
5476         "uniform Data test[3][2];\n"
5477         "const vec2 ZERO = vec2(0.0, 0.0);\n"
5478         "\n"
5479         "bool check(Data data[3][2]) {\n"
5480         "#define DO_CHECK_ijkl(i,j,k,l) \\\n"
5481         "    if (texture(data[i][j].data[k][l], ZERO) != ivec4(i, j, k, l) + 1) { \\\n"
5482         "        return false; \\\n"
5483         "    }\n"
5484         "#define DO_CHECK_ij(i,j) \\\n"
5485         "    DO_CHECK_ijkl(i, j, 0, 0) \\\n"
5486         "    DO_CHECK_ijkl(i, j, 0, 1) \\\n"
5487         "    DO_CHECK_ijkl(i, j, 1, 0) \\\n"
5488         "    DO_CHECK_ijkl(i, j, 1, 1)\n"
5489         "    DO_CHECK_ij(0, 0)\n"
5490         "    DO_CHECK_ij(1, 0)\n"
5491         "    DO_CHECK_ij(2, 0)\n"
5492         "    DO_CHECK_ij(0, 1)\n"
5493         "    DO_CHECK_ij(1, 1)\n"
5494         "    DO_CHECK_ij(2, 1)\n"
5495         "    return true;\n"
5496         "}\n"
5497         "void main() {\n"
5498         "    bool passed = check(test);\n"
5499         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
5500         "}\n";
5501 
5502     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5503     glUseProgram(program.get());
5504     GLTexture textures[3][2][2][2];
5505     for (int i = 0; i < 3; i++)
5506     {
5507         for (int j = 0; j < 2; j++)
5508         {
5509             for (int k = 0; k < 2; k++)
5510             {
5511                 for (int l = 0; l < 2; l++)
5512                 {
5513                     // First generate the texture
5514                     int textureUnit = l + 2 * (k + 2 * (j + 2 * i));
5515                     glActiveTexture(GL_TEXTURE0 + textureUnit);
5516                     glBindTexture(GL_TEXTURE_2D, textures[i][j][k][l]);
5517                     GLint texData[4] = {i + 1, j + 1, k + 1, l + 1};
5518                     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT,
5519                                  &texData[0]);
5520                     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5521                     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5522                     // Then send it as a uniform
5523                     std::stringstream uniformName;
5524                     uniformName << "test[" << i << "][" << j << "].data[" << k << "][" << l << "]";
5525                     GLint uniformLocation =
5526                         glGetUniformLocation(program.get(), uniformName.str().c_str());
5527                     // All array indices should be used.
5528                     EXPECT_NE(uniformLocation, -1);
5529                     glUniform1i(uniformLocation, textureUnit);
5530                 }
5531             }
5532         }
5533     }
5534     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
5535     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5536 }
5537 
5538 // Test that 3D arrays with sub-arrays passed as parameters works as expected.
TEST_P(GLSLTest_ES31,ParameterArrayArrayArraySampler)5539 TEST_P(GLSLTest_ES31, ParameterArrayArrayArraySampler)
5540 {
5541     GLint numTextures;
5542     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
5543     ANGLE_SKIP_TEST_IF(numTextures < 2 * 3 * 4 + 4);
5544 
5545     // anglebug.com/3832 - no sampler array params on Android
5546     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
5547 
5548     // http://anglebug.com/5546
5549     ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
5550 
5551     constexpr char kFS[] =
5552         "#version 310 es\n"
5553         "precision mediump float;\n"
5554         "out vec4 my_FragColor;\n"
5555         "uniform mediump isampler2D test[2][3][4];\n"
5556         "uniform mediump isampler2D test2[4];\n"
5557         "const vec2 ZERO = vec2(0.0, 0.0);\n"
5558         "\n"
5559         "bool check1D(mediump isampler2D arr[4], int x, int y) {\n"
5560         "    if (texture(arr[0], ZERO) != ivec4(x, y, 0, 0)+1) return false;\n"
5561         "    if (texture(arr[1], ZERO) != ivec4(x, y, 1, 0)+1) return false;\n"
5562         "    if (texture(arr[2], ZERO) != ivec4(x, y, 2, 0)+1) return false;\n"
5563         "    if (texture(arr[3], ZERO) != ivec4(x, y, 3, 0)+1) return false;\n"
5564         "    return true;\n"
5565         "}\n"
5566         "bool check2D(mediump isampler2D arr[3][4], int x) {\n"
5567         "    if (!check1D(arr[0], x, 0)) return false;\n"
5568         "    if (!check1D(arr[1], x, 1)) return false;\n"
5569         "    if (!check1D(arr[2], x, 2)) return false;\n"
5570         "    return true;\n"
5571         "}\n"
5572         "bool check3D(mediump isampler2D arr[2][3][4]) {\n"
5573         "    if (!check2D(arr[0], 0)) return false;\n"
5574         "    if (!check2D(arr[1], 1)) return false;\n"
5575         "    return true;\n"
5576         "}\n"
5577         "void main() {\n"
5578         "    bool passed = check3D(test) && check1D(test2, 7, 8);\n"
5579         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
5580         "}\n";
5581 
5582     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5583     glUseProgram(program.get());
5584     GLTexture textures1[2][3][4];
5585     GLTexture textures2[4];
5586     for (int i = 0; i < 2; i++)
5587     {
5588         for (int j = 0; j < 3; j++)
5589         {
5590             for (int k = 0; k < 4; k++)
5591             {
5592                 // First generate the texture
5593                 int textureUnit = k + 4 * (j + 3 * i);
5594                 glActiveTexture(GL_TEXTURE0 + textureUnit);
5595                 glBindTexture(GL_TEXTURE_2D, textures1[i][j][k]);
5596                 GLint texData[3] = {i + 1, j + 1, k + 1};
5597                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32I, 1, 1, 0, GL_RGB_INTEGER, GL_INT,
5598                              &texData[0]);
5599                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5600                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5601                 // Then send it as a uniform
5602                 std::stringstream uniformName;
5603                 uniformName << "test[" << i << "][" << j << "][" << k << "]";
5604                 GLint uniformLocation =
5605                     glGetUniformLocation(program.get(), uniformName.str().c_str());
5606                 // All array indices should be used.
5607                 EXPECT_NE(uniformLocation, -1);
5608                 glUniform1i(uniformLocation, textureUnit);
5609             }
5610         }
5611     }
5612     for (int k = 0; k < 4; k++)
5613     {
5614         // First generate the texture
5615         int textureUnit = 2 * 3 * 4 + k;
5616         glActiveTexture(GL_TEXTURE0 + textureUnit);
5617         glBindTexture(GL_TEXTURE_2D, textures2[k]);
5618         GLint texData[3] = {7 + 1, 8 + 1, k + 1};
5619         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32I, 1, 1, 0, GL_RGB_INTEGER, GL_INT, &texData[0]);
5620         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5621         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5622         // Then send it as a uniform
5623         std::stringstream uniformName;
5624         uniformName << "test2[" << k << "]";
5625         GLint uniformLocation = glGetUniformLocation(program.get(), uniformName.str().c_str());
5626         // All array indices should be used.
5627         EXPECT_NE(uniformLocation, -1);
5628         glUniform1i(uniformLocation, textureUnit);
5629     }
5630     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
5631     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5632 }
5633 
5634 // Test that names do not collide when translating arrays of arrays of samplers.
TEST_P(GLSLTest_ES31,ArraysOfArraysNameCollisionSampler)5635 TEST_P(GLSLTest_ES31, ArraysOfArraysNameCollisionSampler)
5636 {
5637     ANGLE_SKIP_TEST_IF(IsVulkan());  // anglebug.com/3604 - rewriter can create name collisions
5638     GLint numTextures;
5639     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
5640     ANGLE_SKIP_TEST_IF(numTextures < 2 * 2 + 3 * 3 + 4 * 4);
5641     // anglebug.com/3832 - no sampler array params on Android
5642     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
5643     constexpr char kFS[] =
5644         "#version 310 es\n"
5645         "precision mediump sampler2D;\n"
5646         "precision mediump float;\n"
5647         "uniform sampler2D test_field1_field2[2][2];\n"
5648         "struct S1 { sampler2D field2[3][3]; }; uniform S1 test_field1;\n"
5649         "struct S2 { sampler2D field1_field2[4][4]; }; uniform S2 test;\n"
5650         "vec4 func1(sampler2D param_field1_field2[2][2],\n"
5651         "           int param_field1_field2_offset,\n"
5652         "           S1 param_field1,\n"
5653         "           S2 param) {\n"
5654         "    return vec4(0.0, 1.0, 0.0, 0.0);\n"
5655         "}\n"
5656         "out vec4 my_FragColor;\n"
5657         "void main() {\n"
5658         "    my_FragColor = vec4(0.0, 0.0, 0.0, 1.0);\n"
5659         "    my_FragColor += func1(test_field1_field2, 0, test_field1, test);\n"
5660         "    vec2 uv = vec2(0.0);\n"
5661         "    my_FragColor += texture(test_field1_field2[0][0], uv) +\n"
5662         "                    texture(test_field1.field2[0][0], uv) +\n"
5663         "                    texture(test.field1_field2[0][0], uv);\n"
5664         "}\n";
5665     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5666     glActiveTexture(GL_TEXTURE0);
5667     GLTexture tex;
5668     glBindTexture(GL_TEXTURE_2D, tex);
5669     GLint zero = 0;
5670     glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 1, 1, 0, GL_RED, GL_UNSIGNED_BYTE, &zero);
5671     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
5672     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5673 }
5674 
5675 // Test that regular arrays are unmodified.
TEST_P(GLSLTest_ES31,BasicTypeArrayAndArrayOfSampler)5676 TEST_P(GLSLTest_ES31, BasicTypeArrayAndArrayOfSampler)
5677 {
5678     constexpr char kFS[] =
5679         "#version 310 es\n"
5680         "precision mediump sampler2D;\n"
5681         "precision mediump float;\n"
5682         "uniform sampler2D sampler_array[2][2];\n"
5683         "uniform int array[3][2];\n"
5684         "vec4 func1(int param[2],\n"
5685         "           int param2[3]) {\n"
5686         "    return vec4(0.0, 1.0, 0.0, 0.0);\n"
5687         "}\n"
5688         "out vec4 my_FragColor;\n"
5689         "void main() {\n"
5690         "    my_FragColor = texture(sampler_array[0][0], vec2(0.0));\n"
5691         "    my_FragColor += func1(array[1], int[](1, 2, 3));\n"
5692         "}\n";
5693     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5694     glActiveTexture(GL_TEXTURE0);
5695     GLTexture tex;
5696     glBindTexture(GL_TEXTURE_2D, tex);
5697     GLint zero = 0;
5698     glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 1, 1, 0, GL_RED, GL_UNSIGNED_BYTE, &zero);
5699     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.5f);
5700     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5701 }
5702 
5703 // This test covers a bug (and associated workaround) with nested sampling operations in the HLSL
5704 // compiler DLL.
TEST_P(GLSLTest_ES3,NestedSamplingOperation)5705 TEST_P(GLSLTest_ES3, NestedSamplingOperation)
5706 {
5707     // This seems to be bugged on some version of Android. Might not affect the newest versions.
5708     // TODO(jmadill): Lift suppression when Chromium bots are upgraded.
5709     // Test skipped on Android because of bug with Nexus 5X.
5710     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
5711 
5712     constexpr char kVS[] =
5713         "#version 300 es\n"
5714         "out vec2 texCoord;\n"
5715         "in vec2 position;\n"
5716         "void main()\n"
5717         "{\n"
5718         "    gl_Position = vec4(position, 0, 1);\n"
5719         "    texCoord = position * 0.5 + vec2(0.5);\n"
5720         "}\n";
5721 
5722     constexpr char kSimpleFS[] =
5723         "#version 300 es\n"
5724         "in mediump vec2 texCoord;\n"
5725         "out mediump vec4 fragColor;\n"
5726         "void main()\n"
5727         "{\n"
5728         "    fragColor = vec4(texCoord, 0, 1);\n"
5729         "}\n";
5730 
5731     constexpr char kNestedFS[] =
5732         "#version 300 es\n"
5733         "uniform mediump sampler2D samplerA;\n"
5734         "uniform mediump sampler2D samplerB;\n"
5735         "in mediump vec2 texCoord;\n"
5736         "out mediump vec4 fragColor;\n"
5737         "void main ()\n"
5738         "{\n"
5739         "    fragColor = texture(samplerB, texture(samplerA, texCoord).xy);\n"
5740         "}\n";
5741 
5742     ANGLE_GL_PROGRAM(initProg, kVS, kSimpleFS);
5743     ANGLE_GL_PROGRAM(nestedProg, kVS, kNestedFS);
5744 
5745     // Initialize a first texture with default texCoord data.
5746     GLTexture texA;
5747     glActiveTexture(GL_TEXTURE0);
5748     glBindTexture(GL_TEXTURE_2D, texA);
5749     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
5750                  GL_UNSIGNED_BYTE, nullptr);
5751     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5752     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5753 
5754     GLFramebuffer fbo;
5755     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5756     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texA, 0);
5757 
5758     drawQuad(initProg, "position", 0.5f);
5759     ASSERT_GL_NO_ERROR();
5760 
5761     // Initialize a second texture with a simple color pattern.
5762     GLTexture texB;
5763     glActiveTexture(GL_TEXTURE1);
5764     glBindTexture(GL_TEXTURE_2D, texB);
5765 
5766     std::array<GLColor, 4> simpleColors = {
5767         {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
5768     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5769                  simpleColors.data());
5770     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5771     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5772 
5773     // Draw with the nested program, using the first texture to index the second.
5774     glBindFramebuffer(GL_FRAMEBUFFER, 0);
5775     glUseProgram(nestedProg);
5776     GLint samplerALoc = glGetUniformLocation(nestedProg, "samplerA");
5777     ASSERT_NE(-1, samplerALoc);
5778     glUniform1i(samplerALoc, 0);
5779     GLint samplerBLoc = glGetUniformLocation(nestedProg, "samplerB");
5780     ASSERT_NE(-1, samplerBLoc);
5781     glUniform1i(samplerBLoc, 1);
5782 
5783     drawQuad(nestedProg, "position", 0.5f);
5784     ASSERT_GL_NO_ERROR();
5785 
5786     // Compute four texel centers.
5787     Vector2 windowSize(getWindowWidth(), getWindowHeight());
5788     Vector2 quarterWindowSize = windowSize / 4;
5789     Vector2 ul                = quarterWindowSize;
5790     Vector2 ur(windowSize.x() - quarterWindowSize.x(), quarterWindowSize.y());
5791     Vector2 ll(quarterWindowSize.x(), windowSize.y() - quarterWindowSize.y());
5792     Vector2 lr = windowSize - quarterWindowSize;
5793 
5794     EXPECT_PIXEL_COLOR_EQ_VEC2(ul, simpleColors[0]);
5795     EXPECT_PIXEL_COLOR_EQ_VEC2(ur, simpleColors[1]);
5796     EXPECT_PIXEL_COLOR_EQ_VEC2(ll, simpleColors[2]);
5797     EXPECT_PIXEL_COLOR_EQ_VEC2(lr, simpleColors[3]);
5798 }
5799 
5800 // Tests that using a constant declaration as the only statement in a for loop without curly braces
5801 // doesn't crash.
TEST_P(GLSLTest,ConstantStatementInForLoop)5802 TEST_P(GLSLTest, ConstantStatementInForLoop)
5803 {
5804     constexpr char kVS[] =
5805         "void main()\n"
5806         "{\n"
5807         "    for (int i = 0; i < 10; ++i)\n"
5808         "        const int b = 0;\n"
5809         "}\n";
5810 
5811     GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
5812     EXPECT_NE(0u, shader);
5813     glDeleteShader(shader);
5814 }
5815 
5816 // Tests that using a constant declaration as a loop init expression doesn't crash. Note that this
5817 // test doesn't work on D3D9 due to looping limitations, so it is only run on ES3.
TEST_P(GLSLTest_ES3,ConstantStatementAsLoopInit)5818 TEST_P(GLSLTest_ES3, ConstantStatementAsLoopInit)
5819 {
5820     constexpr char kVS[] =
5821         "void main()\n"
5822         "{\n"
5823         "    for (const int i = 0; i < 0;) {}\n"
5824         "}\n";
5825 
5826     GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
5827     EXPECT_NE(0u, shader);
5828     glDeleteShader(shader);
5829 }
5830 
5831 // Test that uninitialized local variables are initialized to 0.
TEST_P(WebGL2GLSLTest,InitUninitializedLocals)5832 TEST_P(WebGL2GLSLTest, InitUninitializedLocals)
5833 {
5834     // Test skipped on Android GLES because local variable initialization is disabled.
5835     // http://anglebug.com/2046
5836     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
5837 
5838     constexpr char kFS[] =
5839         "#version 300 es\n"
5840         "precision mediump float;\n"
5841         "out vec4 my_FragColor;\n"
5842         "int result = 0;\n"
5843         "void main()\n"
5844         "{\n"
5845         "    int u;\n"
5846         "    result += u;\n"
5847         "    int k = 0;\n"
5848         "    for (int i[2], j = i[0] + 1; k < 2; ++k)\n"
5849         "    {\n"
5850         "        result += j;\n"
5851         "    }\n"
5852         "    if (result == 2)\n"
5853         "    {\n"
5854         "        my_FragColor = vec4(0, 1, 0, 1);\n"
5855         "    }\n"
5856         "    else\n"
5857         "    {\n"
5858         "        my_FragColor = vec4(1, 0, 0, 1);\n"
5859         "    }\n"
5860         "}\n";
5861 
5862     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
5863 
5864     // [WebGL 1.0]
5865     // DrawArrays or drawElements will generate an INVALID_OPERATION error
5866     // if a vertex attribute is enabled as an array via enableVertexAttribArray
5867     // but no buffer is bound to that attribute.
5868     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
5869     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5870 }
5871 
5872 // Test that uninitialized structs containing arrays of structs are initialized to 0. This
5873 // specifically tests with two different struct variables declared in the same block.
TEST_P(WebGL2GLSLTest,InitUninitializedStructContainingArrays)5874 TEST_P(WebGL2GLSLTest, InitUninitializedStructContainingArrays)
5875 {
5876     // Test skipped on Android GLES because local variable initialization is disabled.
5877     // http://anglebug.com/2046
5878     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
5879 
5880     constexpr char kFS[] =
5881         "precision mediump float;\n"
5882         "struct T\n"
5883         "{\n"
5884         "    int a[2];\n"
5885         "};\n"
5886         "struct S\n"
5887         "{\n"
5888         "    T t[2];\n"
5889         "};\n"
5890         "void main()\n"
5891         "{\n"
5892         "    S s;\n"
5893         "    S s2;\n"
5894         "    if (s.t[1].a[1] == 0 && s2.t[1].a[1] == 0)\n"
5895         "    {\n"
5896         "        gl_FragColor = vec4(0, 1, 0, 1);\n"
5897         "    }\n"
5898         "    else\n"
5899         "    {\n"
5900         "        gl_FragColor = vec4(1, 0, 0, 1);\n"
5901         "    }\n"
5902         "}\n";
5903 
5904     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
5905     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
5906     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5907 }
5908 
5909 // Verify that two shaders with the same uniform name and members but different structure names will
5910 // not link.
TEST_P(GLSLTest,StructureNameMatchingTest)5911 TEST_P(GLSLTest, StructureNameMatchingTest)
5912 {
5913     const char *vsSource =
5914         "// Structures must have the same name, sequence of type names, and\n"
5915         "// type definitions, and field names to be considered the same type.\n"
5916         "// GLSL 1.017 4.2.4\n"
5917         "precision mediump float;\n"
5918         "struct info {\n"
5919         "  vec4 pos;\n"
5920         "  vec4 color;\n"
5921         "};\n"
5922         "\n"
5923         "uniform info uni;\n"
5924         "void main()\n"
5925         "{\n"
5926         "    gl_Position = uni.pos;\n"
5927         "}\n";
5928 
5929     GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
5930     ASSERT_NE(0u, vs);
5931     glDeleteShader(vs);
5932 
5933     const char *fsSource =
5934         "// Structures must have the same name, sequence of type names, and\n"
5935         "// type definitions, and field names to be considered the same type.\n"
5936         "// GLSL 1.017 4.2.4\n"
5937         "precision mediump float;\n"
5938         "struct info1 {\n"
5939         "  vec4 pos;\n"
5940         "  vec4 color;\n"
5941         "};\n"
5942         "\n"
5943         "uniform info1 uni;\n"
5944         "void main()\n"
5945         "{\n"
5946         "    gl_FragColor = uni.color;\n"
5947         "}\n";
5948 
5949     GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
5950     ASSERT_NE(0u, fs);
5951     glDeleteShader(fs);
5952 
5953     GLuint program = CompileProgram(vsSource, fsSource);
5954     EXPECT_EQ(0u, program);
5955 }
5956 
5957 // Test that an uninitialized nameless struct inside a for loop init statement works.
TEST_P(WebGL2GLSLTest,UninitializedNamelessStructInForInitStatement)5958 TEST_P(WebGL2GLSLTest, UninitializedNamelessStructInForInitStatement)
5959 {
5960     // Test skipped on Android GLES because local variable initialization is disabled.
5961     // http://anglebug.com/2046
5962     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
5963 
5964     constexpr char kFS[] =
5965         "#version 300 es\n"
5966         "precision highp float;\n"
5967         "out vec4 my_FragColor;\n"
5968         "void main()\n"
5969         "{\n"
5970         "    my_FragColor = vec4(1, 0, 0, 1);\n"
5971         "    for (struct { float q; } b; b.q < 2.0; b.q++) {\n"
5972         "        my_FragColor = vec4(0, 1, 0, 1);\n"
5973         "    }\n"
5974         "}\n";
5975 
5976     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
5977     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
5978     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5979 }
5980 
5981 // Test that uninitialized global variables are initialized to 0.
TEST_P(WebGLGLSLTest,InitUninitializedGlobals)5982 TEST_P(WebGLGLSLTest, InitUninitializedGlobals)
5983 {
5984     // http://anglebug.com/2862
5985     ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
5986 
5987     constexpr char kFS[] =
5988         "precision mediump float;\n"
5989         "int result;\n"
5990         "int i[2], j = i[0] + 1;\n"
5991         "void main()\n"
5992         "{\n"
5993         "    result += j;\n"
5994         "    if (result == 1)\n"
5995         "    {\n"
5996         "        gl_FragColor = vec4(0, 1, 0, 1);\n"
5997         "    }\n"
5998         "    else\n"
5999         "    {\n"
6000         "        gl_FragColor = vec4(1, 0, 0, 1);\n"
6001         "    }\n"
6002         "}\n";
6003 
6004     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
6005     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6006     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6007 }
6008 
6009 // Test that an uninitialized nameless struct in the global scope works.
TEST_P(WebGLGLSLTest,UninitializedNamelessStructInGlobalScope)6010 TEST_P(WebGLGLSLTest, UninitializedNamelessStructInGlobalScope)
6011 {
6012     constexpr char kFS[] =
6013         "precision mediump float;\n"
6014         "struct { float q; } b;\n"
6015         "void main()\n"
6016         "{\n"
6017         "    gl_FragColor = vec4(1, 0, 0, 1);\n"
6018         "    if (b.q == 0.0)\n"
6019         "    {\n"
6020         "        gl_FragColor = vec4(0, 1, 0, 1);\n"
6021         "    }\n"
6022         "}\n";
6023 
6024     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
6025     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6026     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6027 }
6028 
6029 // Tests nameless struct uniforms.
TEST_P(GLSLTest,EmbeddedStructUniform)6030 TEST_P(GLSLTest, EmbeddedStructUniform)
6031 {
6032     const char kFragmentShader[] = R"(precision mediump float;
6033 uniform struct { float q; } b;
6034 void main()
6035 {
6036     gl_FragColor = vec4(1, 0, 0, 1);
6037     if (b.q == 0.5)
6038     {
6039         gl_FragColor = vec4(0, 1, 0, 1);
6040     }
6041 })";
6042 
6043     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
6044     glUseProgram(program);
6045     GLint uniLoc = glGetUniformLocation(program, "b.q");
6046     ASSERT_NE(-1, uniLoc);
6047     glUniform1f(uniLoc, 0.5f);
6048 
6049     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6050     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6051 }
6052 
6053 // Tests nameless struct uniform arrays.
TEST_P(GLSLTest,EmbeddedStructUniformArray)6054 TEST_P(GLSLTest, EmbeddedStructUniformArray)
6055 {
6056     const char kFragmentShader[] = R"(precision mediump float;
6057 uniform struct { float q; } b[2];
6058 void main()
6059 {
6060     gl_FragColor = vec4(1, 0, 0, 1);
6061     if (b[0].q == 0.5)
6062     {
6063         gl_FragColor = vec4(0, 1, 0, 1);
6064     }
6065 })";
6066 
6067     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
6068     glUseProgram(program);
6069     GLint uniLoc = glGetUniformLocation(program, "b[0].q");
6070     ASSERT_NE(-1, uniLoc);
6071     glUniform1f(uniLoc, 0.5f);
6072 
6073     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6074     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6075 }
6076 
6077 // Tests that rewriting samplers in structs doesn't mess up indexing.
TEST_P(GLSLTest,SamplerInStructMemberIndexing)6078 TEST_P(GLSLTest, SamplerInStructMemberIndexing)
6079 {
6080     const char kVertexShader[] = R"(attribute vec2 position;
6081 varying vec2 texCoord;
6082 void main()
6083 {
6084     gl_Position = vec4(position, 0, 1);
6085     texCoord = position * 0.5 + vec2(0.5);
6086 })";
6087 
6088     const char kFragmentShader[] = R"(precision mediump float;
6089 struct S { sampler2D samp; bool b; };
6090 uniform S uni;
6091 varying vec2 texCoord;
6092 void main()
6093 {
6094     if (uni.b)
6095     {
6096         gl_FragColor = texture2D(uni.samp, texCoord);
6097     }
6098     else
6099     {
6100         gl_FragColor = vec4(1, 0, 0, 1);
6101     }
6102 })";
6103 
6104     ANGLE_GL_PROGRAM(program, kVertexShader, kFragmentShader);
6105     glUseProgram(program);
6106 
6107     GLint bLoc = glGetUniformLocation(program, "uni.b");
6108     ASSERT_NE(-1, bLoc);
6109     GLint sampLoc = glGetUniformLocation(program, "uni.samp");
6110     ASSERT_NE(-1, sampLoc);
6111 
6112     glUniform1i(bLoc, 1);
6113 
6114     std::array<GLColor, 4> kGreenPixels = {
6115         {GLColor::green, GLColor::green, GLColor::green, GLColor::green}};
6116 
6117     GLTexture tex;
6118     glBindTexture(GL_TEXTURE_2D, tex);
6119     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6120                  kGreenPixels.data());
6121     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6122     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6123     ASSERT_GL_NO_ERROR();
6124 
6125     drawQuad(program, "position", 0.5f);
6126     ASSERT_GL_NO_ERROR();
6127 
6128     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6129 }
6130 
6131 // Tests two nameless struct uniforms.
TEST_P(GLSLTest,TwoEmbeddedStructUniforms)6132 TEST_P(GLSLTest, TwoEmbeddedStructUniforms)
6133 {
6134     const char kFragmentShader[] = R"(precision mediump float;
6135 uniform struct { float q; } b, c;
6136 void main()
6137 {
6138     gl_FragColor = vec4(1, 0, 0, 1);
6139     if (b.q == 0.5 && c.q == 1.0)
6140     {
6141         gl_FragColor = vec4(0, 1, 0, 1);
6142     }
6143 })";
6144 
6145     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
6146     glUseProgram(program);
6147 
6148     GLint uniLocB = glGetUniformLocation(program, "b.q");
6149     ASSERT_NE(-1, uniLocB);
6150     glUniform1f(uniLocB, 0.5f);
6151 
6152     GLint uniLocC = glGetUniformLocation(program, "c.q");
6153     ASSERT_NE(-1, uniLocC);
6154     glUniform1f(uniLocC, 1.0f);
6155 
6156     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6157     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6158 }
6159 
6160 // Test that a loop condition that has an initializer declares a variable.
TEST_P(GLSLTest_ES3,ConditionInitializerDeclaresVariable)6161 TEST_P(GLSLTest_ES3, ConditionInitializerDeclaresVariable)
6162 {
6163     constexpr char kFS[] =
6164         "#version 300 es\n"
6165         "precision highp float;\n"
6166         "out vec4 my_FragColor;\n"
6167         "void main()\n"
6168         "{\n"
6169         "    float i = 0.0;\n"
6170         "    while (bool foo = (i < 1.5))\n"
6171         "    {\n"
6172         "        if (!foo)\n"
6173         "        {\n"
6174         "            ++i;\n"
6175         "        }\n"
6176         "        if (i > 3.5)\n"
6177         "        {\n"
6178         "            break;\n"
6179         "        }\n"
6180         "        ++i;\n"
6181         "    }\n"
6182         "    my_FragColor = vec4(i * 0.5 - 1.0, i * 0.5, 0.0, 1.0);\n"
6183         "}\n";
6184 
6185     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6186     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
6187     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6188 }
6189 
6190 // Test that a variable hides a user-defined function with the same name after its initializer.
6191 // GLSL ES 1.00.17 section 4.2.2: "A variable declaration is visible immediately following the
6192 // initializer if present, otherwise immediately following the identifier"
TEST_P(GLSLTest,VariableHidesUserDefinedFunctionAfterInitializer)6193 TEST_P(GLSLTest, VariableHidesUserDefinedFunctionAfterInitializer)
6194 {
6195     constexpr char kFS[] =
6196         "precision mediump float;\n"
6197         "uniform vec4 u;\n"
6198         "vec4 foo()\n"
6199         "{\n"
6200         "    return u;\n"
6201         "}\n"
6202         "void main()\n"
6203         "{\n"
6204         "    vec4 foo = foo();\n"
6205         "    gl_FragColor = foo + vec4(0, 1, 0, 1);\n"
6206         "}\n";
6207 
6208     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
6209     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
6210     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6211 }
6212 
6213 // Test that structs with identical members are not ambiguous as function arguments.
TEST_P(GLSLTest,StructsWithSameMembersDisambiguatedByName)6214 TEST_P(GLSLTest, StructsWithSameMembersDisambiguatedByName)
6215 {
6216     constexpr char kFS[] =
6217         "precision mediump float;\n"
6218         "uniform float u_zero;\n"
6219         "struct S { float foo; };\n"
6220         "struct S2 { float foo; };\n"
6221         "float get(S s) { return s.foo + u_zero; }\n"
6222         "float get(S2 s2) { return 0.25 + s2.foo + u_zero; }\n"
6223         "void main()\n"
6224         "{\n"
6225         "    S s;\n"
6226         "    s.foo = 0.5;\n"
6227         "    S2 s2;\n"
6228         "    s2.foo = 0.25;\n"
6229         "    gl_FragColor = vec4(0.0, get(s) + get(s2), 0.0, 1.0);\n"
6230         "}\n";
6231 
6232     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
6233     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
6234     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6235 }
6236 
6237 // Test that an inactive varying in vertex shader but used in fragment shader can be linked
6238 // successfully.
TEST_P(GLSLTest,InactiveVaryingInVertexActiveInFragment)6239 TEST_P(GLSLTest, InactiveVaryingInVertexActiveInFragment)
6240 {
6241     // http://anglebug.com/4820
6242     ANGLE_SKIP_TEST_IF((IsOSX() && IsOpenGL()) || (IsIOS() && IsOpenGLES()));
6243 
6244     constexpr char kVS[] =
6245         "attribute vec4 inputAttribute;\n"
6246         "varying vec4 varColor;\n"
6247         "void main()\n"
6248         "{\n"
6249         "    gl_Position = inputAttribute;\n"
6250         "}\n";
6251 
6252     constexpr char kFS[] =
6253         "precision mediump float;\n"
6254         "varying vec4 varColor;\n"
6255         "void main()\n"
6256         "{\n"
6257         "    gl_FragColor = varColor;\n"
6258         "}\n";
6259 
6260     ANGLE_GL_PROGRAM(program, kVS, kFS);
6261     drawQuad(program.get(), "inputAttribute", 0.5f);
6262     ASSERT_GL_NO_ERROR();
6263 }
6264 
6265 // Test that a varying struct that's not statically used in the fragment shader works.
6266 // GLSL ES 3.00.6 section 4.3.10.
TEST_P(GLSLTest_ES3,VaryingStructNotStaticallyUsedInFragmentShader)6267 TEST_P(GLSLTest_ES3, VaryingStructNotStaticallyUsedInFragmentShader)
6268 {
6269     constexpr char kVS[] =
6270         "#version 300 es\n"
6271         "struct S {\n"
6272         "    vec4 field;\n"
6273         "};\n"
6274         "out S varStruct;\n"
6275         "void main()\n"
6276         "{\n"
6277         "    gl_Position = vec4(1.0);\n"
6278         "    varStruct.field = vec4(0.0, 0.5, 0.0, 0.0);\n"
6279         "}\n";
6280 
6281     constexpr char kFS[] =
6282         "#version 300 es\n"
6283         "precision mediump float;\n"
6284         "struct S {\n"
6285         "    vec4 field;\n"
6286         "};\n"
6287         "in S varStruct;\n"
6288         "out vec4 col;\n"
6289         "void main()\n"
6290         "{\n"
6291         "    col = vec4(1.0);\n"
6292         "}\n";
6293 
6294     ANGLE_GL_PROGRAM(program, kVS, kFS);
6295 }
6296 
6297 // Test that a shader IO block varying that's not declared in the fragment shader links
6298 // successfully.
TEST_P(GLSLTest_ES31,VaryingIOBlockNotDeclaredInFragmentShader)6299 TEST_P(GLSLTest_ES31, VaryingIOBlockNotDeclaredInFragmentShader)
6300 {
6301     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
6302 
6303     constexpr char kVS[] =
6304         R"(#version 310 es
6305         #extension GL_EXT_shader_io_blocks : require
6306 
6307         precision highp float;
6308         in vec4 inputAttribute;
6309         out Block_inout { vec4 value; } user_out;
6310 
6311         void main()
6312         {
6313             gl_Position    = inputAttribute;
6314             user_out.value = vec4(4.0, 5.0, 6.0, 7.0);
6315         })";
6316 
6317     constexpr char kFS[] =
6318         R"(#version 310 es
6319         #extension GL_EXT_shader_io_blocks : require
6320 
6321         precision highp float;
6322         layout(location = 0) out mediump vec4 color;
6323         void main()
6324         {
6325             color = vec4(1, 0, 0, 1);
6326         })";
6327 
6328     ANGLE_GL_PROGRAM(program, kVS, kFS);
6329     drawQuad(program.get(), "inputAttribute", 0.5f);
6330     ASSERT_GL_NO_ERROR();
6331 
6332     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6333 }
6334 
6335 // Test that a shader IO block varying that's not declared in the vertex shader links
6336 // successfully.
TEST_P(GLSLTest_ES31,VaryingIOBlockNotDeclaredInVertexShader)6337 TEST_P(GLSLTest_ES31, VaryingIOBlockNotDeclaredInVertexShader)
6338 {
6339     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
6340 
6341     constexpr char kVS[] =
6342         R"(#version 310 es
6343         #extension GL_EXT_shader_io_blocks : require
6344 
6345         precision highp float;
6346         in vec4 inputAttribute;
6347 
6348         void main()
6349         {
6350             gl_Position = inputAttribute;
6351         })";
6352 
6353     constexpr char kFS[] =
6354         R"(#version 310 es
6355         #extension GL_EXT_shader_io_blocks : require
6356 
6357         precision highp float;
6358         in Block_inout { vec4 value; } user_in;
6359         layout(location = 0) out mediump vec4 color;
6360 
6361         void main()
6362         {
6363             color = vec4(1, 0, 0, 1);
6364         })";
6365 
6366     ANGLE_GL_PROGRAM(program, kVS, kFS);
6367     drawQuad(program.get(), "inputAttribute", 0.5f);
6368     ASSERT_GL_NO_ERROR();
6369 
6370     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6371 }
6372 
6373 // Test that a shader with sample in / sample out can be linked successfully.
TEST_P(GLSLTest_ES31,VaryingTessellationSampleInAndOut)6374 TEST_P(GLSLTest_ES31, VaryingTessellationSampleInAndOut)
6375 {
6376     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
6377     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_multisample_interpolation"));
6378 
6379     constexpr char kVS[] =
6380         R"(#version 310 es
6381         #extension GL_OES_shader_multisample_interpolation : require
6382 
6383         precision highp float;
6384         in vec4 inputAttribute;
6385 
6386         sample out mediump float tc_in;
6387         void main()
6388         {
6389             tc_in = inputAttribute[0];
6390             gl_Position = inputAttribute;
6391         })";
6392 
6393     constexpr char kTCS[] =
6394         R"(#version 310 es
6395         #extension GL_EXT_tessellation_shader : require
6396         #extension GL_OES_shader_multisample_interpolation : require
6397         layout (vertices=3) out;
6398 
6399         sample in mediump float tc_in[];
6400         sample out mediump float tc_out[];
6401         void main()
6402         {
6403             tc_out[gl_InvocationID] = tc_in[gl_InvocationID];
6404             gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
6405             gl_TessLevelInner[0] = 2.0;
6406             gl_TessLevelInner[1] = 2.0;
6407             gl_TessLevelOuter[0] = 2.0;
6408             gl_TessLevelOuter[1] = 2.0;
6409             gl_TessLevelOuter[2] = 2.0;
6410             gl_TessLevelOuter[3] = 2.0;
6411         })";
6412 
6413     constexpr char kTES[] =
6414         R"(#version 310 es
6415         #extension GL_EXT_tessellation_shader : require
6416         #extension GL_OES_shader_multisample_interpolation : require
6417         layout (triangles) in;
6418 
6419         sample in mediump float tc_out[];
6420         sample out mediump float te_out;
6421         void main()
6422         {
6423             te_out = tc_out[2];
6424             gl_Position = gl_TessCoord[0] * gl_in[0].gl_Position;
6425         })";
6426 
6427     constexpr char kFS[] =
6428         R"(#version 310 es
6429         #extension GL_OES_shader_multisample_interpolation : require
6430 
6431         precision highp float;
6432         sample in mediump float te_out;
6433         layout(location = 0) out mediump vec4 color;
6434 
6435         void main()
6436         {
6437             float out0 = te_out;
6438             color = vec4(1, 0, 0, 1);
6439         })";
6440 
6441     ANGLE_GL_PROGRAM_WITH_TESS(program, kVS, kTCS, kTES, kFS);
6442     drawPatches(program.get(), "inputAttribute", 0.5f, 1.0f, GL_FALSE);
6443     ASSERT_GL_NO_ERROR();
6444 }
6445 
6446 // Test that a shader with sample in / sample out can be used successfully when the varying
6447 // precision is different between VS and FS.
TEST_P(GLSLTest_ES31,VaryingSampleInAndOutDifferentPrecision)6448 TEST_P(GLSLTest_ES31, VaryingSampleInAndOutDifferentPrecision)
6449 {
6450     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_multisample_interpolation"));
6451 
6452     constexpr char kVS[] =
6453         R"(#version 310 es
6454         #extension GL_OES_shader_multisample_interpolation : require
6455 
6456         precision highp float;
6457         in vec4 inputAttribute;
6458 
6459         sample out highp float v;
6460         void main()
6461         {
6462             v = inputAttribute[0];
6463             gl_Position = inputAttribute;
6464         })";
6465 
6466     constexpr char kFS[] =
6467         R"(#version 310 es
6468         #extension GL_OES_shader_multisample_interpolation : require
6469 
6470         precision highp float;
6471         sample in mediump float v;
6472         layout(location = 0) out mediump vec4 color;
6473 
6474         void main()
6475         {
6476             color = vec4(round((v + 1.) / 2. * 5.) / 5., 0, 0, 1);
6477         })";
6478 
6479     ANGLE_GL_PROGRAM(program, kVS, kFS);
6480     drawQuad(program.get(), "inputAttribute", 0.5f, 1.0f, GL_FALSE);
6481     ASSERT_GL_NO_ERROR();
6482 
6483     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, 0, GLColor::red);
6484 }
6485 
6486 // Test that a varying struct that's not declared in the fragment shader links successfully.
6487 // GLSL ES 3.00.6 section 4.3.10.
TEST_P(GLSLTest_ES3,VaryingStructNotDeclaredInFragmentShader)6488 TEST_P(GLSLTest_ES3, VaryingStructNotDeclaredInFragmentShader)
6489 {
6490     constexpr char kVS[] =
6491         "#version 300 es\n"
6492         "struct S {\n"
6493         "    vec4 field;\n"
6494         "};\n"
6495         "out S varStruct;\n"
6496         "void main()\n"
6497         "{\n"
6498         "    gl_Position = vec4(1.0);\n"
6499         "    varStruct.field = vec4(0.0, 0.5, 0.0, 0.0);\n"
6500         "}\n";
6501 
6502     constexpr char kFS[] =
6503         "#version 300 es\n"
6504         "precision mediump float;\n"
6505         "out vec4 col;\n"
6506         "void main()\n"
6507         "{\n"
6508         "    col = vec4(1.0);\n"
6509         "}\n";
6510 
6511     ANGLE_GL_PROGRAM(program, kVS, kFS);
6512 }
6513 
6514 // Test that a varying struct that's not declared in the vertex shader, and is unused in the
6515 // fragment shader links successfully.
TEST_P(GLSLTest_ES3,VaryingStructNotDeclaredInVertexShader)6516 TEST_P(GLSLTest_ES3, VaryingStructNotDeclaredInVertexShader)
6517 {
6518     // GLSL ES allows the vertex shader to not declare a varying if the fragment shader is not
6519     // going to use it.  See section 9.1 in
6520     // https://www.khronos.org/registry/OpenGL/specs/es/3.2/GLSL_ES_Specification_3.20.pdf or
6521     // section 4.3.5 in https://www.khronos.org/files/opengles_shading_language.pdf
6522     //
6523     // However, nvidia OpenGL ES drivers fail to link this program.
6524     //
6525     // http://anglebug.com/3413
6526     ANGLE_SKIP_TEST_IF(IsOpenGLES() && IsNVIDIA());
6527 
6528     constexpr char kVS[] =
6529         "#version 300 es\n"
6530         "void main()\n"
6531         "{\n"
6532         "    gl_Position = vec4(1.0);\n"
6533         "}\n";
6534 
6535     constexpr char kFS[] =
6536         "#version 300 es\n"
6537         "precision mediump float;\n"
6538         "out vec4 col;\n"
6539         "struct S {\n"
6540         "    vec4 field;\n"
6541         "};\n"
6542         "in S varStruct;\n"
6543         "void main()\n"
6544         "{\n"
6545         "    col = vec4(1.0);\n"
6546         "}\n";
6547 
6548     ANGLE_GL_PROGRAM(program, kVS, kFS);
6549 }
6550 
6551 // Test that a varying struct that's not initialized in the vertex shader links successfully.
TEST_P(WebGL2GLSLTest,VaryingStructNotInitializedInVertexShader)6552 TEST_P(WebGL2GLSLTest, VaryingStructNotInitializedInVertexShader)
6553 {
6554     // GLSL ES allows the vertex shader to declare but not initialize a varying (with a
6555     // specification that the varying values are undefined in the fragment stage).  See section 9.1
6556     // in https://www.khronos.org/registry/OpenGL/specs/es/3.2/GLSL_ES_Specification_3.20.pdf
6557     // or section 4.3.5 in https://www.khronos.org/files/opengles_shading_language.pdf
6558     //
6559     // However, windows and mac OpenGL drivers fail to link this program.  With a message like:
6560     //
6561     // > Input of fragment shader 'varStruct' not written by vertex shader
6562     //
6563     // http://anglebug.com/3413
6564     ANGLE_SKIP_TEST_IF(IsDesktopOpenGL() && (IsOSX() || (IsWindows() && !IsNVIDIA())));
6565     // TODO(anglebug.com/5491): iOS thinks that the precision qualifiers don't match on the
6566     // struct member. Not sure if it's being overly strict.
6567     ANGLE_SKIP_TEST_IF(IsIOS() && IsOpenGLES());
6568 
6569     constexpr char kVS[] =
6570         "#version 300 es\n"
6571         "struct S {\n"
6572         "    vec4 field;\n"
6573         "};\n"
6574         "out S varStruct;\n"
6575         "void main()\n"
6576         "{\n"
6577         "    gl_Position = vec4(1.0);\n"
6578         "}\n";
6579 
6580     constexpr char kFS[] =
6581         "#version 300 es\n"
6582         "precision mediump float;\n"
6583         "out vec4 col;\n"
6584         "struct S {\n"
6585         "    vec4 field;\n"
6586         "};\n"
6587         "in S varStruct;\n"
6588         "void main()\n"
6589         "{\n"
6590         "    col = varStruct.field;\n"
6591         "}\n";
6592 
6593     ANGLE_GL_PROGRAM(program, kVS, kFS);
6594 }
6595 
6596 // Test that a varying struct that gets used in the fragment shader works.
TEST_P(GLSLTest_ES3,VaryingStructUsedInFragmentShader)6597 TEST_P(GLSLTest_ES3, VaryingStructUsedInFragmentShader)
6598 {
6599     // TODO(anglebug.com/5491): iOS thinks that the precision qualifiers don't match on the
6600     // struct member. Not sure if it's being overly strict.
6601     ANGLE_SKIP_TEST_IF(IsIOS() && IsOpenGLES());
6602     constexpr char kVS[] =
6603         "#version 300 es\n"
6604         "in vec4 inputAttribute;\n"
6605         "struct S {\n"
6606         "    vec4 field;\n"
6607         "};\n"
6608         "out S varStruct;\n"
6609         "out S varStruct2;\n"
6610         "void main()\n"
6611         "{\n"
6612         "    gl_Position = inputAttribute;\n"
6613         "    varStruct.field = vec4(0.0, 0.5, 0.0, 1.0);\n"
6614         "    varStruct2.field = vec4(0.0, 0.5, 0.0, 1.0);\n"
6615         "}\n";
6616 
6617     constexpr char kFS[] =
6618         "#version 300 es\n"
6619         "precision mediump float;\n"
6620         "out vec4 col;\n"
6621         "struct S {\n"
6622         "    vec4 field;\n"
6623         "};\n"
6624         "in S varStruct;\n"
6625         "in S varStruct2;\n"
6626         "void main()\n"
6627         "{\n"
6628         "    col = varStruct.field + varStruct2.field;\n"
6629         "}\n";
6630 
6631     ANGLE_GL_PROGRAM(program, kVS, kFS);
6632     drawQuad(program.get(), "inputAttribute", 0.5f);
6633     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6634 }
6635 
6636 // This is a regression test to make sure a red quad is rendered without issues
6637 // when a passthrough function with a vec3 input parameter is used in the fragment shader.
TEST_P(GLSLTest_ES31,SamplerPassthroughFailedLink)6638 TEST_P(GLSLTest_ES31, SamplerPassthroughFailedLink)
6639 {
6640     constexpr char kVS[] =
6641         "precision mediump float;\n"
6642         "attribute vec4 inputAttribute;\n"
6643         "varying mediump vec2 texCoord;\n"
6644         "void main() {\n"
6645         "    texCoord = inputAttribute.xy;\n"
6646         "    gl_Position = vec4(inputAttribute.x, inputAttribute.y, 0.0, 1.0);\n"
6647         "}\n";
6648 
6649     constexpr char kFS[] =
6650         "precision mediump float;\n"
6651         "varying mediump vec2 texCoord;\n"
6652         "uniform sampler2D testSampler;\n"
6653         "vec3 passthrough(vec3 c) {\n"
6654         "    return c;\n"
6655         "}\n"
6656         "void main() {\n"
6657         "    gl_FragColor = vec4(passthrough(texture2D(testSampler, texCoord).rgb), 1.0);\n"
6658         "}\n";
6659     ANGLE_GL_PROGRAM(program, kVS, kFS);
6660 
6661     // Initialize basic red texture.
6662     GLTexture texture;
6663     glBindTexture(GL_TEXTURE_2D, texture);
6664     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6665                  GLColor::red.data());
6666     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6667     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6668     ASSERT_GL_NO_ERROR();
6669 
6670     drawQuad(program.get(), "inputAttribute", 0.5f);
6671     ASSERT_GL_NO_ERROR();
6672     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6673 }
6674 
6675 // This is a regression test to make sure a red quad is rendered without issues
6676 // when a passthrough function with a vec4 input parameter is used in the fragment shader.
TEST_P(GLSLTest_ES31,SamplerPassthroughIncorrectColor)6677 TEST_P(GLSLTest_ES31, SamplerPassthroughIncorrectColor)
6678 {
6679     constexpr char kVS[] =
6680         "precision mediump float;\n"
6681         "attribute vec4 inputAttribute;\n"
6682         "varying mediump vec2 texCoord;\n"
6683         "void main() {\n"
6684         "    texCoord = inputAttribute.xy;\n"
6685         "    gl_Position = vec4(inputAttribute.x, inputAttribute.y, 0.0, 1.0);\n"
6686         "}\n";
6687 
6688     constexpr char kFS[] =
6689         "precision mediump float;\n"
6690         "varying mediump vec2 texCoord;\n"
6691         "uniform sampler2D testSampler;\n"
6692         "vec4 passthrough(vec4 c) {\n"
6693         "    return c;\n"
6694         "}\n"
6695         "void main() {\n"
6696         "    gl_FragColor = vec4(passthrough(texture2D(testSampler, texCoord)));\n"
6697         "}\n";
6698     ANGLE_GL_PROGRAM(program, kVS, kFS);
6699 
6700     // Initialize basic red texture.
6701     GLTexture texture;
6702     glBindTexture(GL_TEXTURE_2D, texture);
6703     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6704                  GLColor::red.data());
6705     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6706     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6707     ASSERT_GL_NO_ERROR();
6708 
6709     drawQuad(program.get(), "inputAttribute", 0.5f);
6710     ASSERT_GL_NO_ERROR();
6711     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6712 }
6713 
6714 // Test that multiple multi-field varying structs that get used in the fragment shader work.
TEST_P(GLSLTest_ES3,ComplexVaryingStructsUsedInFragmentShader)6715 TEST_P(GLSLTest_ES3, ComplexVaryingStructsUsedInFragmentShader)
6716 {
6717     // TODO(syoussefi): fails on android with:
6718     //
6719     // > Internal Vulkan error: A return array was too small for the result
6720     //
6721     // http://anglebug.com/3220
6722     ANGLE_SKIP_TEST_IF(IsVulkan() && IsAndroid());
6723     // TODO(anglebug.com/5491): iOS thinks that the precision qualifiers don't match on the
6724     // struct members. Not sure if it's being overly strict.
6725     ANGLE_SKIP_TEST_IF(IsIOS() && IsOpenGLES());
6726 
6727     constexpr char kVS[] =
6728         "#version 300 es\n"
6729         "in vec4 inputAttribute;\n"
6730         "struct S {\n"
6731         "    vec4 field1;\n"
6732         "    vec4 field2;\n"
6733         "};\n"
6734         "out S varStruct;\n"
6735         "out S varStruct2;\n"
6736         "void main()\n"
6737         "{\n"
6738         "    gl_Position = inputAttribute;\n"
6739         "    varStruct.field1 = vec4(0.0, 0.5, 0.0, 1.0);\n"
6740         "    varStruct.field2 = vec4(0.0, 0.5, 0.0, 1.0);\n"
6741         "    varStruct2.field1 = vec4(0.0, 0.5, 0.0, 1.0);\n"
6742         "    varStruct2.field2 = vec4(0.0, 0.5, 0.0, 1.0);\n"
6743         "}\n";
6744 
6745     constexpr char kFS[] =
6746         "#version 300 es\n"
6747         "precision mediump float;\n"
6748         "out vec4 col;\n"
6749         "struct S {\n"
6750         "    vec4 field1;\n"
6751         "    vec4 field2;\n"
6752         "};\n"
6753         "in S varStruct;\n"
6754         "in S varStruct2;\n"
6755         "void main()\n"
6756         "{\n"
6757         "    col = varStruct.field1 + varStruct2.field2;\n"
6758         "}\n";
6759 
6760     ANGLE_GL_PROGRAM(program, kVS, kFS);
6761     drawQuad(program.get(), "inputAttribute", 0.5f);
6762     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6763 }
6764 
6765 // Test that an inactive varying array that doesn't get used in the fragment shader works.
TEST_P(GLSLTest_ES3,InactiveVaryingArrayUnusedInFragmentShader)6766 TEST_P(GLSLTest_ES3, InactiveVaryingArrayUnusedInFragmentShader)
6767 {
6768     constexpr char kVS[] =
6769         "#version 300 es\n"
6770         "in vec4 inputAttribute;\n"
6771         "out vec4 varArray[4];\n"
6772         "void main()\n"
6773         "{\n"
6774         "    gl_Position = inputAttribute;\n"
6775         "    varArray[0] = vec4(1.0, 0.0, 0.0, 1.0);\n"
6776         "    varArray[1] = vec4(0.0, 1.0, 0.0, 1.0);\n"
6777         "    varArray[2] = vec4(0.0, 0.0, 1.0, 1.0);\n"
6778         "    varArray[3] = vec4(1.0, 1.0, 0.0, 1.0);\n"
6779         "}\n";
6780 
6781     constexpr char kFS[] =
6782         "#version 300 es\n"
6783         "precision mediump float;\n"
6784         "out vec4 col;\n"
6785         "void main()\n"
6786         "{\n"
6787         "    col = vec4(0.0, 0.0, 0.0, 1.0);\n"
6788         "}\n";
6789 
6790     ANGLE_GL_PROGRAM(program, kVS, kFS);
6791     drawQuad(program.get(), "inputAttribute", 0.5f);
6792     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
6793 }
6794 
6795 // Test that an inactive varying struct that doesn't get used in the fragment shader works.
TEST_P(GLSLTest_ES3,InactiveVaryingStructUnusedInFragmentShader)6796 TEST_P(GLSLTest_ES3, InactiveVaryingStructUnusedInFragmentShader)
6797 {
6798     constexpr char kVS[] =
6799         "#version 300 es\n"
6800         "in vec4 inputAttribute;\n"
6801         "struct S {\n"
6802         "    vec4 field;\n"
6803         "};\n"
6804         "out S varStruct;\n"
6805         "out S varStruct2;\n"
6806         "void main()\n"
6807         "{\n"
6808         "    gl_Position = inputAttribute;\n"
6809         "    varStruct.field = vec4(0.0, 1.0, 0.0, 1.0);\n"
6810         "    varStruct2.field = vec4(0.0, 1.0, 0.0, 1.0);\n"
6811         "}\n";
6812 
6813     constexpr char kFS[] =
6814         "#version 300 es\n"
6815         "precision mediump float;\n"
6816         "out vec4 col;\n"
6817         "struct S {\n"
6818         "    vec4 field;\n"
6819         "};\n"
6820         "in S varStruct;\n"
6821         "in S varStruct2;\n"
6822         "void main()\n"
6823         "{\n"
6824         "    col = varStruct.field;\n"
6825         "}\n";
6826 
6827     ANGLE_GL_PROGRAM(program, kVS, kFS);
6828     drawQuad(program.get(), "inputAttribute", 0.5f);
6829     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6830 }
6831 
6832 // Test that multiple varying matrices that get used in the fragment shader work.
TEST_P(GLSLTest_ES3,VaryingMatrices)6833 TEST_P(GLSLTest_ES3, VaryingMatrices)
6834 {
6835     constexpr char kVS[] =
6836         "#version 300 es\n"
6837         "in vec4 inputAttribute;\n"
6838         "out mat2x2 varMat;\n"
6839         "out mat2x2 varMat2;\n"
6840         "out mat4x3 varMat3;\n"
6841         "void main()\n"
6842         "{\n"
6843         "    gl_Position = inputAttribute;\n"
6844         "    varMat[0] = vec2(1, 1);\n"
6845         "    varMat[1] = vec2(1, 1);\n"
6846         "    varMat2[0] = vec2(0.5, 0.5);\n"
6847         "    varMat2[1] = vec2(0.5, 0.5);\n"
6848         "    varMat3[0] = vec3(0.75, 0.75, 0.75);\n"
6849         "    varMat3[1] = vec3(0.75, 0.75, 0.75);\n"
6850         "    varMat3[2] = vec3(0.75, 0.75, 0.75);\n"
6851         "    varMat3[3] = vec3(0.75, 0.75, 0.75);\n"
6852         "}\n";
6853 
6854     constexpr char kFS[] =
6855         "#version 300 es\n"
6856         "precision mediump float;\n"
6857         "out vec4 col;\n"
6858         "in mat2x2 varMat;\n"
6859         "in mat2x2 varMat2;\n"
6860         "in mat4x3 varMat3;\n"
6861         "void main()\n"
6862         "{\n"
6863         "    col = vec4(varMat[0].x, varMat2[1].y, varMat3[2].z, 1);\n"
6864         "}\n";
6865 
6866     ANGLE_GL_PROGRAM(program, kVS, kFS);
6867     drawQuad(program.get(), "inputAttribute", 0.5f);
6868     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 127, 191, 255), 1);
6869 }
6870 
6871 // This test covers passing a struct containing a sampler as a function argument.
TEST_P(GLSLTest,StructsWithSamplersAsFunctionArg)6872 TEST_P(GLSLTest, StructsWithSamplersAsFunctionArg)
6873 {
6874     // Shader failed to compile on Nexus devices. http://anglebug.com/2114
6875     ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
6876 
6877     const char kFragmentShader[] = R"(precision mediump float;
6878 struct S { sampler2D samplerMember; };
6879 uniform S uStruct;
6880 uniform vec2 uTexCoord;
6881 vec4 foo(S structVar)
6882 {
6883     return texture2D(structVar.samplerMember, uTexCoord);
6884 }
6885 void main()
6886 {
6887     gl_FragColor = foo(uStruct);
6888 })";
6889 
6890     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
6891 
6892     // Initialize the texture with green.
6893     GLTexture tex;
6894     glActiveTexture(GL_TEXTURE0);
6895     glBindTexture(GL_TEXTURE_2D, tex);
6896     GLubyte texData[] = {0u, 255u, 0u, 255u};
6897     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
6898     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6899     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6900     ASSERT_GL_NO_ERROR();
6901 
6902     // Draw
6903     glUseProgram(program);
6904     GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMember");
6905     ASSERT_NE(-1, samplerMemberLoc);
6906     glUniform1i(samplerMemberLoc, 0);
6907     GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
6908     ASSERT_NE(-1, texCoordLoc);
6909     glUniform2f(texCoordLoc, 0.5f, 0.5f);
6910 
6911     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
6912     ASSERT_GL_NO_ERROR();
6913 
6914     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
6915 }
6916 
6917 // This test covers passing a struct containing a sampler as a function argument.
TEST_P(GLSLTest,StructsWithSamplersAsFunctionArgWithPrototype)6918 TEST_P(GLSLTest, StructsWithSamplersAsFunctionArgWithPrototype)
6919 {
6920     // Shader failed to compile on Android. http://anglebug.com/2114
6921     ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
6922 
6923     const char kFragmentShader[] = R"(precision mediump float;
6924 struct S { sampler2D samplerMember; };
6925 uniform S uStruct;
6926 uniform vec2 uTexCoord;
6927 vec4 foo(S structVar);
6928 vec4 foo(S structVar)
6929 {
6930     return texture2D(structVar.samplerMember, uTexCoord);
6931 }
6932 void main()
6933 {
6934     gl_FragColor = foo(uStruct);
6935 })";
6936 
6937     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
6938 
6939     // Initialize the texture with green.
6940     GLTexture tex;
6941     glActiveTexture(GL_TEXTURE0);
6942     glBindTexture(GL_TEXTURE_2D, tex);
6943     GLubyte texData[] = {0u, 255u, 0u, 255u};
6944     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
6945     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6946     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6947     ASSERT_GL_NO_ERROR();
6948 
6949     // Draw
6950     glUseProgram(program);
6951     GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMember");
6952     ASSERT_NE(-1, samplerMemberLoc);
6953     glUniform1i(samplerMemberLoc, 0);
6954     GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
6955     ASSERT_NE(-1, texCoordLoc);
6956     glUniform2f(texCoordLoc, 0.5f, 0.5f);
6957 
6958     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
6959     ASSERT_GL_NO_ERROR();
6960 
6961     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
6962 }
6963 // This test covers passing an array of structs containing samplers as a function argument.
TEST_P(GLSLTest,ArrayOfStructsWithSamplersAsFunctionArg)6964 TEST_P(GLSLTest, ArrayOfStructsWithSamplersAsFunctionArg)
6965 {
6966     // Shader failed to compile on Nexus devices. http://anglebug.com/2114
6967     ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
6968 
6969     constexpr char kFS[] =
6970         "precision mediump float;\n"
6971         "struct S\n"
6972         "{\n"
6973         "    sampler2D samplerMember; \n"
6974         "};\n"
6975         "uniform S uStructs[2];\n"
6976         "uniform vec2 uTexCoord;\n"
6977         "\n"
6978         "vec4 foo(S[2] structs)\n"
6979         "{\n"
6980         "    return texture2D(structs[0].samplerMember, uTexCoord);\n"
6981         "}\n"
6982         "void main()\n"
6983         "{\n"
6984         "    gl_FragColor = foo(uStructs);\n"
6985         "}\n";
6986 
6987     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
6988 
6989     // Initialize the texture with green.
6990     GLTexture tex;
6991     glActiveTexture(GL_TEXTURE0);
6992     glBindTexture(GL_TEXTURE_2D, tex);
6993     GLubyte texData[] = {0u, 255u, 0u, 255u};
6994     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
6995     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6996     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6997     ASSERT_GL_NO_ERROR();
6998 
6999     // Draw
7000     glUseProgram(program);
7001     GLint samplerMemberLoc = glGetUniformLocation(program, "uStructs[0].samplerMember");
7002     ASSERT_NE(-1, samplerMemberLoc);
7003     glUniform1i(samplerMemberLoc, 0);
7004     GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
7005     ASSERT_NE(-1, texCoordLoc);
7006     glUniform2f(texCoordLoc, 0.5f, 0.5f);
7007 
7008     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
7009     ASSERT_GL_NO_ERROR();
7010 
7011     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
7012 }
7013 
7014 // This test covers passing a struct containing an array of samplers as a function argument.
TEST_P(GLSLTest,StructWithSamplerArrayAsFunctionArg)7015 TEST_P(GLSLTest, StructWithSamplerArrayAsFunctionArg)
7016 {
7017     // Shader failed to compile on Nexus devices. http://anglebug.com/2114
7018     ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
7019 
7020     constexpr char kFS[] =
7021         "precision mediump float;\n"
7022         "struct S\n"
7023         "{\n"
7024         "    sampler2D samplerMembers[2];\n"
7025         "};\n"
7026         "uniform S uStruct;\n"
7027         "uniform vec2 uTexCoord;\n"
7028         "\n"
7029         "vec4 foo(S str)\n"
7030         "{\n"
7031         "    return texture2D(str.samplerMembers[0], uTexCoord);\n"
7032         "}\n"
7033         "void main()\n"
7034         "{\n"
7035         "    gl_FragColor = foo(uStruct);\n"
7036         "}\n";
7037 
7038     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
7039 
7040     // Initialize the texture with green.
7041     GLTexture tex;
7042     glActiveTexture(GL_TEXTURE0);
7043     glBindTexture(GL_TEXTURE_2D, tex);
7044     GLubyte texData[] = {0u, 255u, 0u, 255u};
7045     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
7046     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7047     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7048     ASSERT_GL_NO_ERROR();
7049 
7050     // Draw
7051     glUseProgram(program);
7052     GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMembers[0]");
7053     ASSERT_NE(-1, samplerMemberLoc);
7054     glUniform1i(samplerMemberLoc, 0);
7055     GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
7056     ASSERT_NE(-1, texCoordLoc);
7057     glUniform2f(texCoordLoc, 0.5f, 0.5f);
7058 
7059     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
7060     ASSERT_GL_NO_ERROR();
7061 
7062     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
7063 }
7064 
7065 // This test covers passing nested structs containing a sampler as a function argument.
TEST_P(GLSLTest,NestedStructsWithSamplersAsFunctionArg)7066 TEST_P(GLSLTest, NestedStructsWithSamplersAsFunctionArg)
7067 {
7068     // Shader failed to compile on Nexus devices. http://anglebug.com/2114
7069     ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
7070 
7071     // TODO(anglebug.com/5360): Failing on ARM-based Apple DTKs.
7072     ANGLE_SKIP_TEST_IF(IsOSX() && IsARM64() && IsDesktopOpenGL());
7073 
7074     const char kFragmentShader[] = R"(precision mediump float;
7075 struct S { sampler2D samplerMember; };
7076 struct T { S nest; };
7077 uniform T uStruct;
7078 uniform vec2 uTexCoord;
7079 vec4 foo2(S structVar)
7080 {
7081     return texture2D(structVar.samplerMember, uTexCoord);
7082 }
7083 vec4 foo(T structVar)
7084 {
7085     return foo2(structVar.nest);
7086 }
7087 void main()
7088 {
7089     gl_FragColor = foo(uStruct);
7090 })";
7091 
7092     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
7093 
7094     // Initialize the texture with green.
7095     GLTexture tex;
7096     glActiveTexture(GL_TEXTURE0);
7097     glBindTexture(GL_TEXTURE_2D, tex);
7098     GLubyte texData[] = {0u, 255u, 0u, 255u};
7099     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
7100     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7101     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7102     ASSERT_GL_NO_ERROR();
7103 
7104     // Draw
7105     glUseProgram(program);
7106     GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.nest.samplerMember");
7107     ASSERT_NE(-1, samplerMemberLoc);
7108     glUniform1i(samplerMemberLoc, 0);
7109     GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
7110     ASSERT_NE(-1, texCoordLoc);
7111     glUniform2f(texCoordLoc, 0.5f, 0.5f);
7112 
7113     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
7114     ASSERT_GL_NO_ERROR();
7115 
7116     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
7117 }
7118 
7119 // This test covers passing a compound structs containing a sampler as a function argument.
TEST_P(GLSLTest,CompoundStructsWithSamplersAsFunctionArg)7120 TEST_P(GLSLTest, CompoundStructsWithSamplersAsFunctionArg)
7121 {
7122     // Shader failed to compile on Nexus devices. http://anglebug.com/2114
7123     ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
7124 
7125     const char kFragmentShader[] = R"(precision mediump float;
7126 struct S { sampler2D samplerMember; bool b; };
7127 uniform S uStruct;
7128 uniform vec2 uTexCoord;
7129 vec4 foo(S structVar)
7130 {
7131     if (structVar.b)
7132         return texture2D(structVar.samplerMember, uTexCoord);
7133     else
7134         return vec4(1, 0, 0, 1);
7135 }
7136 void main()
7137 {
7138     gl_FragColor = foo(uStruct);
7139 })";
7140 
7141     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
7142 
7143     // Initialize the texture with green.
7144     GLTexture tex;
7145     glActiveTexture(GL_TEXTURE0);
7146     glBindTexture(GL_TEXTURE_2D, tex);
7147     GLubyte texData[] = {0u, 255u, 0u, 255u};
7148     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
7149     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7150     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7151     ASSERT_GL_NO_ERROR();
7152 
7153     // Draw
7154     glUseProgram(program);
7155     GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMember");
7156     ASSERT_NE(-1, samplerMemberLoc);
7157     glUniform1i(samplerMemberLoc, 0);
7158     GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
7159     ASSERT_NE(-1, texCoordLoc);
7160     glUniform2f(texCoordLoc, 0.5f, 0.5f);
7161     GLint bLoc = glGetUniformLocation(program, "uStruct.b");
7162     ASSERT_NE(-1, bLoc);
7163     glUniform1i(bLoc, 1);
7164 
7165     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
7166     ASSERT_GL_NO_ERROR();
7167 
7168     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
7169 }
7170 
7171 // This test covers passing nested compound structs containing a sampler as a function argument.
TEST_P(GLSLTest,NestedCompoundStructsWithSamplersAsFunctionArg)7172 TEST_P(GLSLTest, NestedCompoundStructsWithSamplersAsFunctionArg)
7173 {
7174     // Shader failed to compile on Nexus devices. http://anglebug.com/2114
7175     ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
7176 
7177     // TODO(anglebug.com/5360): Failing on ARM-based Apple DTKs.
7178     ANGLE_SKIP_TEST_IF(IsOSX() && IsARM64() && IsDesktopOpenGL());
7179 
7180     const char kFragmentShader[] = R"(precision mediump float;
7181 struct S { sampler2D samplerMember; bool b; };
7182 struct T { S nest; bool b; };
7183 uniform T uStruct;
7184 uniform vec2 uTexCoord;
7185 vec4 foo2(S structVar)
7186 {
7187     if (structVar.b)
7188         return texture2D(structVar.samplerMember, uTexCoord);
7189     else
7190         return vec4(1, 0, 0, 1);
7191 }
7192 vec4 foo(T structVar)
7193 {
7194     if (structVar.b)
7195         return foo2(structVar.nest);
7196     else
7197         return vec4(1, 0, 0, 1);
7198 }
7199 void main()
7200 {
7201     gl_FragColor = foo(uStruct);
7202 })";
7203 
7204     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
7205 
7206     // Initialize the texture with green.
7207     GLTexture tex;
7208     glActiveTexture(GL_TEXTURE0);
7209     glBindTexture(GL_TEXTURE_2D, tex);
7210     GLubyte texData[] = {0u, 255u, 0u, 255u};
7211     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
7212     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7213     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7214     ASSERT_GL_NO_ERROR();
7215 
7216     // Draw
7217     glUseProgram(program);
7218     GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.nest.samplerMember");
7219     ASSERT_NE(-1, samplerMemberLoc);
7220     glUniform1i(samplerMemberLoc, 0);
7221     GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
7222     ASSERT_NE(-1, texCoordLoc);
7223     glUniform2f(texCoordLoc, 0.5f, 0.5f);
7224 
7225     GLint bLoc = glGetUniformLocation(program, "uStruct.b");
7226     ASSERT_NE(-1, bLoc);
7227     glUniform1i(bLoc, 1);
7228 
7229     GLint nestbLoc = glGetUniformLocation(program, "uStruct.nest.b");
7230     ASSERT_NE(-1, nestbLoc);
7231     glUniform1i(nestbLoc, 1);
7232 
7233     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
7234     ASSERT_GL_NO_ERROR();
7235 
7236     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
7237 }
7238 
7239 // Same as the prior test but with reordered struct members.
TEST_P(GLSLTest,MoreNestedCompoundStructsWithSamplersAsFunctionArg)7240 TEST_P(GLSLTest, MoreNestedCompoundStructsWithSamplersAsFunctionArg)
7241 {
7242     // Shader failed to compile on Nexus devices. http://anglebug.com/2114
7243     ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
7244 
7245     // TODO(anglebug.com/5360): Failing on ARM-based Apple DTKs.
7246     ANGLE_SKIP_TEST_IF(IsOSX() && IsARM64() && IsDesktopOpenGL());
7247 
7248     const char kFragmentShader[] = R"(precision mediump float;
7249 struct S { bool b; sampler2D samplerMember; };
7250 struct T { bool b; S nest; };
7251 uniform T uStruct;
7252 uniform vec2 uTexCoord;
7253 vec4 foo2(S structVar)
7254 {
7255     if (structVar.b)
7256         return texture2D(structVar.samplerMember, uTexCoord);
7257     else
7258         return vec4(1, 0, 0, 1);
7259 }
7260 vec4 foo(T structVar)
7261 {
7262     if (structVar.b)
7263         return foo2(structVar.nest);
7264     else
7265         return vec4(1, 0, 0, 1);
7266 }
7267 void main()
7268 {
7269     gl_FragColor = foo(uStruct);
7270 })";
7271 
7272     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
7273 
7274     // Initialize the texture with green.
7275     GLTexture tex;
7276     glActiveTexture(GL_TEXTURE0);
7277     glBindTexture(GL_TEXTURE_2D, tex);
7278     GLubyte texData[] = {0u, 255u, 0u, 255u};
7279     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
7280     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7281     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7282     ASSERT_GL_NO_ERROR();
7283 
7284     // Draw
7285     glUseProgram(program);
7286     GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.nest.samplerMember");
7287     ASSERT_NE(-1, samplerMemberLoc);
7288     glUniform1i(samplerMemberLoc, 0);
7289     GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
7290     ASSERT_NE(-1, texCoordLoc);
7291     glUniform2f(texCoordLoc, 0.5f, 0.5f);
7292 
7293     GLint bLoc = glGetUniformLocation(program, "uStruct.b");
7294     ASSERT_NE(-1, bLoc);
7295     glUniform1i(bLoc, 1);
7296 
7297     GLint nestbLoc = glGetUniformLocation(program, "uStruct.nest.b");
7298     ASSERT_NE(-1, nestbLoc);
7299     glUniform1i(nestbLoc, 1);
7300 
7301     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
7302     ASSERT_GL_NO_ERROR();
7303 
7304     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
7305 }
7306 // Test that a global variable declared after main() works. This is a regression test for an issue
7307 // in global variable initialization.
TEST_P(WebGLGLSLTest,GlobalVariableDeclaredAfterMain)7308 TEST_P(WebGLGLSLTest, GlobalVariableDeclaredAfterMain)
7309 {
7310     constexpr char kFS[] =
7311         "precision mediump float;\n"
7312         "int getFoo();\n"
7313         "uniform int u_zero;\n"
7314         "void main()\n"
7315         "{\n"
7316         "    gl_FragColor = vec4(1, 0, 0, 1);\n"
7317         "    if (getFoo() == 0)\n"
7318         "    {\n"
7319         "        gl_FragColor = vec4(0, 1, 0, 1);\n"
7320         "    }\n"
7321         "}\n"
7322         "int foo;\n"
7323         "int getFoo()\n"
7324         "{\n"
7325         "    foo = u_zero;\n"
7326         "    return foo;\n"
7327         "}\n";
7328 
7329     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
7330     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
7331     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7332 }
7333 
7334 // Test calling array length() with a "this" expression having side effects inside a loop condition.
7335 // The spec says that sequence operator operands need to run in sequence.
TEST_P(GLSLTest_ES3,ArrayLengthOnExpressionWithSideEffectsInLoopCondition)7336 TEST_P(GLSLTest_ES3, ArrayLengthOnExpressionWithSideEffectsInLoopCondition)
7337 {
7338     // "a" gets doubled three times in the below program.
7339     constexpr char kFS[] = R"(#version 300 es
7340 precision highp float;
7341 out vec4 my_FragColor;
7342 uniform int u_zero;
7343 int a;
7344 int[2] doubleA()
7345 {
7346     a *= 2;
7347     return int[2](a, a);
7348 }
7349 void main()
7350 {
7351     a = u_zero + 1;
7352     for (int i = 0; i < doubleA().length(); ++i)
7353     {}
7354     if (a == 8)
7355     {
7356         my_FragColor = vec4(0, 1, 0, 1);
7357     }
7358     else
7359     {
7360         my_FragColor = vec4(1, 0, 0, 1);
7361     }
7362 })";
7363 
7364     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7365     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
7366     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7367 }
7368 
7369 // Test calling array length() with a "this" expression having side effects that interact with side
7370 // effects of another operand of the same sequence operator. The spec says that sequence operator
7371 // operands need to run in order from left to right (ESSL 3.00.6 section 5.9).
TEST_P(GLSLTest_ES3,ArrayLengthOnExpressionWithSideEffectsInSequence)7372 TEST_P(GLSLTest_ES3, ArrayLengthOnExpressionWithSideEffectsInSequence)
7373 {
7374     constexpr char kFS[] = R"(#version 300 es
7375 precision highp float;
7376 out vec4 my_FragColor;
7377 uniform int u_zero;
7378 int a;
7379 int[3] doubleA()
7380 {
7381     a *= 2;
7382     return int[3](a, a, a);
7383 }
7384 void main()
7385 {
7386     a = u_zero;
7387     int b = (a++, doubleA().length());
7388     if (b == 3 && a == 2)
7389     {
7390         my_FragColor = vec4(0, 1, 0, 1);
7391     }
7392     else
7393     {
7394         my_FragColor = vec4(1, 0, 0, 1);
7395     }
7396 })";
7397 
7398     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7399     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
7400     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7401 }
7402 
7403 // Test calling array length() with a "this" expression that also contains a call of array length().
7404 // Both "this" expressions also have side effects.
TEST_P(GLSLTest_ES3,NestedArrayLengthMethodsWithSideEffects)7405 TEST_P(GLSLTest_ES3, NestedArrayLengthMethodsWithSideEffects)
7406 {
7407     constexpr char kFS[] = R"(#version 300 es
7408 precision highp float;
7409 out vec4 my_FragColor;
7410 uniform int u_zero;
7411 int a;
7412 int[3] multiplyA(int multiplier)
7413 {
7414     a *= multiplier;
7415     return int[3](a, a, a);
7416 }
7417 void main()
7418 {
7419     a = u_zero + 1;
7420     int b = multiplyA(multiplyA(2).length()).length();
7421     if (b == 3 && a == 6)
7422     {
7423         my_FragColor = vec4(0, 1, 0, 1);
7424     }
7425     else
7426     {
7427         my_FragColor = vec4(1, 0, 0, 1);
7428     }
7429 })";
7430 
7431     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7432     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
7433     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7434 }
7435 
7436 // Test calling array length() with a "this" expression having side effects inside an if condition.
7437 // This is an issue if the the side effect can be short circuited.
TEST_P(GLSLTest_ES3,ArrayLengthOnShortCircuitedExpressionWithSideEffectsInIfCondition)7438 TEST_P(GLSLTest_ES3, ArrayLengthOnShortCircuitedExpressionWithSideEffectsInIfCondition)
7439 {
7440     // Bug in the shader translator.  http://anglebug.com/3829
7441     ANGLE_SKIP_TEST_IF(true);
7442 
7443     // "a" shouldn't get modified by this shader.
7444     constexpr char kFS[] = R"(#version 300 es
7445 precision highp float;
7446 out vec4 my_FragColor;
7447 uniform int u_zero;
7448 int a;
7449 int[2] doubleA()
7450 {
7451     a *= 2;
7452     return int[2](a, a);
7453 }
7454 void main()
7455 {
7456     a = u_zero + 1;
7457     if (u_zero != 0 && doubleA().length() == 2)
7458     {
7459         ++a;
7460     }
7461     if (a == 1)
7462     {
7463         my_FragColor = vec4(0, 1, 0, 1);
7464     }
7465     else
7466     {
7467         my_FragColor = vec4(1, 0, 0, 1);
7468     }
7469 })";
7470 
7471     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7472     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
7473     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7474 }
7475 
7476 // Test calling array length() with a "this" expression having side effects in a statement where the
7477 // side effect can be short circuited.
TEST_P(GLSLTest_ES3,ArrayLengthOnShortCircuitedExpressionWithSideEffectsInStatement)7478 TEST_P(GLSLTest_ES3, ArrayLengthOnShortCircuitedExpressionWithSideEffectsInStatement)
7479 {
7480     // Bug in the shader translator.  http://anglebug.com/3829
7481     ANGLE_SKIP_TEST_IF(true);
7482 
7483     // "a" shouldn't get modified by this shader.
7484     constexpr char kFS[] = R"(#version 300 es
7485 precision highp float;
7486 out vec4 my_FragColor;
7487 uniform int u_zero;
7488 int a;
7489 int[2] doubleA()
7490 {
7491     a *= 2;
7492     return int[2](a, a);
7493 }
7494 void main()
7495 {
7496     a = u_zero + 1;
7497     bool test = u_zero != 0 && doubleA().length() == 2;
7498     if (a == 1)
7499     {
7500         my_FragColor = vec4(0, 1, 0, 1);
7501     }
7502     else
7503     {
7504         my_FragColor = vec4(1, 0, 0, 1);
7505     }
7506 })";
7507 
7508     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7509     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
7510     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7511 }
7512 
7513 // Test that statements inside switch() get translated to correct HLSL.
TEST_P(GLSLTest_ES3,DifferentStatementsInsideSwitch)7514 TEST_P(GLSLTest_ES3, DifferentStatementsInsideSwitch)
7515 {
7516     constexpr char kFS[] = R"(#version 300 es
7517 precision highp float;
7518 uniform int u;
7519 void main()
7520 {
7521     switch (u)
7522     {
7523         case 0:
7524             ivec2 i;
7525             i.yx;
7526     }
7527 })";
7528 
7529     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7530 }
7531 
7532 // Test that switch fall-through works correctly.
7533 // This is a regression test for http://anglebug.com/2178
TEST_P(GLSLTest_ES3,SwitchFallThroughCodeDuplication)7534 TEST_P(GLSLTest_ES3, SwitchFallThroughCodeDuplication)
7535 {
7536     constexpr char kFS[] = R"(#version 300 es
7537 precision highp float;
7538 out vec4 my_FragColor;
7539 uniform int u_zero;
7540 
7541 void main()
7542 {
7543     int i = 0;
7544     // switch should fall through both cases.
7545     switch(u_zero)
7546     {
7547         case 0:
7548             i += 1;
7549         case 1:
7550             i += 2;
7551     }
7552     if (i == 3)
7553     {
7554         my_FragColor = vec4(0, 1, 0, 1);
7555     }
7556     else
7557     {
7558         my_FragColor = vec4(1, 0, 0, 1);
7559     }
7560 })";
7561 
7562     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7563     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
7564     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7565 }
7566 
7567 // Test switch/case where default is last.
TEST_P(GLSLTest_ES3,SwitchWithDefaultAtTheEnd)7568 TEST_P(GLSLTest_ES3, SwitchWithDefaultAtTheEnd)
7569 {
7570     constexpr char kFS[] = R"(#version 300 es
7571 
7572 precision highp float;
7573 out vec4 my_FragColor;
7574 
7575 uniform int u_zero;
7576 
7577 void main()
7578 {
7579     switch (u_zero)
7580     {
7581         case 1:
7582             my_FragColor = vec4(1, 0, 0, 1);
7583             break;
7584         default:
7585             my_FragColor = vec4(0, 1, 0, 1);
7586     }
7587 })";
7588 
7589     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7590     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
7591     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7592 }
7593 
7594 // Test that a switch statement with an empty block inside as a final statement compiles.
TEST_P(GLSLTest_ES3,SwitchFinalCaseHasEmptyBlock)7595 TEST_P(GLSLTest_ES3, SwitchFinalCaseHasEmptyBlock)
7596 {
7597     constexpr char kFS[] = R"(#version 300 es
7598 
7599 precision mediump float;
7600 uniform int i;
7601 void main()
7602 {
7603     switch (i)
7604     {
7605         case 0:
7606             break;
7607         default:
7608             {}
7609     }
7610 })";
7611     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7612 }
7613 
7614 // Test that a switch statement with an empty declaration inside as a final statement compiles.
TEST_P(GLSLTest_ES3,SwitchFinalCaseHasEmptyDeclaration)7615 TEST_P(GLSLTest_ES3, SwitchFinalCaseHasEmptyDeclaration)
7616 {
7617     constexpr char kFS[] = R"(#version 300 es
7618 
7619 precision mediump float;
7620 uniform int i;
7621 void main()
7622 {
7623     switch (i)
7624     {
7625         case 0:
7626             break;
7627         default:
7628             float;
7629     }
7630 })";
7631     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7632 }
7633 
7634 // Test switch/case where break/return statements are within blocks.
TEST_P(GLSLTest_ES3,SwitchBreakOrReturnInsideBlocks)7635 TEST_P(GLSLTest_ES3, SwitchBreakOrReturnInsideBlocks)
7636 {
7637     constexpr char kFS[] = R"(#version 300 es
7638 
7639 precision highp float;
7640 
7641 uniform int u_zero;
7642 out vec4 my_FragColor;
7643 
7644 bool test(int n)
7645 {
7646     switch(n) {
7647         case 0:
7648         {
7649             {
7650                 break;
7651             }
7652         }
7653         case 1:
7654         {
7655             return true;
7656         }
7657         case 2:
7658         {
7659             n++;
7660         }
7661     }
7662     return false;
7663 }
7664 
7665 void main()
7666 {
7667     my_FragColor = test(u_zero + 1) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
7668 })";
7669 
7670     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7671     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
7672     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7673 }
7674 
7675 // Test switch/case where a variable is declared inside one of the cases and is accessed by a
7676 // subsequent case.
TEST_P(GLSLTest_ES3,SwitchWithVariableDeclarationInside)7677 TEST_P(GLSLTest_ES3, SwitchWithVariableDeclarationInside)
7678 {
7679     constexpr char kFS[] = R"(#version 300 es
7680 
7681 precision highp float;
7682 out vec4 my_FragColor;
7683 
7684 uniform int u_zero;
7685 
7686 void main()
7687 {
7688     my_FragColor = vec4(1, 0, 0, 1);
7689     switch (u_zero)
7690     {
7691         case 0:
7692             ivec2 i;
7693             i = ivec2(1, 0);
7694         default:
7695             my_FragColor = vec4(0, i[0], 0, 1);
7696     }
7697 })";
7698 
7699     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7700     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
7701     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7702 }
7703 
7704 // Test nested switch/case where a variable is declared inside one of the cases and is accessed by a
7705 // subsequent case.
TEST_P(GLSLTest_ES3,NestedSwitchWithVariableDeclarationInside)7706 TEST_P(GLSLTest_ES3, NestedSwitchWithVariableDeclarationInside)
7707 {
7708     constexpr char kFS[] = R"(#version 300 es
7709 
7710 precision highp float;
7711 out vec4 my_FragColor;
7712 
7713 uniform int u_zero;
7714 uniform int u_zero2;
7715 
7716 void main()
7717 {
7718     my_FragColor = vec4(1, 0, 0, 1);
7719     switch (u_zero)
7720     {
7721         case 0:
7722             ivec2 i;
7723             i = ivec2(1, 0);
7724             switch (u_zero2)
7725             {
7726                 case 0:
7727                     int j;
7728                 default:
7729                     j = 1;
7730                     i *= j;
7731             }
7732         default:
7733             my_FragColor = vec4(0, i[0], 0, 1);
7734     }
7735 })";
7736 
7737     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7738     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
7739     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7740 }
7741 
7742 // Test that an empty switch/case statement is translated in a way that compiles and executes the
7743 // init-statement.
TEST_P(GLSLTest_ES3,EmptySwitch)7744 TEST_P(GLSLTest_ES3, EmptySwitch)
7745 {
7746     constexpr char kFS[] = R"(#version 300 es
7747 
7748 precision highp float;
7749 
7750 uniform int u_zero;
7751 out vec4 my_FragColor;
7752 
7753 void main()
7754 {
7755     int i = u_zero;
7756     switch(++i) {}
7757     my_FragColor = (i == 1) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
7758 })";
7759 
7760     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7761     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
7762     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7763 }
7764 
7765 // Test that a constant struct inside an expression is handled correctly.
TEST_P(GLSLTest_ES3,ConstStructInsideExpression)7766 TEST_P(GLSLTest_ES3, ConstStructInsideExpression)
7767 {
7768     // Incorrect output color was seen on Android. http://anglebug.com/2226
7769     ANGLE_SKIP_TEST_IF(IsAndroid() && !IsNVIDIA() && IsOpenGLES());
7770 
7771     constexpr char kFS[] = R"(#version 300 es
7772 
7773 precision highp float;
7774 out vec4 my_FragColor;
7775 
7776 uniform float u_zero;
7777 
7778 struct S
7779 {
7780     float field;
7781 };
7782 
7783 void main()
7784 {
7785     const S constS = S(1.0);
7786     S nonConstS = constS;
7787     nonConstS.field = u_zero;
7788     bool fail = (constS == nonConstS);
7789     my_FragColor = vec4(0, 1, 0, 1);
7790     if (fail)
7791     {
7792         my_FragColor = vec4(1, 0, 0, 1);
7793     }
7794 })";
7795 
7796     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7797     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
7798     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7799 }
7800 
7801 // Test that a varying struct that's defined as a part of the declaration is handled correctly.
TEST_P(GLSLTest_ES3,VaryingStructWithInlineDefinition)7802 TEST_P(GLSLTest_ES3, VaryingStructWithInlineDefinition)
7803 {
7804     // TODO(anglebug.com/5491): iOS thinks that the precision qualifiers don't match on the
7805     // struct member. Not sure if it's being overly strict.
7806     ANGLE_SKIP_TEST_IF(IsIOS() && IsOpenGLES());
7807     constexpr char kVS[] = R"(#version 300 es
7808 in vec4 inputAttribute;
7809 
7810 flat out struct S
7811 {
7812     int field;
7813 } v_s;
7814 
7815 void main()
7816 {
7817     v_s.field = 1;
7818     gl_Position = inputAttribute;
7819 })";
7820 
7821     constexpr char kFS[] = R"(#version 300 es
7822 
7823 precision highp float;
7824 out vec4 my_FragColor;
7825 
7826 flat in struct S
7827 {
7828     int field;
7829 } v_s;
7830 
7831 void main()
7832 {
7833     bool success = (v_s.field == 1);
7834     my_FragColor = vec4(1, 0, 0, 1);
7835     if (success)
7836     {
7837         my_FragColor = vec4(0, 1, 0, 1);
7838     }
7839 })";
7840 
7841     ANGLE_GL_PROGRAM(program, kVS, kFS);
7842     drawQuad(program.get(), "inputAttribute", 0.5f);
7843     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7844 }
7845 
7846 // Test mismatched precision in varying is handled correctly.
TEST_P(GLSLTest_ES3,MismatchPrecisionFloat)7847 TEST_P(GLSLTest_ES3, MismatchPrecisionFloat)
7848 {
7849     constexpr char kVS[] = R"(#version 300 es
7850 in vec4 position;
7851 uniform highp float inVal;
7852 out highp float myVarying;
7853 
7854 void main()
7855 {
7856     myVarying = inVal;
7857     gl_Position = position;
7858 })";
7859 
7860     constexpr char kFS[] = R"(#version 300 es
7861 precision highp float;
7862 out vec4 my_FragColor;
7863 in mediump float myVarying;
7864 
7865 void main()
7866 {
7867     my_FragColor = vec4(1, 0, 0, 1);
7868     if (myVarying > 1.0)
7869     {
7870         my_FragColor = vec4(0, 1, 0, 1);
7871     }
7872 })";
7873 
7874     ANGLE_GL_PROGRAM(program, kVS, kFS);
7875 
7876     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
7877     glClear(GL_COLOR_BUFFER_BIT);
7878     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7879 
7880     glUseProgram(program.get());
7881     GLint positionLocation              = glGetAttribLocation(program.get(), "position");
7882     std::array<Vector3, 6> quadVertices = GetQuadVertices();
7883     for (Vector3 &vertex : quadVertices)
7884     {
7885         vertex.z() = 0.5f;
7886     }
7887     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
7888     glEnableVertexAttribArray(positionLocation);
7889 
7890     GLint inValLoc = glGetUniformLocation(program, "inVal");
7891     ASSERT_NE(-1, inValLoc);
7892     glUniform1f(inValLoc, static_cast<GLfloat>(1.003));
7893 
7894     glDrawArrays(GL_TRIANGLES, 0, 6);
7895     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7896 }
7897 
7898 // Test mismatched precision in varying is handled correctly.
TEST_P(GLSLTest_ES3,MismatchPrecisionlowpFloat)7899 TEST_P(GLSLTest_ES3, MismatchPrecisionlowpFloat)
7900 {
7901     // Note: SPIRV only has relaxed precision so both lowp and mediump turn into "relaxed
7902     // precision", thus this is the same test as MismatchPrecisionFloat but including it for
7903     // completeness in case something changes.
7904     constexpr char kVS[] = R"(#version 300 es
7905 in vec4 position;
7906 uniform highp float inVal;
7907 out highp float myVarying;
7908 
7909 void main()
7910 {
7911     myVarying = inVal;
7912     gl_Position = position;
7913 })";
7914 
7915     constexpr char kFS[] = R"(#version 300 es
7916 precision highp float;
7917 out vec4 my_FragColor;
7918 in lowp float myVarying;
7919 
7920 void main()
7921 {
7922     my_FragColor = vec4(1, 0, 0, 1);
7923     if (myVarying > 1.0)
7924     {
7925         my_FragColor = vec4(0, 1, 0, 1);
7926     }
7927 })";
7928 
7929     ANGLE_GL_PROGRAM(program, kVS, kFS);
7930 
7931     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
7932     glClear(GL_COLOR_BUFFER_BIT);
7933     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7934 
7935     glUseProgram(program.get());
7936     GLint positionLocation              = glGetAttribLocation(program.get(), "position");
7937     std::array<Vector3, 6> quadVertices = GetQuadVertices();
7938     for (Vector3 &vertex : quadVertices)
7939     {
7940         vertex.z() = 0.5f;
7941     }
7942     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
7943     glEnableVertexAttribArray(positionLocation);
7944 
7945     GLint inValLoc = glGetUniformLocation(program, "inVal");
7946     ASSERT_NE(-1, inValLoc);
7947     glUniform1f(inValLoc, static_cast<GLfloat>(1.003));
7948 
7949     glDrawArrays(GL_TRIANGLES, 0, 6);
7950     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7951 }
7952 
7953 // Test mismatched precision in varying is handled correctly.
TEST_P(GLSLTest_ES3,MismatchPrecisionVec2UnusedVarying)7954 TEST_P(GLSLTest_ES3, MismatchPrecisionVec2UnusedVarying)
7955 {
7956     constexpr char kVS[] = R"(#version 300 es
7957 in vec2 position;
7958 uniform highp float inVal;
7959 out highp float myVarying;
7960 out highp vec2 texCoord;
7961 
7962 void main()
7963 {
7964     myVarying = inVal;
7965     gl_Position = vec4(position, 0, 1);
7966     texCoord = position * 0.5 + vec2(0.5);
7967 })";
7968 
7969     constexpr char kFS[] = R"(#version 300 es
7970 precision highp float;
7971 out vec4 my_FragColor;
7972 in mediump float myVarying;
7973 in mediump vec2 texCoord;
7974 
7975 void main()
7976 {
7977     my_FragColor = vec4(1, 0, 0, 1);
7978     if (myVarying > 1.0)
7979     {
7980         my_FragColor = vec4(0, 1, 0, 1);
7981     }
7982 })";
7983 
7984     ANGLE_GL_PROGRAM(program, kVS, kFS);
7985 
7986     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
7987     glClear(GL_COLOR_BUFFER_BIT);
7988     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7989 
7990     glUseProgram(program.get());
7991     GLint positionLocation              = glGetAttribLocation(program.get(), "position");
7992     std::array<Vector3, 6> quadVertices = GetQuadVertices();
7993     for (Vector3 &vertex : quadVertices)
7994     {
7995         vertex.z() = 0.5f;
7996     }
7997     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
7998     glEnableVertexAttribArray(positionLocation);
7999 
8000     GLint inValLoc = glGetUniformLocation(program, "inVal");
8001     ASSERT_NE(-1, inValLoc);
8002     glUniform1f(inValLoc, static_cast<GLfloat>(1.003));
8003 
8004     glDrawArrays(GL_TRIANGLES, 0, 6);
8005     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8006 }
8007 
8008 // Test mismatched precision in varying is handled correctly.
TEST_P(GLSLTest_ES3,MismatchPrecisionMedToHigh)8009 TEST_P(GLSLTest_ES3, MismatchPrecisionMedToHigh)
8010 {
8011     constexpr char kVS[] = R"(#version 300 es
8012 in vec2 position;
8013 uniform highp float inVal;
8014 out mediump float myVarying;
8015 
8016 void main()
8017 {
8018     myVarying = inVal;
8019     gl_Position = vec4(position, 0, 1);
8020 })";
8021 
8022     constexpr char kFS[] = R"(#version 300 es
8023 precision highp float;
8024 out vec4 my_FragColor;
8025 in highp float myVarying;
8026 
8027 void main()
8028 {
8029     my_FragColor = vec4(1, 0, 0, 1);
8030     if (myVarying > 1.0)
8031     {
8032         my_FragColor = vec4(0, 1, 0, 1);
8033     }
8034 })";
8035 
8036     ANGLE_GL_PROGRAM(program, kVS, kFS);
8037 
8038     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
8039     glClear(GL_COLOR_BUFFER_BIT);
8040     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
8041 
8042     glUseProgram(program.get());
8043     GLint positionLocation              = glGetAttribLocation(program.get(), "position");
8044     std::array<Vector3, 6> quadVertices = GetQuadVertices();
8045     for (Vector3 &vertex : quadVertices)
8046     {
8047         vertex.z() = 0.5f;
8048     }
8049     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
8050     glEnableVertexAttribArray(positionLocation);
8051 
8052     GLint inValLoc = glGetUniformLocation(program, "inVal");
8053     ASSERT_NE(-1, inValLoc);
8054     glUniform1f(inValLoc, static_cast<GLfloat>(1.003));
8055 
8056     glDrawArrays(GL_TRIANGLES, 0, 6);
8057     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8058 }
8059 
8060 // Test vector/scalar arithmetic (in this case multiplication and addition).
TEST_P(GLSLTest,VectorScalarMultiplyAndAddInLoop)8061 TEST_P(GLSLTest, VectorScalarMultiplyAndAddInLoop)
8062 {
8063     constexpr char kFS[] = R"(precision mediump float;
8064 
8065 void main() {
8066     gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
8067     for (int i = 0; i < 2; i++)
8068     {
8069         gl_FragColor += (2.0 * gl_FragCoord.x);
8070     }
8071     if (gl_FragColor.g == gl_FragColor.r &&
8072         gl_FragColor.b == gl_FragColor.r &&
8073         gl_FragColor.a == gl_FragColor.r)
8074     {
8075         gl_FragColor = vec4(0, 1, 0, 1);
8076     }
8077 })";
8078 
8079     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
8080     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
8081     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8082 }
8083 
8084 // Test vector/scalar arithmetic (in this case compound division and addition).
TEST_P(GLSLTest,VectorScalarDivideAndAddInLoop)8085 TEST_P(GLSLTest, VectorScalarDivideAndAddInLoop)
8086 {
8087     constexpr char kFS[] = R"(precision mediump float;
8088 
8089 void main() {
8090     gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
8091     for (int i = 0; i < 2; i++)
8092     {
8093         float x = gl_FragCoord.x;
8094         gl_FragColor = gl_FragColor + (x /= 2.0);
8095     }
8096     if (gl_FragColor.g == gl_FragColor.r &&
8097         gl_FragColor.b == gl_FragColor.r &&
8098         gl_FragColor.a == gl_FragColor.r)
8099     {
8100         gl_FragColor = vec4(0, 1, 0, 1);
8101     }
8102 })";
8103 
8104     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
8105     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
8106     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8107 }
8108 
8109 // Test that a varying with a flat qualifier that is used as an operand of a folded ternary operator
8110 // is handled correctly.
TEST_P(GLSLTest_ES3,FlatVaryingUsedInFoldedTernary)8111 TEST_P(GLSLTest_ES3, FlatVaryingUsedInFoldedTernary)
8112 {
8113     constexpr char kVS[] = R"(#version 300 es
8114 
8115 in vec4 inputAttribute;
8116 
8117 flat out int v;
8118 
8119 void main()
8120 {
8121     v = 1;
8122     gl_Position = inputAttribute;
8123 })";
8124 
8125     constexpr char kFS[] = R"(#version 300 es
8126 
8127 precision highp float;
8128 out vec4 my_FragColor;
8129 
8130 flat in int v;
8131 
8132 void main()
8133 {
8134     my_FragColor = vec4(0, (true ? v : 0), 0, 1);
8135 })";
8136 
8137     ANGLE_GL_PROGRAM(program, kVS, kFS);
8138     drawQuad(program.get(), "inputAttribute", 0.5f);
8139     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8140 }
8141 
8142 // Verify that the link error message from last link failure is cleared when the new link is
8143 // finished.
TEST_P(GLSLTest,ClearLinkErrorLog)8144 TEST_P(GLSLTest, ClearLinkErrorLog)
8145 {
8146     constexpr char kVS[] = R"(attribute vec4 vert_in;
8147 varying vec4 vert_out;
8148 void main()
8149 {
8150     gl_Position = vert_in;
8151     vert_out = vert_in;
8152 })";
8153 
8154     constexpr char kFS[] = R"(precision mediump float;
8155 varying vec4 frag_in;
8156 void main()
8157 {
8158     gl_FragColor = frag_in;
8159 })";
8160 
8161     GLuint vs = CompileShader(GL_VERTEX_SHADER, kVS);
8162     GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
8163 
8164     GLuint program = glCreateProgram();
8165 
8166     // The first time the program link fails because of lack of fragment shader.
8167     glAttachShader(program, vs);
8168     glLinkProgram(program);
8169     GLint linkStatus = GL_TRUE;
8170     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
8171     ASSERT_FALSE(linkStatus);
8172 
8173     const std::string &lackOfFragmentShader = QueryErrorMessage(program);
8174 
8175     // The second time the program link fails because of the mismatch of the varying types.
8176     glAttachShader(program, fs);
8177     glLinkProgram(program);
8178     linkStatus = GL_TRUE;
8179     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
8180     ASSERT_FALSE(linkStatus);
8181 
8182     const std::string &varyingTypeMismatch = QueryErrorMessage(program);
8183 
8184     EXPECT_EQ(std::string::npos, varyingTypeMismatch.find(lackOfFragmentShader));
8185 
8186     glDetachShader(program, vs);
8187     glDetachShader(program, fs);
8188     glDeleteShader(vs);
8189     glDeleteShader(fs);
8190     glDeleteProgram(program);
8191 
8192     ASSERT_GL_NO_ERROR();
8193 }
8194 
8195 // Verify that a valid program still draws correctly after a shader link error
TEST_P(GLSLTest,DrawAfterShaderLinkError)8196 TEST_P(GLSLTest, DrawAfterShaderLinkError)
8197 {
8198     constexpr char kVS[]    = R"(attribute vec4 position;
8199         varying vec4 vColor;
8200         void main()
8201         {
8202             vColor = vec4(0.0, 1.0, 0.0, 1.0);
8203             gl_Position = position;
8204         })";
8205     constexpr char kFS[]    = R"(precision mediump float;
8206         varying vec4 vColor;
8207         void main()
8208         {
8209             gl_FragColor = vColor;
8210         })";
8211     constexpr char kBadFS[] = R"(WILL NOT COMPILE;)";
8212 
8213     GLuint fsBad = glCreateShader(GL_FRAGMENT_SHADER);
8214 
8215     // Create bad fragment shader
8216     {
8217         const char *sourceArray[1] = {kBadFS};
8218         glShaderSource(fsBad, 1, sourceArray, nullptr);
8219         glCompileShader(fsBad);
8220 
8221         GLint compileResult;
8222         glGetShaderiv(fsBad, GL_COMPILE_STATUS, &compileResult);
8223         ASSERT_FALSE(compileResult);
8224     }
8225 
8226     ANGLE_GL_PROGRAM(program, kVS, kFS);
8227     GLuint fs = GetProgramShader(program.get(), GL_FRAGMENT_SHADER);
8228 
8229     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
8230     glClear(GL_COLOR_BUFFER_BIT);
8231     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
8232 
8233     glUseProgram(program.get());
8234     GLint positionLocation              = glGetAttribLocation(program.get(), "position");
8235     std::array<Vector3, 6> quadVertices = GetQuadVertices();
8236     for (Vector3 &vertex : quadVertices)
8237     {
8238         vertex.z() = 0.5f;
8239     }
8240     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
8241     glEnableVertexAttribArray(positionLocation);
8242     glDrawArrays(GL_TRIANGLES, 0, 6);
8243     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8244 
8245     glDetachShader(program.get(), fs);
8246     glAttachShader(program.get(), fsBad);
8247     glLinkProgram(program.get());
8248     GLint linkStatus = GL_TRUE;
8249     glGetProgramiv(program.get(), GL_LINK_STATUS, &linkStatus);
8250     ASSERT_FALSE(linkStatus);
8251 
8252     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
8253     glClear(GL_COLOR_BUFFER_BIT);
8254     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
8255 
8256     glDrawArrays(GL_TRIANGLES, 0, 6);
8257     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8258 }
8259 
8260 // Validate error messages when the link mismatch occurs on the type of a non-struct varying.
TEST_P(GLSLTest,ErrorMessageOfVaryingMismatch)8261 TEST_P(GLSLTest, ErrorMessageOfVaryingMismatch)
8262 {
8263     constexpr char kVS[] = R"(attribute vec4 inputAttribute;
8264 varying vec4 vertex_out;
8265 void main()
8266 {
8267     vertex_out = inputAttribute;
8268     gl_Position = inputAttribute;
8269 })";
8270 
8271     constexpr char kFS[] = R"(precision mediump float;
8272 varying float vertex_out;
8273 void main()
8274 {
8275     gl_FragColor = vec4(vertex_out, 0.0, 0.0, 1.0);
8276 })";
8277 
8278     validateComponentsInErrorMessage(kVS, kFS, "Types", "varying 'vertex_out'");
8279 }
8280 
8281 // Validate error messages when the link mismatch occurs on the name of a varying field.
TEST_P(GLSLTest_ES3,ErrorMessageOfVaryingStructFieldNameMismatch)8282 TEST_P(GLSLTest_ES3, ErrorMessageOfVaryingStructFieldNameMismatch)
8283 {
8284     constexpr char kVS[] = R"(#version 300 es
8285 in vec4 inputAttribute;
8286 struct S {
8287     float val1;
8288     vec4 val2;
8289 };
8290 out S vertex_out;
8291 void main()
8292 {
8293     vertex_out.val2 = inputAttribute;
8294     vertex_out.val1 = inputAttribute[0];
8295     gl_Position = inputAttribute;
8296 })";
8297 
8298     constexpr char kFS[] = R"(#version 300 es
8299 precision mediump float;
8300 struct S {
8301     float val1;
8302     vec4 val3;
8303 };
8304 in S vertex_out;
8305 layout (location = 0) out vec4 frag_out;
8306 void main()
8307 {
8308     frag_out = vec4(vertex_out.val1, 0.0, 0.0, 1.0);
8309 })";
8310 
8311     validateComponentsInErrorMessage(kVS, kFS, "Field names", "varying 'vertex_out'");
8312 }
8313 
8314 // Validate error messages when the link mismatch occurs on the type of a varying field.
TEST_P(GLSLTest_ES3,ErrorMessageOfVaryingStructFieldMismatch)8315 TEST_P(GLSLTest_ES3, ErrorMessageOfVaryingStructFieldMismatch)
8316 {
8317     constexpr char kVS[] = R"(#version 300 es
8318 in vec4 inputAttribute;
8319 struct S {
8320     float val1;
8321     vec4 val2;
8322 };
8323 out S vertex_out;
8324 void main()
8325 {
8326     vertex_out.val2 = inputAttribute;
8327     vertex_out.val1 = inputAttribute[0];
8328     gl_Position = inputAttribute;
8329 })";
8330 
8331     constexpr char kFS[] = R"(#version 300 es
8332 precision mediump float;
8333 struct S {
8334     float val1;
8335     vec2 val2;
8336 };
8337 in S vertex_out;
8338 layout (location = 0) out vec4 frag_out;
8339 void main()
8340 {
8341     frag_out = vec4(vertex_out.val1, 0.0, 0.0, 1.0);
8342 })";
8343 
8344     validateComponentsInErrorMessage(kVS, kFS, "Types",
8345                                      "varying 'vertex_out' member 'vertex_out.val2'");
8346 }
8347 
8348 // Validate error messages when the link mismatch occurs on the name of a struct member of a uniform
8349 // field.
TEST_P(GLSLTest,ErrorMessageOfLinkUniformStructFieldNameMismatch)8350 TEST_P(GLSLTest, ErrorMessageOfLinkUniformStructFieldNameMismatch)
8351 {
8352     constexpr char kVS[] = R"(
8353 struct T
8354 {
8355     vec2 t1;
8356     vec3 t2;
8357 };
8358 struct S {
8359     T val1;
8360     vec4 val2;
8361 };
8362 uniform S uni;
8363 
8364 attribute vec4 inputAttribute;
8365 varying vec4 vertex_out;
8366 void main()
8367 {
8368     vertex_out = uni.val2;
8369     gl_Position = inputAttribute;
8370 })";
8371 
8372     constexpr char kFS[] = R"(precision highp float;
8373 struct T
8374 {
8375     vec2 t1;
8376     vec3 t3;
8377 };
8378 struct S {
8379     T val1;
8380     vec4 val2;
8381 };
8382 uniform S uni;
8383 
8384 varying vec4 vertex_out;
8385 void main()
8386 {
8387     gl_FragColor = vec4(uni.val1.t1[0], 0.0, 0.0, 1.0);
8388 })";
8389 
8390     validateComponentsInErrorMessage(kVS, kFS, "Field names", "uniform 'uni' member 'uni.val1'");
8391 }
8392 
8393 // Validate error messages  when the link mismatch occurs on the type of a non-struct uniform block
8394 // field.
TEST_P(GLSLTest_ES3,ErrorMessageOfLinkInterfaceBlockFieldMismatch)8395 TEST_P(GLSLTest_ES3, ErrorMessageOfLinkInterfaceBlockFieldMismatch)
8396 {
8397     constexpr char kVS[] = R"(#version 300 es
8398 uniform S {
8399     vec2 val1;
8400     vec4 val2;
8401 } uni;
8402 
8403 in vec4 inputAttribute;
8404 out vec4 vertex_out;
8405 void main()
8406 {
8407     vertex_out = uni.val2;
8408     gl_Position = inputAttribute;
8409 })";
8410 
8411     constexpr char kFS[] = R"(#version 300 es
8412 precision highp float;
8413 uniform S {
8414     vec2 val1;
8415     vec3 val2;
8416 } uni;
8417 
8418 in vec4 vertex_out;
8419 layout (location = 0) out vec4 frag_out;
8420 void main()
8421 {
8422     frag_out = vec4(uni.val1[0], 0.0, 0.0, 1.0);
8423 })";
8424 
8425     validateComponentsInErrorMessage(kVS, kFS, "Types", "uniform block 'S' member 'S.val2'");
8426 }
8427 
8428 // Validate error messages  when the link mismatch occurs on the type of a member of a uniform block
8429 // struct field.
TEST_P(GLSLTest_ES3,ErrorMessageOfLinkInterfaceBlockStructFieldMismatch)8430 TEST_P(GLSLTest_ES3, ErrorMessageOfLinkInterfaceBlockStructFieldMismatch)
8431 {
8432     constexpr char kVS[] = R"(#version 300 es
8433 struct T
8434 {
8435     vec2 t1;
8436     vec3 t2;
8437 };
8438 uniform S {
8439     T val1;
8440     vec4 val2;
8441 } uni;
8442 
8443 in vec4 inputAttribute;
8444 out vec4 vertex_out;
8445 void main()
8446 {
8447     vertex_out = uni.val2;
8448     gl_Position = inputAttribute;
8449 })";
8450 
8451     constexpr char kFS[] = R"(#version 300 es
8452 precision highp float;
8453 struct T
8454 {
8455     vec2 t1;
8456     vec4 t2;
8457 };
8458 uniform S {
8459     T val1;
8460     vec4 val2;
8461 } uni;
8462 
8463 in vec4 vertex_out;
8464 layout (location = 0) out vec4 frag_out;
8465 void main()
8466 {
8467     frag_out = vec4(uni.val1.t1[0], 0.0, 0.0, 1.0);
8468 })";
8469 
8470     validateComponentsInErrorMessage(kVS, kFS, "Types", "uniform block 'S' member 'S.val1.t2'");
8471 }
8472 
8473 // Test a vertex shader that doesn't declare any varyings with a fragment shader that statically
8474 // uses a varying, but in a statement that gets trivially optimized out by the compiler.
TEST_P(GLSLTest_ES3,FragmentShaderStaticallyUsesVaryingMissingFromVertex)8475 TEST_P(GLSLTest_ES3, FragmentShaderStaticallyUsesVaryingMissingFromVertex)
8476 {
8477     constexpr char kVS[] = R"(#version 300 es
8478 precision mediump float;
8479 
8480 void main()
8481 {
8482     gl_Position = vec4(0, 1, 0, 1);
8483 })";
8484 
8485     constexpr char kFS[] = R"(#version 300 es
8486 precision mediump float;
8487 in float foo;
8488 out vec4 my_FragColor;
8489 
8490 void main()
8491 {
8492     if (false)
8493     {
8494         float unreferenced = foo;
8495     }
8496     my_FragColor = vec4(0, 1, 0, 1);
8497 })";
8498 
8499     validateComponentsInErrorMessage(kVS, kFS, "does not match any", "foo");
8500 }
8501 
8502 // Test a varying that is statically used but not active in the fragment shader.
TEST_P(GLSLTest_ES3,VaryingStaticallyUsedButNotActiveInFragmentShader)8503 TEST_P(GLSLTest_ES3, VaryingStaticallyUsedButNotActiveInFragmentShader)
8504 {
8505     constexpr char kVS[] = R"(#version 300 es
8506 precision mediump float;
8507 in vec4 iv;
8508 out vec4 v;
8509 void main()
8510 {
8511     gl_Position = iv;
8512     v = iv;
8513 })";
8514 
8515     constexpr char kFS[] = R"(#version 300 es
8516 precision mediump float;
8517 in vec4 v;
8518 out vec4 color;
8519 void main()
8520 {
8521     color = true ? vec4(0.0) : v;
8522 })";
8523 
8524     ANGLE_GL_PROGRAM(program, kVS, kFS);
8525 }
8526 
8527 // Test that linking varyings by location works.
TEST_P(GLSLTest_ES31,LinkVaryingsByLocation)8528 TEST_P(GLSLTest_ES31, LinkVaryingsByLocation)
8529 {
8530     constexpr char kVS[] = R"(#version 310 es
8531 precision highp float;
8532 in vec4 position;
8533 layout(location = 1) out vec4 shaderOutput;
8534 void main() {
8535     gl_Position = position;
8536     shaderOutput = vec4(0.0, 1.0, 0.0, 1.0);
8537 })";
8538 
8539     constexpr char kFS[] = R"(#version 310 es
8540 precision highp float;
8541 layout(location = 1) in vec4 shaderInput;
8542 out vec4 outColor;
8543 void main() {
8544     outColor = shaderInput;
8545 })";
8546 
8547     ANGLE_GL_PROGRAM(program, kVS, kFS);
8548     drawQuad(program, "position", 0.5f);
8549     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8550 }
8551 
8552 // Test nesting floor() calls with a large multiplier inside.
TEST_P(GLSLTest_ES3,NestedFloorWithLargeMultiplierInside)8553 TEST_P(GLSLTest_ES3, NestedFloorWithLargeMultiplierInside)
8554 {
8555     // D3D11 seems to ignore the floor() calls in this particular case, so one of the corners ends
8556     // up red. http://crbug.com/838885
8557     ANGLE_SKIP_TEST_IF(IsD3D11());
8558 
8559     constexpr char kFS[] = R"(#version 300 es
8560 precision highp float;
8561 out vec4 my_FragColor;
8562 void main()
8563 {
8564     vec2 coord = gl_FragCoord.xy / 500.0;
8565     my_FragColor = vec4(1, 0, 0, 1);
8566     if (coord.y + 0.1 > floor(1e-6 * floor(coord.x*4e5)))
8567     {
8568         my_FragColor = vec4(0, 1, 0, 1);
8569     }
8570 })";
8571 
8572     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8573     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
8574     // Verify that all the corners of the rendered result are green.
8575     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8576     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
8577     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, 0, GLColor::green);
8578     EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() - 1, GLColor::green);
8579 }
8580 
8581 // Verify that a link error is generated when the sum of the number of active image uniforms and
8582 // active shader storage blocks in a rendering pipeline exceeds
8583 // GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES.
TEST_P(GLSLTest_ES31,ExceedCombinedShaderOutputResourcesInVSAndFS)8584 TEST_P(GLSLTest_ES31, ExceedCombinedShaderOutputResourcesInVSAndFS)
8585 {
8586     // TODO(jiawei.shao@intel.com): enable this test when shader storage buffer is supported on
8587     // D3D11 back-ends.
8588     ANGLE_SKIP_TEST_IF(IsD3D11());
8589 
8590     GLint maxVertexShaderStorageBlocks;
8591     GLint maxVertexImageUniforms;
8592     GLint maxFragmentShaderStorageBlocks;
8593     GLint maxFragmentImageUniforms;
8594     GLint maxCombinedShaderStorageBlocks;
8595     GLint maxCombinedImageUniforms;
8596     glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &maxVertexShaderStorageBlocks);
8597     glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &maxVertexImageUniforms);
8598     glGetIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &maxFragmentShaderStorageBlocks);
8599     glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &maxFragmentImageUniforms);
8600     glGetIntegerv(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, &maxCombinedShaderStorageBlocks);
8601     glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS, &maxCombinedImageUniforms);
8602 
8603     ASSERT_GE(maxCombinedShaderStorageBlocks, maxVertexShaderStorageBlocks);
8604     ASSERT_GE(maxCombinedShaderStorageBlocks, maxFragmentShaderStorageBlocks);
8605     ASSERT_GE(maxCombinedImageUniforms, maxVertexImageUniforms);
8606     ASSERT_GE(maxCombinedImageUniforms, maxFragmentImageUniforms);
8607 
8608     GLint vertexSSBOs   = maxVertexShaderStorageBlocks;
8609     GLint fragmentSSBOs = maxFragmentShaderStorageBlocks;
8610     // Limit the sum of ssbos in vertex and fragment shaders to maxCombinedShaderStorageBlocks.
8611     if (vertexSSBOs + fragmentSSBOs > maxCombinedShaderStorageBlocks)
8612     {
8613         fragmentSSBOs = maxCombinedShaderStorageBlocks - vertexSSBOs;
8614     }
8615 
8616     GLint vertexImages   = maxVertexImageUniforms;
8617     GLint fragmentImages = maxFragmentImageUniforms;
8618     // Limit the sum of images in vertex and fragment shaders to maxCombinedImageUniforms.
8619     if (vertexImages + fragmentImages > maxCombinedImageUniforms)
8620     {
8621         vertexImages = maxCombinedImageUniforms - fragmentImages;
8622     }
8623 
8624     GLint maxDrawBuffers;
8625     glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
8626 
8627     GLint maxCombinedShaderOutputResources;
8628     glGetIntegerv(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, &maxCombinedShaderOutputResources);
8629     ASSERT_GL_NO_ERROR();
8630 
8631     ANGLE_SKIP_TEST_IF(vertexSSBOs + fragmentSSBOs + vertexImages + fragmentImages +
8632                            maxDrawBuffers <=
8633                        maxCombinedShaderOutputResources);
8634 
8635     std::ostringstream vertexStream;
8636     vertexStream << "#version 310 es\n";
8637     for (int i = 0; i < vertexSSBOs; ++i)
8638     {
8639         vertexStream << "layout(shared, binding = " << i << ") buffer blockName" << i
8640                      << "{\n"
8641                         "    float data;\n"
8642                         "} ssbo"
8643                      << i << ";\n";
8644     }
8645     vertexStream << "layout(r32f, binding = 0) uniform highp image2D imageArray[" << vertexImages
8646                  << "];\n";
8647     vertexStream << "void main()\n"
8648                     "{\n"
8649                     "    float val = 0.1;\n"
8650                     "    vec4 val2 = vec4(0.0);\n";
8651     for (int i = 0; i < vertexSSBOs; ++i)
8652     {
8653         vertexStream << "    val += ssbo" << i << ".data; \n";
8654     }
8655     for (int i = 0; i < vertexImages; ++i)
8656     {
8657         vertexStream << "    val2 += imageLoad(imageArray[" << i << "], ivec2(0, 0)); \n";
8658     }
8659     vertexStream << "    gl_Position = vec4(val, val2);\n"
8660                     "}\n";
8661 
8662     std::ostringstream fragmentStream;
8663     fragmentStream << "#version 310 es\n"
8664                    << "precision highp float;\n";
8665     for (int i = 0; i < fragmentSSBOs; ++i)
8666     {
8667         fragmentStream << "layout(shared, binding = " << i << ") buffer blockName" << i
8668                        << "{\n"
8669                           "    float data;\n"
8670                           "} ssbo"
8671                        << i << ";\n";
8672     }
8673     fragmentStream << "layout(r32f, binding = 0) uniform highp image2D imageArray["
8674                    << fragmentImages << "];\n";
8675     fragmentStream << "layout (location = 0) out vec4 foutput[" << maxDrawBuffers << "];\n";
8676 
8677     fragmentStream << "void main()\n"
8678                       "{\n"
8679                       "    float val = 0.1;\n"
8680                       "    vec4 val2 = vec4(0.0);\n";
8681     for (int i = 0; i < fragmentSSBOs; ++i)
8682     {
8683         fragmentStream << "    val += ssbo" << i << ".data; \n";
8684     }
8685     for (int i = 0; i < fragmentImages; ++i)
8686     {
8687         fragmentStream << "    val2 += imageLoad(imageArray[" << i << "], ivec2(0, 0)); \n";
8688     }
8689     for (int i = 0; i < maxDrawBuffers; ++i)
8690     {
8691         fragmentStream << "    foutput[" << i << "] = vec4(val, val2);\n";
8692     }
8693     fragmentStream << "}\n";
8694 
8695     GLuint program = CompileProgram(vertexStream.str().c_str(), fragmentStream.str().c_str());
8696     EXPECT_EQ(0u, program);
8697 
8698     ASSERT_GL_NO_ERROR();
8699 }
8700 
8701 // Test that assigning an assignment expression to a swizzled vector field in a user-defined
8702 // function works correctly.
TEST_P(GLSLTest_ES3,AssignAssignmentToSwizzled)8703 TEST_P(GLSLTest_ES3, AssignAssignmentToSwizzled)
8704 {
8705     constexpr char kFS[] = R"(#version 300 es
8706 precision highp float;
8707 out vec4 my_FragColor;
8708 
8709 uniform float uzero;
8710 
8711 vec3 fun(float s, float v)
8712 {
8713     vec3 r = vec3(0);
8714     if (s < 1.0) {
8715         r.x = r.y = r.z = v;
8716         return r;
8717     }
8718     return r;
8719 }
8720 
8721 void main()
8722 {
8723     my_FragColor.a = 1.0;
8724     my_FragColor.rgb = fun(uzero, 1.0);
8725 })";
8726 
8727     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8728     drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
8729     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
8730 }
8731 
8732 // Test a fragment shader that returns inside if (that being the only branch that actually gets
8733 // executed). Regression test for http://anglebug.com/2325
TEST_P(GLSLTest,IfElseIfAndReturn)8734 TEST_P(GLSLTest, IfElseIfAndReturn)
8735 {
8736     constexpr char kVS[] = R"(attribute vec4 a_position;
8737 varying vec2 vPos;
8738 void main()
8739 {
8740     gl_Position = a_position;
8741     vPos = a_position.xy;
8742 })";
8743 
8744     constexpr char kFS[] = R"(precision mediump float;
8745 varying vec2 vPos;
8746 void main()
8747 {
8748     if (vPos.x < 1.0) // This colors the whole canvas green
8749     {
8750         gl_FragColor = vec4(0, 1, 0, 1);
8751         return;
8752     }
8753     else if (vPos.x < 1.1) // This should have no effect
8754     {
8755         gl_FragColor = vec4(1, 0, 0, 1);
8756     }
8757 })";
8758 
8759     ANGLE_GL_PROGRAM(program, kVS, kFS);
8760     drawQuad(program.get(), "a_position", 0.5f);
8761     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8762 }
8763 
8764 // Test that if-else blocks whose contents get pruned due to compile-time constant conditions work.
TEST_P(GLSLTest,IfElsePrunedBlocks)8765 TEST_P(GLSLTest, IfElsePrunedBlocks)
8766 {
8767     constexpr char kFS[] = R"(precision mediump float;
8768 uniform float u;
8769 void main()
8770 {
8771     // if with only a pruned true block
8772     if (u > 0.0)
8773         if (false) discard;
8774 
8775     // if with a pruned true block and a false block
8776     if (u > 0.0)
8777     {
8778         if (false) discard;
8779     }
8780     else
8781         ;
8782 
8783     // if with a true block and a pruned false block
8784     if (u > 0.0)
8785         ;
8786     else
8787         if (false) discard;
8788 
8789     // if with a pruned true block and a pruned false block
8790     if (u > 0.0)
8791     {
8792         if (false) discard;
8793     }
8794     else
8795         if (false) discard;
8796 
8797     gl_FragColor = vec4(0, 1, 0, 1);
8798 })";
8799 
8800     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
8801     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.5f);
8802     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8803 }
8804 
8805 // Tests that PointCoord behaves the same betweeen a user FBO and the back buffer.
TEST_P(GLSLTest,PointCoordConsistency)8806 TEST_P(GLSLTest, PointCoordConsistency)
8807 {
8808     // http://anglebug.com/4092
8809     ANGLE_SKIP_TEST_IF(isSwiftshader());
8810 
8811     constexpr char kPointCoordVS[] = R"(attribute vec2 position;
8812 uniform vec2 viewportSize;
8813 void main()
8814 {
8815    gl_Position = vec4(position, 0, 1);
8816    gl_PointSize = viewportSize.x;
8817 })";
8818 
8819     constexpr char kPointCoordFS[] = R"(void main()
8820 {
8821     gl_FragColor = vec4(gl_PointCoord.xy, 0, 1);
8822 })";
8823 
8824     ANGLE_GL_PROGRAM(program, kPointCoordVS, kPointCoordFS);
8825     glUseProgram(program);
8826 
8827     GLint uniLoc = glGetUniformLocation(program, "viewportSize");
8828     ASSERT_NE(-1, uniLoc);
8829     glUniform2f(uniLoc, static_cast<GLfloat>(getWindowWidth()),
8830                 static_cast<GLfloat>(getWindowHeight()));
8831 
8832     // Draw to backbuffer.
8833     glClear(GL_COLOR_BUFFER_BIT);
8834     glDrawArrays(GL_POINTS, 0, 1);
8835     ASSERT_GL_NO_ERROR();
8836 
8837     std::vector<GLColor> backbufferData(getWindowWidth() * getWindowHeight());
8838     glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
8839                  backbufferData.data());
8840 
8841     GLTexture tex;
8842     glBindTexture(GL_TEXTURE_2D, tex);
8843     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
8844                  GL_UNSIGNED_BYTE, nullptr);
8845 
8846     GLFramebuffer fbo;
8847     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
8848     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
8849     ASSERT_GL_NO_ERROR();
8850     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
8851 
8852     // Draw to user FBO.
8853     glClear(GL_COLOR_BUFFER_BIT);
8854     glDrawArrays(GL_POINTS, 0, 1);
8855     ASSERT_GL_NO_ERROR();
8856 
8857     std::vector<GLColor> userFBOData(getWindowWidth() * getWindowHeight());
8858     glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
8859                  userFBOData.data());
8860 
8861     ASSERT_GL_NO_ERROR();
8862     ASSERT_EQ(userFBOData.size(), backbufferData.size());
8863     EXPECT_EQ(userFBOData, backbufferData);
8864 }
8865 
SubrectEquals(const std::vector<GLColor> & bigArray,const std::vector<GLColor> & smallArray,int bigSize,int offset,int smallSize)8866 bool SubrectEquals(const std::vector<GLColor> &bigArray,
8867                    const std::vector<GLColor> &smallArray,
8868                    int bigSize,
8869                    int offset,
8870                    int smallSize)
8871 {
8872     int badPixels = 0;
8873     for (int y = 0; y < smallSize; y++)
8874     {
8875         for (int x = 0; x < smallSize; x++)
8876         {
8877             int bigOffset   = (y + offset) * bigSize + x + offset;
8878             int smallOffset = y * smallSize + x;
8879             if (bigArray[bigOffset] != smallArray[smallOffset])
8880                 badPixels++;
8881         }
8882     }
8883     return badPixels == 0;
8884 }
8885 
8886 // Tests that FragCoord behaves the same betweeen a user FBO and the back buffer.
TEST_P(GLSLTest,FragCoordConsistency)8887 TEST_P(GLSLTest, FragCoordConsistency)
8888 {
8889     constexpr char kFragCoordShader[] = R"(uniform mediump vec2 viewportSize;
8890 void main()
8891 {
8892     gl_FragColor = vec4(gl_FragCoord.xy / viewportSize, 0, 1);
8893 })";
8894 
8895     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragCoordShader);
8896     glUseProgram(program);
8897 
8898     GLint uniLoc = glGetUniformLocation(program, "viewportSize");
8899     ASSERT_NE(-1, uniLoc);
8900     glUniform2f(uniLoc, static_cast<GLfloat>(getWindowWidth()),
8901                 static_cast<GLfloat>(getWindowHeight()));
8902 
8903     // Draw to backbuffer.
8904     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
8905     ASSERT_GL_NO_ERROR();
8906 
8907     std::vector<GLColor> backbufferData(getWindowWidth() * getWindowHeight());
8908     glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
8909                  backbufferData.data());
8910 
8911     GLTexture tex;
8912     glBindTexture(GL_TEXTURE_2D, tex);
8913     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
8914                  GL_UNSIGNED_BYTE, nullptr);
8915 
8916     GLFramebuffer fbo;
8917     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
8918     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
8919     ASSERT_GL_NO_ERROR();
8920     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
8921 
8922     // Draw to user FBO.
8923     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
8924     ASSERT_GL_NO_ERROR();
8925 
8926     std::vector<GLColor> userFBOData(getWindowWidth() * getWindowHeight());
8927     glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
8928                  userFBOData.data());
8929 
8930     ASSERT_GL_NO_ERROR();
8931     ASSERT_EQ(userFBOData.size(), backbufferData.size());
8932     EXPECT_EQ(userFBOData, backbufferData)
8933         << "FragCoord should be the same to default and user FBO";
8934 
8935     // Repeat the same test but with a smaller viewport.
8936     ASSERT_EQ(getWindowHeight(), getWindowWidth());
8937     const int kQuarterSize = getWindowWidth() >> 2;
8938     glViewport(kQuarterSize, kQuarterSize, kQuarterSize * 2, kQuarterSize * 2);
8939 
8940     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
8941     glClear(GL_COLOR_BUFFER_BIT);
8942     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
8943 
8944     std::vector<GLColor> userFBOViewportData(kQuarterSize * kQuarterSize * 4);
8945     glReadPixels(kQuarterSize, kQuarterSize, kQuarterSize * 2, kQuarterSize * 2, GL_RGBA,
8946                  GL_UNSIGNED_BYTE, userFBOViewportData.data());
8947 
8948     glBindFramebuffer(GL_FRAMEBUFFER, 0);
8949     glClear(GL_COLOR_BUFFER_BIT);
8950     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
8951 
8952     std::vector<GLColor> defaultFBOViewportData(kQuarterSize * kQuarterSize * 4);
8953     glReadPixels(kQuarterSize, kQuarterSize, kQuarterSize * 2, kQuarterSize * 2, GL_RGBA,
8954                  GL_UNSIGNED_BYTE, defaultFBOViewportData.data());
8955     ASSERT_GL_NO_ERROR();
8956     EXPECT_EQ(userFBOViewportData, defaultFBOViewportData)
8957         << "FragCoord should be the same to default and user FBO even with a custom viewport";
8958 
8959     // Check that the subrectangles are the same between the viewport and non-viewport modes.
8960     EXPECT_TRUE(SubrectEquals(userFBOData, userFBOViewportData, getWindowWidth(), kQuarterSize,
8961                               kQuarterSize * 2));
8962     EXPECT_TRUE(SubrectEquals(backbufferData, defaultFBOViewportData, getWindowWidth(),
8963                               kQuarterSize, kQuarterSize * 2));
8964 }
8965 
8966 // Ensure that using defined in a macro works in this simple case. This mirrors a dEQP test.
TEST_P(GLSLTest,DefinedInMacroSucceeds)8967 TEST_P(GLSLTest, DefinedInMacroSucceeds)
8968 {
8969     constexpr char kVS[] = R"(precision mediump float;
8970 attribute highp vec4 position;
8971 varying vec2 out0;
8972 
8973 void main()
8974 {
8975 #define AAA defined(BBB)
8976 
8977 #if !AAA
8978     out0 = vec2(0.0, 1.0);
8979 #else
8980     out0 = vec2(1.0, 0.0);
8981 #endif
8982     gl_Position = position;
8983 })";
8984 
8985     constexpr char kFS[] = R"(precision mediump float;
8986 varying vec2 out0;
8987 void main()
8988 {
8989     gl_FragColor = vec4(out0, 0, 1);
8990 })";
8991 
8992     ANGLE_GL_PROGRAM(program, kVS, kFS);
8993     drawQuad(program, "position", 0.5f);
8994     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8995 }
8996 
8997 // Validate the defined operator is evaluated when the macro is called, not when defined.
TEST_P(GLSLTest,DefinedInMacroWithUndef)8998 TEST_P(GLSLTest, DefinedInMacroWithUndef)
8999 {
9000     constexpr char kVS[] = R"(precision mediump float;
9001 attribute highp vec4 position;
9002 varying vec2 out0;
9003 
9004 void main()
9005 {
9006 #define BBB 1
9007 #define AAA defined(BBB)
9008 #undef BBB
9009 
9010 #if AAA
9011     out0 = vec2(1.0, 0.0);
9012 #else
9013     out0 = vec2(0.0, 1.0);
9014 #endif
9015     gl_Position = position;
9016 })";
9017 
9018     constexpr char kFS[] = R"(precision mediump float;
9019 varying vec2 out0;
9020 void main()
9021 {
9022     gl_FragColor = vec4(out0, 0, 1);
9023 })";
9024 
9025     ANGLE_GL_PROGRAM(program, kVS, kFS);
9026     drawQuad(program, "position", 0.5f);
9027     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9028 }
9029 
9030 // Validate the defined operator is evaluated when the macro is called, not when defined.
TEST_P(GLSLTest,DefinedAfterMacroUsage)9031 TEST_P(GLSLTest, DefinedAfterMacroUsage)
9032 {
9033     constexpr char kVS[] = R"(precision mediump float;
9034 attribute highp vec4 position;
9035 varying vec2 out0;
9036 
9037 void main()
9038 {
9039 #define AAA defined(BBB)
9040 #define BBB 1
9041 
9042 #if AAA
9043     out0 = vec2(0.0, 1.0);
9044 #else
9045     out0 = vec2(1.0, 0.0);
9046 #endif
9047     gl_Position = position;
9048 })";
9049 
9050     constexpr char kFS[] = R"(precision mediump float;
9051 varying vec2 out0;
9052 void main()
9053 {
9054     gl_FragColor = vec4(out0, 0, 1);
9055 })";
9056 
9057     ANGLE_GL_PROGRAM(program, kVS, kFS);
9058     drawQuad(program, "position", 0.5f);
9059     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9060 }
9061 
9062 // Test generating "defined" by concatenation when a macro is called. This is not allowed.
TEST_P(GLSLTest,DefinedInMacroConcatenationNotAllowed)9063 TEST_P(GLSLTest, DefinedInMacroConcatenationNotAllowed)
9064 {
9065     constexpr char kVS[] = R"(precision mediump float;
9066 attribute highp vec4 position;
9067 varying vec2 out0;
9068 
9069 void main()
9070 {
9071 #define BBB 1
9072 #define AAA(defi, ned) defi ## ned(BBB)
9073 
9074 #if AAA(defi, ned)
9075     out0 = vec2(0.0, 1.0);
9076 #else
9077     out0 = vec2(1.0, 0.0);
9078 #endif
9079     gl_Position = position;
9080 })";
9081 
9082     constexpr char kFS[] = R"(precision mediump float;
9083 varying vec2 out0;
9084 void main()
9085 {
9086     gl_FragColor = vec4(out0, 0, 1);
9087 })";
9088 
9089     GLuint program = CompileProgram(kVS, kFS);
9090     EXPECT_EQ(0u, program);
9091     glDeleteProgram(program);
9092 }
9093 
9094 // Test using defined in a macro parameter name. This is not allowed.
TEST_P(GLSLTest,DefinedAsParameterNameNotAllowed)9095 TEST_P(GLSLTest, DefinedAsParameterNameNotAllowed)
9096 {
9097     constexpr char kVS[] = R"(precision mediump float;
9098 attribute highp vec4 position;
9099 varying vec2 out0;
9100 
9101 void main()
9102 {
9103 #define BBB 1
9104 #define AAA(defined) defined(BBB)
9105 
9106 #if AAA(defined)
9107     out0 = vec2(0.0, 1.0);
9108 #else
9109     out0 = vec2(1.0, 0.0);
9110 #endif
9111     gl_Position = position;
9112 })";
9113 
9114     constexpr char kFS[] = R"(precision mediump float;
9115 varying vec2 out0;
9116 void main()
9117 {
9118     gl_FragColor = vec4(out0, 0, 1);
9119 })";
9120 
9121     GLuint program = CompileProgram(kVS, kFS);
9122     EXPECT_EQ(0u, program);
9123     glDeleteProgram(program);
9124 }
9125 
9126 // Ensure that defined in a macro is no accepted in WebGL.
TEST_P(WebGLGLSLTest,DefinedInMacroFails)9127 TEST_P(WebGLGLSLTest, DefinedInMacroFails)
9128 {
9129     constexpr char kVS[] = R"(precision mediump float;
9130 attribute highp vec4 position;
9131 varying float out0;
9132 
9133 void main()
9134 {
9135 #define AAA defined(BBB)
9136 
9137 #if !AAA
9138     out0 = 1.0;
9139 #else
9140     out0 = 0.0;
9141 #endif
9142     gl_Position = dEQP_Position;
9143 })";
9144 
9145     constexpr char kFS[] = R"(precision mediump float;
9146 varying float out0;
9147 void main()
9148 {
9149     gl_FragColor = vec4(out0, 0, 0, 1);
9150 })";
9151 
9152     GLuint program = CompileProgram(kVS, kFS);
9153     EXPECT_EQ(0u, program);
9154     glDeleteProgram(program);
9155 }
9156 
9157 // Simple test using a define macro in WebGL.
TEST_P(WebGLGLSLTest,DefinedGLESSymbol)9158 TEST_P(WebGLGLSLTest, DefinedGLESSymbol)
9159 {
9160     constexpr char kVS[] = R"(void main()
9161 {
9162     gl_Position = vec4(1, 0, 0, 1);
9163 })";
9164 
9165     constexpr char kFS[] = R"(#if defined(GL_ES)
9166 precision mediump float;
9167 void main()
9168 {
9169     gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
9170 }
9171 #else
9172 foo
9173 #endif
9174 )";
9175 
9176     ANGLE_GL_PROGRAM(program, kVS, kFS);
9177 }
9178 
9179 // Test that inactive output variables compile ok in combination with SH_INIT_OUTPUT_VARIABLES
9180 // (which is enabled on WebGL).
TEST_P(WebGL2GLSLTest,InactiveOutput)9181 TEST_P(WebGL2GLSLTest, InactiveOutput)
9182 {
9183     constexpr char kFS[] = R"(#version 300 es
9184 precision highp float;
9185 out vec4 _cassgl_2_;
9186 void main()
9187 {
9188 })";
9189 
9190     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
9191     EXPECT_NE(shader, 0u);
9192 }
9193 
9194 // Test that clamp applied on non-literal indices is correct on es 100 shaders.
TEST_P(GLSLTest,ValidIndexClampES100)9195 TEST_P(GLSLTest, ValidIndexClampES100)
9196 {
9197     // http://anglebug.com/6027
9198     ANGLE_SKIP_TEST_IF(IsD3D9());
9199 
9200     constexpr char kFS[] = R"(
9201 precision mediump float;
9202 uniform int u;
9203 uniform mat4 m[2];
9204 void main()
9205 {
9206     gl_FragColor = vec4(m[u][1].xyz, 1);
9207 }
9208 )";
9209 
9210     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
9211     glUseProgram(program);
9212 
9213     GLint uniformLocation = glGetUniformLocation(program, "u");
9214     ASSERT_NE(-1, uniformLocation);
9215 
9216     GLint matrixLocation = glGetUniformLocation(program, "m");
9217     ASSERT_NE(matrixLocation, -1);
9218     const std::array<GLfloat, 32> mValue = {{0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f,
9219                                              0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f,
9220                                              1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
9221                                              0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}};
9222     glUniformMatrix4fv(matrixLocation, 2, false, mValue.data());
9223 
9224     glUniform1i(uniformLocation, 1);
9225     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
9226     EXPECT_GL_NO_ERROR();
9227 
9228     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9229 }
9230 
9231 // Test that clamp applied on non-literal indices is correct on es 300 shaders.
TEST_P(GLSLTest_ES3,ValidIndexClampES300)9232 TEST_P(GLSLTest_ES3, ValidIndexClampES300)
9233 {
9234     constexpr char kFS[] = R"(#version 300 es
9235 precision mediump float;
9236 out vec4 color;
9237 uniform int u;
9238 mat4 m[4] = mat4[4](mat4(0.25), mat4(0.5), mat4(1), mat4(0.75));
9239 void main()
9240 {
9241     color = vec4(m[u][2].xyz, 1);
9242 }
9243 )";
9244 
9245     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9246     glUseProgram(program);
9247 
9248     GLint uniformLocation = glGetUniformLocation(program, "u");
9249     ASSERT_NE(-1, uniformLocation);
9250 
9251     glUniform1i(uniformLocation, 2);
9252     EXPECT_GL_NO_ERROR();
9253     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
9254     EXPECT_GL_NO_ERROR();
9255 
9256     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
9257 }
9258 
9259 // Tests constant folding of non-square 'matrixCompMult'.
TEST_P(GLSLTest_ES3,NonSquareMatrixCompMult)9260 TEST_P(GLSLTest_ES3, NonSquareMatrixCompMult)
9261 {
9262     constexpr char kFS[] = R"(#version 300 es
9263 precision mediump float;
9264 
9265 const mat4x2 matA = mat4x2(2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0);
9266 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);
9267 
9268 out vec4 color;
9269 
9270 void main()
9271 {
9272     mat4x2 result = matrixCompMult(matA, matB);
9273     vec2 vresult = result * vec4(1.0, 1.0, 1.0, 1.0);
9274     if (vresult == vec2(4.0, 4.0))
9275     {
9276         color = vec4(0.0, 1.0, 0.0, 1.0);
9277     }
9278     else
9279     {
9280         color = vec4(1.0, 0.0, 0.0, 1.0);
9281     }
9282 })";
9283 
9284     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9285     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
9286     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9287 }
9288 
9289 // Test initializing an array with the same name of previously declared array
TEST_P(GLSLTest_ES3,InitSameNameArray)9290 TEST_P(GLSLTest_ES3, InitSameNameArray)
9291 {
9292     constexpr char kFS[] = R"(#version 300 es
9293       precision highp float;
9294       out vec4 my_FragColor;
9295 
9296       void main()
9297       {
9298           float arr[2] = float[2](1.0, 1.0);
9299           {
9300               float arr[2] = arr;
9301               my_FragColor = vec4(0.0, arr[0], 0.0, arr[1]);
9302           }
9303       })";
9304 
9305     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9306     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
9307     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9308 }
9309 
9310 // Tests using gl_FragData[0] instead of gl_FragColor.
TEST_P(GLSLTest,FragData)9311 TEST_P(GLSLTest, FragData)
9312 {
9313     // Ensures that we don't regress and emit Vulkan layer warnings.
9314     // TODO(jonahr): http://anglebug.com/3900 - Remove check once warnings are cleaned up
9315     if (IsVulkan())
9316     {
9317         treatPlatformWarningsAsErrors();
9318     }
9319 
9320     constexpr char kFS[] = R"(void main() { gl_FragData[0] = vec4(1, 0, 0, 1); })";
9321     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
9322     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
9323     EXPECT_GL_NO_ERROR();
9324     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
9325 }
9326 
9327 // Test angle can handle big initial stack size with dynamic stack allocation.
TEST_P(GLSLTest,MemoryExhaustedTest)9328 TEST_P(GLSLTest, MemoryExhaustedTest)
9329 {
9330     GLuint program =
9331         CompileProgram(essl1_shaders::vs::Simple(), BuildBigInitialStackShader(36).c_str());
9332     EXPECT_NE(0u, program);
9333 }
9334 
9335 // Test that inactive samplers in structs don't cause any errors.
TEST_P(GLSLTest,InactiveSamplersInStruct)9336 TEST_P(GLSLTest, InactiveSamplersInStruct)
9337 {
9338     constexpr char kVS[] = R"(attribute vec4 a_position;
9339 void main() {
9340   gl_Position = a_position;
9341 })";
9342 
9343     constexpr char kFS[] = R"(precision highp float;
9344 struct S
9345 {
9346     vec4 v;
9347     sampler2D t[10];
9348 };
9349 uniform S s;
9350 void main() {
9351   gl_FragColor = s.v;
9352 })";
9353 
9354     ANGLE_GL_PROGRAM(program, kVS, kFS);
9355 
9356     drawQuad(program, "a_position", 0.5f);
9357 }
9358 
9359 // Helper functions for MixedRowAndColumnMajorMatrices* tests
9360 
9361 // Round up to alignment, assuming it's a power of 2
RoundUpPow2(uint32_t value,uint32_t alignment)9362 uint32_t RoundUpPow2(uint32_t value, uint32_t alignment)
9363 {
9364     return (value + alignment - 1) & ~(alignment - 1);
9365 }
9366 
CreateOutputBuffer(GLBuffer * buffer,uint32_t binding)9367 void CreateOutputBuffer(GLBuffer *buffer, uint32_t binding)
9368 {
9369     unsigned int outputInitData = 0;
9370     glBindBuffer(GL_SHADER_STORAGE_BUFFER, *buffer);
9371     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
9372     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, binding, *buffer);
9373     EXPECT_GL_NO_ERROR();
9374 }
9375 
9376 // Fill provided buffer with matrices based on the given dimensions.  The buffer should be large
9377 // 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)9378 uint32_t FillBuffer(const std::pair<uint32_t, uint32_t> matrixDims[],
9379                     const bool matrixIsColMajor[],
9380                     size_t matrixCount,
9381                     float data[],
9382                     bool isStd430,
9383                     bool isTransposed)
9384 {
9385     size_t offset = 0;
9386     for (size_t m = 0; m < matrixCount; ++m)
9387     {
9388         uint32_t cols   = matrixDims[m].first;
9389         uint32_t rows   = matrixDims[m].second;
9390         bool isColMajor = matrixIsColMajor[m] != isTransposed;
9391 
9392         uint32_t arraySize              = isColMajor ? cols : rows;
9393         uint32_t arrayElementComponents = isColMajor ? rows : cols;
9394         // Note: stride is generally 4 with std140, except for scalar and gvec2 types (which
9395         // MixedRowAndColumnMajorMatrices* tests don't use).  With std430, small matrices can have
9396         // a stride of 2 between rows/columns.
9397         uint32_t stride = isStd430 ? RoundUpPow2(arrayElementComponents, 2) : 4;
9398 
9399         offset = RoundUpPow2(offset, stride);
9400 
9401         for (uint32_t i = 0; i < arraySize; ++i)
9402         {
9403             for (uint32_t c = 0; c < arrayElementComponents; ++c)
9404             {
9405                 uint32_t row = isColMajor ? c : i;
9406                 uint32_t col = isColMajor ? i : c;
9407 
9408                 data[offset + i * stride + c] = col * 4 + row;
9409             }
9410         }
9411 
9412         offset += arraySize * stride;
9413     }
9414     return offset;
9415 }
9416 
9417 // Initialize and bind the buffer.
9418 template <typename T>
InitBuffer(GLuint program,const char * name,GLuint buffer,uint32_t bindingIndex,const T data[],uint32_t dataSize,bool isUniform)9419 void InitBuffer(GLuint program,
9420                 const char *name,
9421                 GLuint buffer,
9422                 uint32_t bindingIndex,
9423                 const T data[],
9424                 uint32_t dataSize,
9425                 bool isUniform)
9426 {
9427     GLenum bindPoint = isUniform ? GL_UNIFORM_BUFFER : GL_SHADER_STORAGE_BUFFER;
9428 
9429     glBindBufferBase(bindPoint, bindingIndex, buffer);
9430     glBufferData(bindPoint, dataSize * sizeof(*data), data, GL_STATIC_DRAW);
9431 
9432     if (isUniform)
9433     {
9434         GLint blockIndex = glGetUniformBlockIndex(program, name);
9435         glUniformBlockBinding(program, blockIndex, bindingIndex);
9436     }
9437 }
9438 
9439 // Verify that buffer data is written by the shader as expected.
9440 template <typename T>
VerifyBuffer(GLuint buffer,const T data[],uint32_t dataSize)9441 bool VerifyBuffer(GLuint buffer, const T data[], uint32_t dataSize)
9442 {
9443     glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
9444 
9445     const T *ptr = reinterpret_cast<const T *>(
9446         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, dataSize, GL_MAP_READ_BIT));
9447 
9448     bool isCorrect = memcmp(ptr, data, dataSize * sizeof(*data)) == 0;
9449     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
9450 
9451     return isCorrect;
9452 }
9453 
9454 // Verify that the success output of the shader is as expected.
VerifySuccess(GLuint buffer)9455 bool VerifySuccess(GLuint buffer)
9456 {
9457     uint32_t success = 1;
9458     return VerifyBuffer(buffer, reinterpret_cast<const float *>(&success), 1);
9459 }
9460 
9461 // Test reading from UBOs and SSBOs and writing to SSBOs with mixed row- and colum-major layouts in
9462 // both std140 and std430 layouts.  Tests many combinations of std140 vs std430, struct being used
9463 // as row- or column-major in different UBOs, reading from UBOs and SSBOs and writing to SSBOs,
9464 // nested structs, matrix arrays, inout parameters etc.
9465 //
9466 // Some very specific corner cases that are not covered here are tested in the subsequent tests.
TEST_P(GLSLTest_ES31,MixedRowAndColumnMajorMatrices)9467 TEST_P(GLSLTest_ES31, MixedRowAndColumnMajorMatrices)
9468 {
9469     GLint maxComputeShaderStorageBlocks;
9470     glGetIntegerv(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, &maxComputeShaderStorageBlocks);
9471 
9472     // The test uses 9 SSBOs.  Skip if not that many are supported.
9473     ANGLE_SKIP_TEST_IF(maxComputeShaderStorageBlocks < 9);
9474 
9475     // Fails on Nvidia because having |Matrices| qualified as row-major in one UBO makes the other
9476     // UBO also see it as row-major despite explicit column-major qualifier.
9477     // http://anglebug.com/3830
9478     ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGL());
9479 
9480     // Fails on mesa because in the first UBO which is qualified as column-major, |Matrices| is
9481     // read column-major despite explicit row-major qualifier.  http://anglebug.com/3837
9482     ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsOpenGL());
9483 
9484     // Fails on windows AMD on GL: http://anglebug.com/3838
9485     ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL() && IsAMD());
9486 
9487     // Fails to compile the shader on Android.  http://anglebug.com/3839
9488     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
9489 
9490     // Fails on assertion in translation to D3D.  http://anglebug.com/3841
9491     ANGLE_SKIP_TEST_IF(IsD3D11());
9492 
9493     // Fails on SSBO validation on Android/Vulkan.  http://anglebug.com/3840
9494     ANGLE_SKIP_TEST_IF(IsAndroid() && IsVulkan());
9495 
9496     // Fails input verification as well as std140 SSBO validation.  http://anglebug.com/3844
9497     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());
9498 
9499     // Fails on ARM on Vulkan.  http://anglebug.com/4492
9500     ANGLE_SKIP_TEST_IF(IsARM() && IsVulkan());
9501 
9502     constexpr char kCS[] = R"(#version 310 es
9503 precision highp float;
9504 layout(local_size_x=1) in;
9505 
9506 struct Inner
9507 {
9508     mat3x4 m3c4r;
9509     mat4x3 m4c3r;
9510 };
9511 
9512 struct Matrices
9513 {
9514     mat2 m2c2r;
9515     mat2x3 m2c3r[2];
9516     mat3x2 m3c2r;
9517     Inner inner;
9518 };
9519 
9520 // For simplicity, the layouts are either of:
9521 // - col-major mat4, row-major rest
9522 // - row-major mat4, col-major rest
9523 //
9524 // The former is tagged with c, the latter with r.
9525 layout(std140, column_major) uniform Ubo140c
9526 {
9527     mat4 m4c4r;
9528     layout(row_major) Matrices m;
9529 } ubo140cIn;
9530 
9531 layout(std140, row_major) uniform Ubo140r
9532 {
9533     mat4 m4c4r;
9534     layout(column_major) Matrices m;
9535 } ubo140rIn;
9536 
9537 layout(std140, row_major, binding = 0) buffer Ssbo140c
9538 {
9539     layout(column_major) mat4 m4c4r;
9540     Matrices m;
9541 } ssbo140cIn;
9542 
9543 layout(std140, column_major, binding = 1) buffer Ssbo140r
9544 {
9545     layout(row_major) mat4 m4c4r;
9546     Matrices m;
9547 } ssbo140rIn;
9548 
9549 layout(std430, column_major, binding = 2) buffer Ssbo430c
9550 {
9551     mat4 m4c4r;
9552     layout(row_major) Matrices m;
9553 } ssbo430cIn;
9554 
9555 layout(std430, row_major, binding = 3) buffer Ssbo430r
9556 {
9557     mat4 m4c4r;
9558     layout(column_major) Matrices m;
9559 } ssbo430rIn;
9560 
9561 layout(std140, row_major, binding = 4) buffer Ssbo140cOut
9562 {
9563     layout(column_major) mat4 m4c4r;
9564     Matrices m;
9565 } ssbo140cOut;
9566 
9567 layout(std140, column_major, binding = 5) buffer Ssbo140rOut
9568 {
9569     layout(row_major) mat4 m4c4r;
9570     Matrices m;
9571 } ssbo140rOut;
9572 
9573 layout(std430, column_major, binding = 6) buffer Ssbo430cOut
9574 {
9575     mat4 m4c4r;
9576     layout(row_major) Matrices m;
9577 } ssbo430cOut;
9578 
9579 layout(std430, row_major, binding = 7) buffer Ssbo430rOut
9580 {
9581     mat4 m4c4r;
9582     layout(column_major) Matrices m;
9583 } ssbo430rOut;
9584 
9585 layout(std140, binding = 8) buffer Result
9586 {
9587     uint success;
9588 } resultOut;
9589 
9590 #define EXPECT(result, expression, value) if ((expression) != value) { result = false; }
9591 #define EXPECTV(result, expression, value) if (any(notEqual(expression, value))) { result = false; }
9592 
9593 #define VERIFY_IN(result, mat, cols, rows)                  \
9594     EXPECT(result, mat[0].x, 0.0);                          \
9595     EXPECT(result, mat[0][1], 1.0);                         \
9596     EXPECTV(result, mat[0].xy, vec2(0, 1));                 \
9597     EXPECTV(result, mat[1].xy, vec2(4, 5));                 \
9598     for (int c = 0; c < cols; ++c)                          \
9599     {                                                       \
9600         for (int r = 0; r < rows; ++r)                      \
9601         {                                                   \
9602             EXPECT(result, mat[c][r], float(c * 4 + r));    \
9603         }                                                   \
9604     }
9605 
9606 #define COPY(matIn, matOut, cols, rows)     \
9607     matOut = matOut + matIn;                \
9608     /* random operations for testing */     \
9609     matOut[0].x += matIn[0].x + matIn[1].x; \
9610     matOut[0].x -= matIn[1].x;              \
9611     matOut[0][1] += matIn[0][1];            \
9612     matOut[1] += matIn[1];                  \
9613     matOut[1].xy -= matIn[1].xy;            \
9614     /* undo the above to get back matIn */  \
9615     matOut[0].x -= matIn[0].x;              \
9616     matOut[0][1] -= matIn[0][1];            \
9617     matOut[1] -= matIn[1];                  \
9618     matOut[1].xy += matIn[1].xy;
9619 
9620 bool verifyMatrices(in Matrices m)
9621 {
9622     bool result = true;
9623     VERIFY_IN(result, m.m2c2r, 2, 2);
9624     VERIFY_IN(result, m.m2c3r[0], 2, 3);
9625     VERIFY_IN(result, m.m2c3r[1], 2, 3);
9626     VERIFY_IN(result, m.m3c2r, 3, 2);
9627     VERIFY_IN(result, m.inner.m3c4r, 3, 4);
9628     VERIFY_IN(result, m.inner.m4c3r, 4, 3);
9629     return result;
9630 }
9631 
9632 mat4 copyMat4(in mat4 m)
9633 {
9634     return m;
9635 }
9636 
9637 void copyMatrices(in Matrices mIn, inout Matrices mOut)
9638 {
9639     COPY(mIn.m2c2r, mOut.m2c2r, 2, 2);
9640     COPY(mIn.m2c3r[0], mOut.m2c3r[0], 2, 3);
9641     COPY(mIn.m2c3r[1], mOut.m2c3r[1], 2, 3);
9642     COPY(mIn.m3c2r, mOut.m3c2r, 3, 2);
9643     COPY(mIn.inner.m3c4r, mOut.inner.m3c4r, 3, 4);
9644     COPY(mIn.inner.m4c3r, mOut.inner.m4c3r, 4, 3);
9645 }
9646 
9647 void main()
9648 {
9649     bool result = true;
9650 
9651     VERIFY_IN(result, ubo140cIn.m4c4r, 4, 4);
9652     VERIFY_IN(result, ubo140cIn.m.m2c3r[0], 2, 3);
9653     EXPECT(result, verifyMatrices(ubo140cIn.m), true);
9654 
9655     VERIFY_IN(result, ubo140rIn.m4c4r, 4, 4);
9656     VERIFY_IN(result, ubo140rIn.m.m2c2r, 2, 2);
9657     EXPECT(result, verifyMatrices(ubo140rIn.m), true);
9658 
9659     VERIFY_IN(result, ssbo140cIn.m4c4r, 4, 4);
9660     VERIFY_IN(result, ssbo140cIn.m.m3c2r, 3, 2);
9661     EXPECT(result, verifyMatrices(ssbo140cIn.m), true);
9662 
9663     VERIFY_IN(result, ssbo140rIn.m4c4r, 4, 4);
9664     VERIFY_IN(result, ssbo140rIn.m.inner.m4c3r, 4, 3);
9665     EXPECT(result, verifyMatrices(ssbo140rIn.m), true);
9666 
9667     VERIFY_IN(result, ssbo430cIn.m4c4r, 4, 4);
9668     VERIFY_IN(result, ssbo430cIn.m.m2c3r[1], 2, 3);
9669     EXPECT(result, verifyMatrices(ssbo430cIn.m), true);
9670 
9671     VERIFY_IN(result, ssbo430rIn.m4c4r, 4, 4);
9672     VERIFY_IN(result, ssbo430rIn.m.inner.m3c4r, 3, 4);
9673     EXPECT(result, verifyMatrices(ssbo430rIn.m), true);
9674 
9675     // Only assign to SSBO from a single invocation.
9676     if (gl_GlobalInvocationID.x == 0u)
9677     {
9678         ssbo140cOut.m4c4r = copyMat4(ssbo140cIn.m4c4r);
9679         copyMatrices(ssbo430cIn.m, ssbo140cOut.m);
9680         ssbo140cOut.m.m2c3r[1] = mat2x3(0);
9681         COPY(ssbo430cIn.m.m2c3r[1], ssbo140cOut.m.m2c3r[1], 2, 3);
9682 
9683         ssbo140rOut.m4c4r = copyMat4(ssbo140rIn.m4c4r);
9684         copyMatrices(ssbo430rIn.m, ssbo140rOut.m);
9685         ssbo140rOut.m.inner.m3c4r = mat3x4(0);
9686         COPY(ssbo430rIn.m.inner.m3c4r, ssbo140rOut.m.inner.m3c4r, 3, 4);
9687 
9688         ssbo430cOut.m4c4r = copyMat4(ssbo430cIn.m4c4r);
9689         copyMatrices(ssbo140cIn.m, ssbo430cOut.m);
9690         ssbo430cOut.m.m3c2r = mat3x2(0);
9691         COPY(ssbo430cIn.m.m3c2r, ssbo430cOut.m.m3c2r, 3, 2);
9692 
9693         ssbo430rOut.m4c4r = copyMat4(ssbo430rIn.m4c4r);
9694         copyMatrices(ssbo140rIn.m, ssbo430rOut.m);
9695         ssbo430rOut.m.inner.m4c3r = mat4x3(0);
9696         COPY(ssbo430rIn.m.inner.m4c3r, ssbo430rOut.m.inner.m4c3r, 4, 3);
9697 
9698         resultOut.success = uint(result);
9699     }
9700 })";
9701 
9702     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
9703     EXPECT_GL_NO_ERROR();
9704 
9705     constexpr size_t kMatrixCount                                     = 7;
9706     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
9707         {4, 4}, {2, 2}, {2, 3}, {2, 3}, {3, 2}, {3, 4}, {4, 3},
9708     };
9709     constexpr bool kMatrixIsColMajor[kMatrixCount] = {
9710         true, false, false, false, false, false, false,
9711     };
9712 
9713     float dataStd140ColMajor[kMatrixCount * 4 * 4] = {};
9714     float dataStd140RowMajor[kMatrixCount * 4 * 4] = {};
9715     float dataStd430ColMajor[kMatrixCount * 4 * 4] = {};
9716     float dataStd430RowMajor[kMatrixCount * 4 * 4] = {};
9717     float dataZeros[kMatrixCount * 4 * 4]          = {};
9718 
9719     const uint32_t sizeStd140ColMajor =
9720         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, dataStd140ColMajor, false, false);
9721     const uint32_t sizeStd140RowMajor =
9722         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, dataStd140RowMajor, false, true);
9723     const uint32_t sizeStd430ColMajor =
9724         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, dataStd430ColMajor, true, false);
9725     const uint32_t sizeStd430RowMajor =
9726         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, dataStd430RowMajor, true, true);
9727 
9728     GLBuffer uboStd140ColMajor, uboStd140RowMajor;
9729     GLBuffer ssboStd140ColMajor, ssboStd140RowMajor;
9730     GLBuffer ssboStd430ColMajor, ssboStd430RowMajor;
9731     GLBuffer ssboStd140ColMajorOut, ssboStd140RowMajorOut;
9732     GLBuffer ssboStd430ColMajorOut, ssboStd430RowMajorOut;
9733 
9734     InitBuffer(program, "Ubo140c", uboStd140ColMajor, 0, dataStd140ColMajor, sizeStd140ColMajor,
9735                true);
9736     InitBuffer(program, "Ubo140r", uboStd140RowMajor, 1, dataStd140RowMajor, sizeStd140RowMajor,
9737                true);
9738     InitBuffer(program, "Ssbo140c", ssboStd140ColMajor, 0, dataStd140ColMajor, sizeStd140ColMajor,
9739                false);
9740     InitBuffer(program, "Ssbo140r", ssboStd140RowMajor, 1, dataStd140RowMajor, sizeStd140RowMajor,
9741                false);
9742     InitBuffer(program, "Ssbo430c", ssboStd430ColMajor, 2, dataStd430ColMajor, sizeStd430ColMajor,
9743                false);
9744     InitBuffer(program, "Ssbo430r", ssboStd430RowMajor, 3, dataStd430RowMajor, sizeStd430RowMajor,
9745                false);
9746     InitBuffer(program, "Ssbo140cOut", ssboStd140ColMajorOut, 4, dataZeros, sizeStd140ColMajor,
9747                false);
9748     InitBuffer(program, "Ssbo140rOut", ssboStd140RowMajorOut, 5, dataZeros, sizeStd140RowMajor,
9749                false);
9750     InitBuffer(program, "Ssbo430cOut", ssboStd430ColMajorOut, 6, dataZeros, sizeStd430ColMajor,
9751                false);
9752     InitBuffer(program, "Ssbo430rOut", ssboStd430RowMajorOut, 7, dataZeros, sizeStd430RowMajor,
9753                false);
9754     EXPECT_GL_NO_ERROR();
9755 
9756     GLBuffer outputBuffer;
9757     CreateOutputBuffer(&outputBuffer, 8);
9758 
9759     glUseProgram(program);
9760     glDispatchCompute(1, 1, 1);
9761     EXPECT_GL_NO_ERROR();
9762     EXPECT_TRUE(VerifySuccess(outputBuffer));
9763 
9764     EXPECT_TRUE(VerifyBuffer(ssboStd140ColMajorOut, dataStd140ColMajor, sizeStd140ColMajor));
9765     EXPECT_TRUE(VerifyBuffer(ssboStd140RowMajorOut, dataStd140RowMajor, sizeStd140RowMajor));
9766     EXPECT_TRUE(VerifyBuffer(ssboStd430ColMajorOut, dataStd430ColMajor, sizeStd430ColMajor));
9767     EXPECT_TRUE(VerifyBuffer(ssboStd430RowMajorOut, dataStd430RowMajor, sizeStd430RowMajor));
9768 }
9769 
9770 // Test that array UBOs are transformed correctly.
TEST_P(GLSLTest_ES3,RowMajorMatrix_ReadMat4Test)9771 TEST_P(GLSLTest_ES3, RowMajorMatrix_ReadMat4Test)
9772 {
9773     constexpr char kFS[] = R"(#version 300 es
9774 precision highp float;
9775 out vec4 outColor;
9776 
9777 layout(std140, row_major) uniform Ubo
9778 {
9779     mat4 m1;
9780 };
9781 
9782 void main()
9783 {
9784     outColor = m1[3] / 255.0;
9785 })";
9786 
9787     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9788     EXPECT_GL_NO_ERROR();
9789 
9790     constexpr size_t kMatrixCount                                     = 1;
9791     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
9792         {4, 4},
9793     };
9794     constexpr bool kMatrixIsColMajor[kMatrixCount] = {
9795         false,
9796     };
9797 
9798     float data[kMatrixCount * 4 * 4] = {};
9799 
9800     const uint32_t size =
9801         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
9802 
9803     GLBuffer ubos;
9804 
9805     InitBuffer(program, "Ubo", ubos, 0, data, size, true);
9806 
9807     EXPECT_GL_NO_ERROR();
9808 
9809     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
9810     EXPECT_PIXEL_NEAR(0, 0, 12, 13, 14, 15, 0);
9811 }
9812 
9813 // Test that array UBOs are transformed correctly.
TEST_P(GLSLTest_ES3,RowMajorMatrix_ReadMat2x3Test)9814 TEST_P(GLSLTest_ES3, RowMajorMatrix_ReadMat2x3Test)
9815 {
9816     constexpr char kFS[] = R"(#version 300 es
9817 precision highp float;
9818 out vec4 outColor;
9819 
9820 layout(std140, row_major) uniform Ubo
9821 {
9822     mat2x3 m1;
9823 };
9824 
9825 void main()
9826 {
9827     outColor = vec4(m1[1], 0) / 255.0;
9828 })";
9829 
9830     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9831     EXPECT_GL_NO_ERROR();
9832 
9833     constexpr size_t kMatrixCount                                     = 1;
9834     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
9835         {2, 3},
9836     };
9837     constexpr bool kMatrixIsColMajor[kMatrixCount] = {
9838         false,
9839     };
9840 
9841     float data[kMatrixCount * 3 * 4] = {};
9842 
9843     const uint32_t size =
9844         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
9845 
9846     GLBuffer ubos;
9847 
9848     InitBuffer(program, "Ubo", ubos, 0, data, size, true);
9849 
9850     EXPECT_GL_NO_ERROR();
9851 
9852     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
9853     EXPECT_PIXEL_NEAR(0, 0, 4, 5, 6, 0, 0);
9854 }
9855 
TEST_P(GLSLTest_ES3,RowMajorMatrix_ReadMat3x2Test)9856 TEST_P(GLSLTest_ES3, RowMajorMatrix_ReadMat3x2Test)
9857 {
9858     constexpr char kFS[] = R"(#version 300 es
9859 precision highp float;
9860 out vec4 outColor;
9861 
9862 layout(std140, row_major) uniform Ubo
9863 {
9864     mat3x2 m1;
9865 };
9866 
9867 void main()
9868 {
9869     outColor = vec4(m1[2], 0, 0) / 255.0;
9870 })";
9871 
9872     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9873     EXPECT_GL_NO_ERROR();
9874 
9875     constexpr size_t kMatrixCount                                     = 1;
9876     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
9877         {3, 2},
9878     };
9879     constexpr bool kMatrixIsColMajor[kMatrixCount] = {
9880         false,
9881     };
9882 
9883     float data[kMatrixCount * 2 * 4] = {};
9884 
9885     const uint32_t size =
9886         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
9887 
9888     GLBuffer ubos;
9889 
9890     InitBuffer(program, "Ubo", ubos, 0, data, size, true);
9891 
9892     EXPECT_GL_NO_ERROR();
9893 
9894     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
9895     EXPECT_PIXEL_NEAR(0, 0, 8, 9, 0, 0, 0);
9896 }
9897 
TEST_P(GLSLTest_ES3,RowMajorMatrix_NestedExpression)9898 TEST_P(GLSLTest_ES3, RowMajorMatrix_NestedExpression)
9899 {
9900     // Many OpenGL drivers seem to fail this
9901     ANGLE_SKIP_TEST_IF((IsLinux() || IsOSX()) && IsOpenGL());
9902 
9903     constexpr char kFS[] = R"(#version 300 es
9904 precision mediump float;
9905 
9906 uniform Ubo {
9907   layout(row_major) mat4 u_mat[3];
9908   layout(row_major) mat4 u_ndx[3];
9909 } stuff;
9910 
9911 precision highp float;
9912 out vec4 outColor;
9913 
9914 void main() {
9915   outColor = stuff.u_mat[int(stuff.u_ndx[1][1][3])][2] / 255.0;
9916 }
9917 )";
9918 
9919     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9920     EXPECT_GL_NO_ERROR();
9921 
9922     typedef float vec4[4];
9923     typedef vec4 mat4[4];
9924 
9925     constexpr size_t kMatrixCount = 6;
9926     mat4 data[]                   = {
9927         {
9928             {0, 1, 2, 3},      //
9929             {4, 5, 6, 7},      //
9930             {8, 9, 10, 11},    //
9931             {12, 13, 14, 15},  //
9932         },
9933         {
9934             //     +-- we should be looking up this column
9935             //     V
9936             {0, 4, 8, 12},   //
9937             {1, 5, 9, 13},   //
9938             {2, 6, 10, 14},  //
9939             {3, 7, 11, 15},  //
9940         },
9941         {
9942             {0, 2, 4, 6},      //
9943             {8, 10, 12, 14},   //
9944             {16, 18, 20, 22},  //
9945             {24, 26, 28, 30},  //
9946         },
9947         {
9948             {0, 0, 0, 0},  //
9949             {0, 0, 0, 0},  //
9950             {0, 0, 0, 0},  //
9951             {0, 0, 0, 0},  //
9952         },
9953         {
9954             {0, 0, 0, 0},  //
9955             {0, 0, 0, 2},  //
9956             {0, 0, 0, 0},  //
9957             {0, 1, 0, 0},
9958             //  ^
9959             //  +-- we should be using this element
9960         },
9961         {
9962             {0, 0, 0, 0},  //
9963             {0, 0, 0, 0},  //
9964             {0, 0, 0, 0},  //
9965             {0, 0, 0, 0},  //
9966         },
9967     };
9968 
9969     GLBuffer ubos;
9970     InitBuffer(program, "Ubo", ubos, 0, data, kMatrixCount, true);
9971     EXPECT_GL_NO_ERROR();
9972 
9973     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
9974     EXPECT_PIXEL_NEAR(0, 0, 8, 9, 10, 11, 0);
9975 }
9976 
9977 // Test that array UBOs are transformed correctly.
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ArrayBufferDeclaration)9978 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ArrayBufferDeclaration)
9979 {
9980     // Fails to compile the shader on Android: http://anglebug.com/3839
9981     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
9982 
9983     // http://anglebug.com/3837
9984     ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsOpenGL());
9985 
9986     // Fails on Mac on Intel and AMD: http://anglebug.com/3842
9987     ANGLE_SKIP_TEST_IF(IsOSX() && IsOpenGL() && (IsIntel() || IsAMD()));
9988 
9989     // Fails on windows AMD on GL: http://anglebug.com/3838
9990     ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL() && IsAMD());
9991 
9992     // Fails on D3D due to mistranslation: http://anglebug.com/3841
9993     ANGLE_SKIP_TEST_IF(IsD3D11());
9994 
9995     constexpr char kFS[] = R"(#version 300 es
9996 precision highp float;
9997 out vec4 outColor;
9998 
9999 layout(std140, column_major) uniform Ubo
10000 {
10001     mat4 m1;
10002     layout(row_major) mat4 m2;
10003 } ubo[3];
10004 
10005 #define EXPECT(result, expression, value) if ((expression) != value) { result = false; }
10006 
10007 #define VERIFY_IN(result, mat, cols, rows)                  \
10008     for (int c = 0; c < cols; ++c)                          \
10009     {                                                       \
10010         for (int r = 0; r < rows; ++r)                      \
10011         {                                                   \
10012             EXPECT(result, mat[c][r], float(c * 4 + r));    \
10013         }                                                   \
10014     }
10015 
10016 void main()
10017 {
10018     bool result = true;
10019 
10020     VERIFY_IN(result, ubo[0].m1, 4, 4);
10021     VERIFY_IN(result, ubo[0].m2, 4, 4);
10022 
10023     VERIFY_IN(result, ubo[1].m1, 4, 4);
10024     VERIFY_IN(result, ubo[1].m2, 4, 4);
10025 
10026     VERIFY_IN(result, ubo[2].m1, 4, 4);
10027     VERIFY_IN(result, ubo[2].m2, 4, 4);
10028 
10029     outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
10030 })";
10031 
10032     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
10033     EXPECT_GL_NO_ERROR();
10034 
10035     constexpr size_t kMatrixCount                                     = 2;
10036     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
10037         {4, 4},
10038         {4, 4},
10039     };
10040     constexpr bool kMatrixIsColMajor[kMatrixCount] = {
10041         true,
10042         false,
10043     };
10044 
10045     float data[kMatrixCount * 4 * 4] = {};
10046 
10047     const uint32_t size =
10048         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
10049 
10050     GLBuffer ubos[3];
10051 
10052     InitBuffer(program, "Ubo[0]", ubos[0], 0, data, size, true);
10053     InitBuffer(program, "Ubo[1]", ubos[1], 0, data, size, true);
10054     InitBuffer(program, "Ubo[2]", ubos[2], 0, data, size, true);
10055 
10056     EXPECT_GL_NO_ERROR();
10057 
10058     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
10059     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10060 }
10061 
10062 // Test that side effects when transforming read operations are preserved.
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ReadSideEffect)10063 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ReadSideEffect)
10064 {
10065     // Fails on Mac on Intel and AMD: http://anglebug.com/3842
10066     ANGLE_SKIP_TEST_IF(IsOSX() && IsOpenGL() && (IsIntel() || IsAMD()));
10067 
10068     // Fails on D3D due to mistranslation: http://anglebug.com/3841
10069     ANGLE_SKIP_TEST_IF(IsD3D11());
10070 
10071     constexpr char kFS[] = R"(#version 300 es
10072 precision highp float;
10073 out vec4 outColor;
10074 
10075 struct S
10076 {
10077     mat2x3 m2[3];
10078 };
10079 
10080 layout(std140, column_major) uniform Ubo
10081 {
10082     mat4 m1;
10083     layout(row_major) S s[2];
10084 } ubo;
10085 
10086 #define EXPECT(result, expression, value) if ((expression) != value) { result = false; }
10087 
10088 #define VERIFY_IN(result, mat, cols, rows)                  \
10089     for (int c = 0; c < cols; ++c)                          \
10090     {                                                       \
10091         for (int r = 0; r < rows; ++r)                      \
10092         {                                                   \
10093             EXPECT(result, mat[c][r], float(c * 4 + r));    \
10094         }                                                   \
10095     }
10096 
10097 bool verify2x3(mat2x3 mat)
10098 {
10099     bool result = true;
10100 
10101     for (int c = 0; c < 2; ++c)
10102     {
10103         for (int r = 0; r < 3; ++r)
10104         {
10105             EXPECT(result, mat[c][r], float(c * 4 + r));
10106         }
10107     }
10108 
10109     return result;
10110 }
10111 
10112 void main()
10113 {
10114     bool result = true;
10115 
10116     int sideEffect = 0;
10117     VERIFY_IN(result, ubo.m1, 4, 4);
10118     EXPECT(result, verify2x3(ubo.s[0].m2[0]), true);
10119     EXPECT(result, verify2x3(ubo.s[0].m2[sideEffect += 1]), true);
10120     EXPECT(result, verify2x3(ubo.s[0].m2[sideEffect += 1]), true);
10121 
10122     EXPECT(result, sideEffect, 2);
10123 
10124     EXPECT(result, verify2x3(ubo.s[sideEffect = 1].m2[0]), true);
10125     EXPECT(result, verify2x3(ubo.s[1].m2[(sideEffect = 4) - 3]), true);
10126     EXPECT(result, verify2x3(ubo.s[1].m2[sideEffect - 2]), true);
10127 
10128     EXPECT(result, sideEffect, 4);
10129 
10130     outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
10131 })";
10132 
10133     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
10134     EXPECT_GL_NO_ERROR();
10135 
10136     constexpr size_t kMatrixCount                                     = 7;
10137     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
10138         {4, 4}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3},
10139     };
10140     constexpr bool kMatrixIsColMajor[kMatrixCount] = {
10141         true, false, false, false, false, false, false,
10142     };
10143 
10144     float data[kMatrixCount * 4 * 4] = {};
10145 
10146     const uint32_t size =
10147         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
10148 
10149     GLBuffer ubo;
10150     InitBuffer(program, "Ubo", ubo, 0, data, size, true);
10151 
10152     EXPECT_GL_NO_ERROR();
10153 
10154     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
10155     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10156 }
10157 
10158 // Test that side effects respect the order of logical expression operands.
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ReadSideEffectOrder)10159 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ReadSideEffectOrder)
10160 {
10161     // http://anglebug.com/3837
10162     ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsOpenGL());
10163 
10164     // IntermTraverser::insertStatementsInParentBlock that's used to move side effects does not
10165     // respect the order of evaluation of logical expressions.  http://anglebug.com/3829.
10166     ANGLE_SKIP_TEST_IF(IsOSX() && IsOpenGL());
10167 
10168     constexpr char kFS[] = R"(#version 300 es
10169 precision highp float;
10170 out vec4 outColor;
10171 
10172 layout(std140, column_major) uniform Ubo
10173 {
10174     mat4 m1;
10175     layout(row_major) mat4 m2[2];
10176 } ubo;
10177 
10178 void main()
10179 {
10180     bool result = true;
10181 
10182     int x = 0;
10183     if (x == 0 && ubo.m2[x = 1][1][1] == 5.0)
10184     {
10185         result = true;
10186     }
10187     else
10188     {
10189         result = false;
10190     }
10191 
10192     outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
10193 })";
10194 
10195     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
10196     EXPECT_GL_NO_ERROR();
10197 
10198     constexpr size_t kMatrixCount                                     = 3;
10199     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
10200         {4, 4},
10201         {4, 4},
10202         {4, 4},
10203     };
10204     constexpr bool kMatrixIsColMajor[kMatrixCount] = {true, false, false};
10205 
10206     float data[kMatrixCount * 4 * 4] = {};
10207 
10208     const uint32_t size =
10209         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
10210 
10211     GLBuffer ubo;
10212     InitBuffer(program, "Ubo", ubo, 0, data, size, true);
10213 
10214     EXPECT_GL_NO_ERROR();
10215 
10216     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
10217     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10218 }
10219 
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ReadSideEffectOrderSurroundedByLoop)10220 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ReadSideEffectOrderSurroundedByLoop)
10221 {
10222     // http://anglebug.com/3837
10223     ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsOpenGL());
10224 
10225     // IntermTraverser::insertStatementsInParentBlock that's used to move side effects does not
10226     // respect the order of evaluation of logical expressions.  http://anglebug.com/3829.
10227     ANGLE_SKIP_TEST_IF(IsOSX() && IsOpenGL());
10228 
10229     constexpr char kFS[] = R"(#version 300 es
10230 precision highp float;
10231 out vec4 outColor;
10232 
10233 layout(std140, column_major) uniform Ubo
10234 {
10235     mat4 m1;
10236     layout(row_major) mat4 m2[2];
10237 } ubo;
10238 
10239 void main()
10240 {
10241     bool result = false;
10242 
10243     for(int x = 0; x < 1; ++x)
10244     {
10245         if (x == 0 && ubo.m2[x = 1][1][1] == 5.0) {
10246           result = true;
10247         }
10248     }
10249     outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
10250 })";
10251 
10252     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
10253     EXPECT_GL_NO_ERROR();
10254 
10255     constexpr size_t kMatrixCount                                     = 3;
10256     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
10257         {4, 4},
10258         {4, 4},
10259         {4, 4},
10260     };
10261     constexpr bool kMatrixIsColMajor[kMatrixCount] = {true, false, false};
10262 
10263     float data[kMatrixCount * 4 * 4] = {};
10264 
10265     const uint32_t size =
10266         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
10267 
10268     GLBuffer ubo;
10269     InitBuffer(program, "Ubo", ubo, 0, data, size, true);
10270 
10271     EXPECT_GL_NO_ERROR();
10272 
10273     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
10274     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10275 }
10276 
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ReadSideEffectOrderInALoop)10277 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ReadSideEffectOrderInALoop)
10278 {
10279     // http://anglebug.com/3837
10280     ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsOpenGL());
10281 
10282     // IntermTraverser::insertStatementsInParentBlock that's used to move side effects does not
10283     // respect the order of evaluation of logical expressions.  http://anglebug.com/3829.
10284     ANGLE_SKIP_TEST_IF(IsOSX() && IsOpenGL());
10285 
10286     constexpr char kFS[] = R"(#version 300 es
10287 precision highp float;
10288 out vec4 outColor;
10289 
10290 layout(std140, column_major) uniform Ubo
10291 {
10292     mat4 m1;
10293     layout(row_major) mat4 m2[2];
10294 } ubo;
10295 
10296 void main()
10297 {
10298     bool result = false;
10299 
10300     for(int x = 0; x == 0 && ubo.m2[x = 1][1][1] == 5.0;)
10301     {
10302         result = true;
10303     }
10304     outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
10305 })";
10306 
10307     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
10308     EXPECT_GL_NO_ERROR();
10309 
10310     constexpr size_t kMatrixCount                                     = 3;
10311     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
10312         {4, 4},
10313         {4, 4},
10314         {4, 4},
10315     };
10316     constexpr bool kMatrixIsColMajor[kMatrixCount] = {true, false, false};
10317 
10318     float data[kMatrixCount * 4 * 4] = {};
10319 
10320     const uint32_t size =
10321         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
10322 
10323     GLBuffer ubo;
10324     InitBuffer(program, "Ubo", ubo, 0, data, size, true);
10325 
10326     EXPECT_GL_NO_ERROR();
10327 
10328     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
10329     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10330 }
10331 
10332 // Test that side effects respect short-circuit.
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ReadSideEffectShortCircuit)10333 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ReadSideEffectShortCircuit)
10334 {
10335     // Fails on Android: http://anglebug.com/3839
10336     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
10337 
10338     // IntermTraverser::insertStatementsInParentBlock that's used to move side effects does not
10339     // respect the order of evaluation of logical expressions.  http://anglebug.com/3829.
10340     ANGLE_SKIP_TEST_IF(IsOSX() && IsOpenGL());
10341 
10342     constexpr char kFS[] = R"(#version 300 es
10343 precision highp float;
10344 out vec4 outColor;
10345 
10346 layout(std140, column_major) uniform Ubo
10347 {
10348     mat4 m1;
10349     layout(row_major) mat4 m2[2];
10350 } ubo;
10351 
10352 void main()
10353 {
10354     bool result = true;
10355 
10356     int x = 0;
10357     if (x == 1 && ubo.m2[x = 1][1][1] == 5.0)
10358     {
10359         // First x == 1 should prevent the side effect of the second expression (x = 1) from
10360         // being executed.  If x = 1 is run before the if, the condition of the if would be true,
10361         // which is a failure.
10362         result = false;
10363     }
10364     if (x == 1)
10365     {
10366         result = false;
10367     }
10368 
10369     outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
10370 })";
10371 
10372     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
10373     EXPECT_GL_NO_ERROR();
10374 
10375     constexpr size_t kMatrixCount                                     = 3;
10376     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
10377         {4, 4},
10378         {4, 4},
10379         {4, 4},
10380     };
10381     constexpr bool kMatrixIsColMajor[kMatrixCount] = {true, false, false};
10382 
10383     float data[kMatrixCount * 4 * 4] = {};
10384 
10385     const uint32_t size =
10386         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
10387 
10388     GLBuffer ubo;
10389     InitBuffer(program, "Ubo", ubo, 0, data, size, true);
10390 
10391     EXPECT_GL_NO_ERROR();
10392 
10393     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
10394     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10395 }
10396 
10397 // Test that dynamic indexing of swizzled l-values should work.
10398 // A simple porting of sdk/tests/conformance2/glsl3/vector-dynamic-indexing-swizzled-lvalue.html
TEST_P(GLSLTest_ES3,DynamicIndexingOfSwizzledLValuesShouldWork)10399 TEST_P(GLSLTest_ES3, DynamicIndexingOfSwizzledLValuesShouldWork)
10400 {
10401     // The shader first assigns v.x to v.z (1.0)
10402     // Then v.y to v.y (2.0)
10403     // Then v.z to v.x (1.0)
10404     constexpr char kFS[] = R"(#version 300 es
10405 precision highp float;
10406 out vec4 my_FragColor;
10407 void main() {
10408     vec3 v = vec3(1.0, 2.0, 3.0);
10409     for (int i = 0; i < 3; i++) {
10410         v.zyx[i] = v[i];
10411     }
10412     my_FragColor = distance(v, vec3(1.0, 2.0, 1.0)) < 0.01 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
10413 })";
10414 
10415     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
10416     EXPECT_GL_NO_ERROR();
10417     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
10418     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10419 }
10420 
10421 // Test that dead code after discard, return, continue and branch are pruned.
TEST_P(GLSLTest_ES3,DeadCodeIsPruned)10422 TEST_P(GLSLTest_ES3, DeadCodeIsPruned)
10423 {
10424     constexpr char kFS[] = R"(#version 300 es
10425 precision mediump float;
10426 out vec4 color;
10427 
10428 vec4 f(vec4 c)
10429 {
10430     return c;
10431     // dead code
10432     c = vec4(0, 0, 1, 1);
10433     return c;
10434 }
10435 
10436 void main()
10437 {
10438     vec4 result = vec4(0, 0.5, 0, 1);
10439     int var = int(result.y * 2.2);
10440 
10441     {
10442         if (result.x > 1.0)
10443         {
10444             discard;
10445             // dead code
10446             result = vec4(1, 0, 0, 1);
10447         }
10448         for (int i = 0; i < 3; ++i)
10449         {
10450             if (i < 2)
10451             {
10452                 result = f(result);
10453                 continue;
10454                 // dead code
10455                 result = vec4(1, 0, 1, 1);
10456             }
10457             result = f(result);
10458             break;
10459             // dead code
10460             result = vec4(1, 0, 1, 0);
10461         }
10462         while (true)
10463         {
10464             if (result.x > -1.0)
10465             {
10466                 {
10467                     result = f(result);
10468                     {
10469                         break;
10470                         // dead code
10471                         result = vec4(1, 0, 0, 0);
10472                     }
10473                     // dead code
10474                     for (int j = 0; j < 3; ++j)
10475                     {
10476                         if (j > 1) continue;
10477                         result = vec4(0, 0, 1, 0);
10478                         color = vec4(0.5, 0, 0.5, 0.5);
10479                         return;
10480                     }
10481                 }
10482                 // dead code
10483                 result = vec4(0.5, 0, 0, 0);
10484             }
10485         }
10486         switch (var)
10487         {
10488         case 2:
10489             return;
10490             // dead code
10491             color = vec4(0.25, 0, 0.25, 0.25);
10492         case 1:
10493             {
10494                 // Make sure this path is not pruned due to the return in the previous case.
10495                 result.y += 0.5;
10496                 break;
10497                 // dead code
10498                 color = vec4(0.25, 0, 0, 0);
10499             }
10500             // dead code
10501             color = vec4(0, 0, 0.25, 0);
10502             break;
10503         default:
10504             break;
10505         }
10506 
10507         color = result;
10508         return;
10509         // dead code
10510         color = vec4(0, 0, 0.5, 0);
10511     }
10512     // dead code
10513     color = vec4(0, 0, 0, 0.5);
10514 })";
10515 
10516     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
10517 
10518     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
10519     EXPECT_GL_NO_ERROR();
10520 
10521     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10522 }
10523 
10524 // Regression test based on fuzzer issue.  If a case has statements that are pruned, and those
10525 // pruned statements in turn have branches, and another case follows, a prior implementation of
10526 // dead-code elimination doubly pruned some statements.
TEST_P(GLSLTest_ES3,DeadCodeBranchInPrunedStatementsInCaseBeforeAnotherCase)10527 TEST_P(GLSLTest_ES3, DeadCodeBranchInPrunedStatementsInCaseBeforeAnotherCase)
10528 {
10529     constexpr char kFS[] = R"(#version 300 es
10530 precision mediump float;
10531 out vec4 color;
10532 void main()
10533 {
10534     color = vec4(0, 1, 0, 1);
10535     switch(0)
10536     {
10537     case 0:
10538         break;
10539         break;
10540         color = vec4(1, 0, 0, 1);   // The bug was pruning this statement twice
10541     default:
10542         color = vec4(0, 0, 1, 1);
10543         break;
10544     }
10545 })";
10546 
10547     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
10548 
10549     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
10550     EXPECT_GL_NO_ERROR();
10551 
10552     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10553 }
10554 
10555 // Test shader with all resources (default uniform, UBO, SSBO, image, sampler and atomic counter) to
10556 // make sure they are all linked ok.  The front-end sorts these resources and traverses the list of
10557 // "uniforms" to find the range for each resource.  A bug there was causing some resource ranges to
10558 // be empty in the presence of other resources.
TEST_P(GLSLTest_ES31,MixOfAllResources)10559 TEST_P(GLSLTest_ES31, MixOfAllResources)
10560 {
10561     // http://anglebug.com/5072
10562     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
10563 
10564     constexpr char kComputeShader[] = R"(#version 310 es
10565 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
10566 layout(binding = 1, std430) buffer Output {
10567   uint ubo_value;
10568   uint default_value;
10569   uint sampler_value;
10570   uint ac_value;
10571   uint image_value;
10572 } outbuf;
10573 uniform Input {
10574   uint input_value;
10575 } inbuf;
10576 uniform uint default_uniform;
10577 uniform sampler2D smplr;
10578 layout(binding=0) uniform atomic_uint ac;
10579 layout(r32ui) uniform highp readonly uimage2D image;
10580 
10581 void main(void)
10582 {
10583   outbuf.ubo_value = inbuf.input_value;
10584   outbuf.default_value = default_uniform;
10585   outbuf.sampler_value = uint(texture(smplr, vec2(0.5, 0.5)).x * 255.0);
10586   outbuf.ac_value = atomicCounterIncrement(ac);
10587   outbuf.image_value = imageLoad(image, ivec2(0, 0)).x;
10588 }
10589 )";
10590     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
10591     EXPECT_GL_NO_ERROR();
10592 
10593     glUseProgram(program);
10594 
10595     unsigned int inputData = 89u;
10596     GLBuffer inputBuffer;
10597     glBindBuffer(GL_UNIFORM_BUFFER, inputBuffer);
10598     glBufferData(GL_UNIFORM_BUFFER, sizeof(inputData), &inputData, GL_STATIC_DRAW);
10599     GLuint inputBufferIndex = glGetUniformBlockIndex(program.get(), "Input");
10600     ASSERT_NE(inputBufferIndex, GL_INVALID_INDEX);
10601     glUniformBlockBinding(program.get(), inputBufferIndex, 0);
10602     glBindBufferBase(GL_UNIFORM_BUFFER, 0, inputBuffer);
10603 
10604     unsigned int outputInitData[5] = {0x12345678u, 0x09ABCDEFu, 0x56789ABCu, 0x0DEF1234u,
10605                                       0x13579BDFu};
10606     GLBuffer outputBuffer;
10607     glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
10608     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), outputInitData, GL_STATIC_DRAW);
10609     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
10610     EXPECT_GL_NO_ERROR();
10611 
10612     unsigned int uniformData = 456u;
10613     GLint uniformLocation    = glGetUniformLocation(program, "default_uniform");
10614     ASSERT_NE(uniformLocation, -1);
10615     glUniform1ui(uniformLocation, uniformData);
10616 
10617     unsigned int acData = 2u;
10618     GLBuffer atomicCounterBuffer;
10619     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
10620     glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(acData), &acData, GL_STATIC_DRAW);
10621     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
10622     EXPECT_GL_NO_ERROR();
10623 
10624     unsigned int imageData = 33u;
10625     GLTexture image;
10626     glBindTexture(GL_TEXTURE_2D, image);
10627     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
10628     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &imageData);
10629     glBindImageTexture(0, image, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
10630     EXPECT_GL_NO_ERROR();
10631 
10632     GLColor textureData(127, 18, 189, 211);
10633     GLTexture texture;
10634     glBindTexture(GL_TEXTURE_2D, texture);
10635     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &textureData);
10636     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
10637     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10638     ASSERT_GL_NO_ERROR();
10639 
10640     glDispatchCompute(1, 1, 1);
10641     EXPECT_GL_NO_ERROR();
10642 
10643     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
10644 
10645     // read back
10646     const GLuint *ptr = reinterpret_cast<const GLuint *>(
10647         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
10648     EXPECT_EQ(ptr[0], inputData);
10649     EXPECT_EQ(ptr[1], uniformData);
10650     EXPECT_NEAR(ptr[2], textureData.R, 1.0);
10651     EXPECT_EQ(ptr[3], acData);
10652     EXPECT_EQ(ptr[4], imageData);
10653 
10654     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
10655 }
10656 
10657 // Test that sending mixture of resources to functions works.
TEST_P(GLSLTest_ES31,MixOfResourcesAsFunctionArgs)10658 TEST_P(GLSLTest_ES31, MixOfResourcesAsFunctionArgs)
10659 {
10660     // http://anglebug.com/5546
10661     ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
10662 
10663     // anglebug.com/3832 - no sampler array params on Android
10664     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
10665 
10666     constexpr char kComputeShader[] = R"(#version 310 es
10667 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
10668 
10669 layout(binding = 1, std430) buffer Output {
10670   uint success;
10671 } outbuf;
10672 
10673 uniform uint initialAcValue;
10674 uniform sampler2D smplr[2][3];
10675 layout(binding=0) uniform atomic_uint ac;
10676 
10677 bool sampler1DAndAtomicCounter(uvec3 sExpect, in sampler2D s[3], in atomic_uint a, uint aExpect)
10678 {
10679     uvec3 sResult = uvec3(uint(texture(s[0], vec2(0.5, 0.5)).x * 255.0),
10680                           uint(texture(s[1], vec2(0.5, 0.5)).x * 255.0),
10681                           uint(texture(s[2], vec2(0.5, 0.5)).x * 255.0));
10682     uint aResult = atomicCounterIncrement(a);
10683 
10684     return sExpect == sResult && aExpect == aResult;
10685 }
10686 
10687 bool sampler2DAndAtomicCounter(in sampler2D s[2][3], uint aInitial, in atomic_uint a)
10688 {
10689     bool success = true;
10690     success = sampler1DAndAtomicCounter(uvec3(0, 127, 255), s[0], a, aInitial) && success;
10691     success = sampler1DAndAtomicCounter(uvec3(31, 63, 191), s[1], a, aInitial + 1u) && success;
10692     return success;
10693 }
10694 
10695 void main(void)
10696 {
10697     outbuf.success = uint(sampler2DAndAtomicCounter(smplr, initialAcValue, ac));
10698 }
10699 )";
10700     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
10701     EXPECT_GL_NO_ERROR();
10702 
10703     glUseProgram(program);
10704 
10705     unsigned int outputInitData = 0x12345678u;
10706     GLBuffer outputBuffer;
10707     glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
10708     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
10709     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
10710     EXPECT_GL_NO_ERROR();
10711 
10712     unsigned int acData   = 2u;
10713     GLint uniformLocation = glGetUniformLocation(program, "initialAcValue");
10714     ASSERT_NE(uniformLocation, -1);
10715     glUniform1ui(uniformLocation, acData);
10716 
10717     GLBuffer atomicCounterBuffer;
10718     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
10719     glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(acData), &acData, GL_STATIC_DRAW);
10720     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
10721     EXPECT_GL_NO_ERROR();
10722 
10723     const std::array<GLColor, 6> kTextureData = {
10724         GLColor(0, 0, 0, 0),  GLColor(127, 0, 0, 0), GLColor(255, 0, 0, 0),
10725         GLColor(31, 0, 0, 0), GLColor(63, 0, 0, 0),  GLColor(191, 0, 0, 0),
10726     };
10727     GLTexture textures[2][3];
10728 
10729     for (int dim1 = 0; dim1 < 2; ++dim1)
10730     {
10731         for (int dim2 = 0; dim2 < 3; ++dim2)
10732         {
10733             int textureUnit = dim1 * 3 + dim2;
10734             glActiveTexture(GL_TEXTURE0 + textureUnit);
10735             glBindTexture(GL_TEXTURE_2D, textures[dim1][dim2]);
10736             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
10737                          &kTextureData[textureUnit]);
10738             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
10739             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10740 
10741             std::stringstream uniformName;
10742             uniformName << "smplr[" << dim1 << "][" << dim2 << "]";
10743             GLint samplerLocation = glGetUniformLocation(program, uniformName.str().c_str());
10744             EXPECT_NE(samplerLocation, -1);
10745             glUniform1i(samplerLocation, textureUnit);
10746         }
10747     }
10748     ASSERT_GL_NO_ERROR();
10749 
10750     glDispatchCompute(1, 1, 1);
10751     EXPECT_GL_NO_ERROR();
10752 
10753     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
10754 
10755     // read back
10756     const GLuint *ptr = reinterpret_cast<const GLuint *>(
10757         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
10758     EXPECT_EQ(ptr[0], 1u);
10759 
10760     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
10761 }
10762 
10763 // Test that array of array of samplers used as function parameter with an index that has a
10764 // side-effect works.
TEST_P(GLSLTest_ES31,ArrayOfArrayOfSamplerAsFunctionParameterIndexedWithSideEffect)10765 TEST_P(GLSLTest_ES31, ArrayOfArrayOfSamplerAsFunctionParameterIndexedWithSideEffect)
10766 {
10767     // http://anglebug.com/5546
10768     ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
10769 
10770     // anglebug.com/3832 - no sampler array params on Android
10771     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
10772 
10773     // Skip if EXT_gpu_shader5 is not enabled.
10774     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
10775 
10776     constexpr char kComputeShader[] = R"(#version 310 es
10777 #extension GL_EXT_gpu_shader5 : require
10778 
10779 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
10780 
10781 layout(binding = 1, std430) buffer Output {
10782   uint success;
10783 } outbuf;
10784 
10785 uniform sampler2D smplr[2][3];
10786 layout(binding=0) uniform atomic_uint ac;
10787 
10788 bool sampler1DAndAtomicCounter(uvec3 sExpect, in sampler2D s[3], in atomic_uint a, uint aExpect)
10789 {
10790     uvec3 sResult = uvec3(uint(texture(s[0], vec2(0.5, 0.5)).x * 255.0),
10791                           uint(texture(s[1], vec2(0.5, 0.5)).x * 255.0),
10792                           uint(texture(s[2], vec2(0.5, 0.5)).x * 255.0));
10793     uint aResult = atomicCounter(a);
10794 
10795     return sExpect == sResult && aExpect == aResult;
10796 }
10797 
10798 bool sampler2DAndAtomicCounter(in sampler2D s[2][3], uint aInitial, in atomic_uint a)
10799 {
10800     bool success = true;
10801     success = sampler1DAndAtomicCounter(uvec3(0, 127, 255),
10802                     s[atomicCounterIncrement(ac)], a, aInitial + 1u) && success;
10803     success = sampler1DAndAtomicCounter(uvec3(31, 63, 191),
10804                     s[atomicCounterIncrement(ac)], a, aInitial + 2u) && success;
10805     return success;
10806 }
10807 
10808 void main(void)
10809 {
10810     outbuf.success = uint(sampler2DAndAtomicCounter(smplr, 0u, ac));
10811 }
10812 )";
10813     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
10814     EXPECT_GL_NO_ERROR();
10815 
10816     glUseProgram(program);
10817 
10818     unsigned int outputInitData = 0x12345678u;
10819     GLBuffer outputBuffer;
10820     glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
10821     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
10822     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
10823     EXPECT_GL_NO_ERROR();
10824 
10825     unsigned int acData = 0u;
10826     GLBuffer atomicCounterBuffer;
10827     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
10828     glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(acData), &acData, GL_STATIC_DRAW);
10829     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
10830     EXPECT_GL_NO_ERROR();
10831 
10832     const std::array<GLColor, 6> kTextureData = {
10833         GLColor(0, 0, 0, 0),  GLColor(127, 0, 0, 0), GLColor(255, 0, 0, 0),
10834         GLColor(31, 0, 0, 0), GLColor(63, 0, 0, 0),  GLColor(191, 0, 0, 0),
10835     };
10836     GLTexture textures[2][3];
10837 
10838     for (int dim1 = 0; dim1 < 2; ++dim1)
10839     {
10840         for (int dim2 = 0; dim2 < 3; ++dim2)
10841         {
10842             int textureUnit = dim1 * 3 + dim2;
10843             glActiveTexture(GL_TEXTURE0 + textureUnit);
10844             glBindTexture(GL_TEXTURE_2D, textures[dim1][dim2]);
10845             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
10846                          &kTextureData[textureUnit]);
10847             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
10848             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10849 
10850             std::stringstream uniformName;
10851             uniformName << "smplr[" << dim1 << "][" << dim2 << "]";
10852             GLint samplerLocation = glGetUniformLocation(program, uniformName.str().c_str());
10853             EXPECT_NE(samplerLocation, -1);
10854             glUniform1i(samplerLocation, textureUnit);
10855         }
10856     }
10857     ASSERT_GL_NO_ERROR();
10858 
10859     glDispatchCompute(1, 1, 1);
10860     EXPECT_GL_NO_ERROR();
10861 
10862     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
10863 
10864     // read back
10865     const GLuint *ptr = reinterpret_cast<const GLuint *>(
10866         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
10867     EXPECT_EQ(ptr[0], 1u);
10868 
10869     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
10870 }
10871 
10872 // Test that array of array of samplers can be indexed correctly with dynamic indices.
TEST_P(GLSLTest_ES31,ArrayOfArrayOfSamplerDynamicIndex)10873 TEST_P(GLSLTest_ES31, ArrayOfArrayOfSamplerDynamicIndex)
10874 {
10875     // Skip if EXT_gpu_shader5 is not enabled.
10876     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
10877 
10878     int maxTextureImageUnits = 0;
10879     glGetIntegerv(GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
10880     ANGLE_SKIP_TEST_IF(maxTextureImageUnits < 24);
10881 
10882     // anglebug.com/3832 - no sampler array params on Android
10883     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
10884 
10885     // http://anglebug.com/5546
10886     ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
10887 
10888     constexpr char kComputeShader[] = R"(#version 310 es
10889 #extension GL_EXT_gpu_shader5 : require
10890 
10891 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
10892 
10893 layout(binding = 1, std430) buffer Output {
10894   uint success;
10895 } outbuf;
10896 
10897 uniform sampler2D smplr[2][3][4];
10898 layout(binding=0) uniform atomic_uint ac;
10899 
10900 bool sampler1DAndAtomicCounter(uvec4 sExpect, in sampler2D s[4], in atomic_uint a, uint aExpect)
10901 {
10902     uvec4 sResult = uvec4(uint(texture(s[0], vec2(0.5, 0.5)).x * 255.0),
10903                           uint(texture(s[1], vec2(0.5, 0.5)).x * 255.0),
10904                           uint(texture(s[2], vec2(0.5, 0.5)).x * 255.0),
10905                           uint(texture(s[3], vec2(0.5, 0.5)).x * 255.0));
10906     uint aResult = atomicCounter(a);
10907 
10908     return sExpect == sResult && aExpect == aResult;
10909 }
10910 
10911 bool sampler3DAndAtomicCounter(in sampler2D s[2][3][4], uint aInitial, in atomic_uint a)
10912 {
10913     bool success = true;
10914     // [0][0]
10915     success = sampler1DAndAtomicCounter(uvec4(0, 8, 16, 24),
10916                     s[atomicCounterIncrement(ac)][0], a, aInitial + 1u) && success;
10917     // [1][0]
10918     success = sampler1DAndAtomicCounter(uvec4(96, 104, 112, 120),
10919                     s[atomicCounterIncrement(ac)][0], a, aInitial + 2u) && success;
10920     // [0][1]
10921     success = sampler1DAndAtomicCounter(uvec4(32, 40, 48, 56),
10922                     s[0][atomicCounterIncrement(ac) - 1u], a, aInitial + 3u) && success;
10923     // [0][2]
10924     success = sampler1DAndAtomicCounter(uvec4(64, 72, 80, 88),
10925                     s[0][atomicCounterIncrement(ac) - 1u], a, aInitial + 4u) && success;
10926     // [1][1]
10927     success = sampler1DAndAtomicCounter(uvec4(128, 136, 144, 152),
10928                     s[1][atomicCounterIncrement(ac) - 3u], a, aInitial + 5u) && success;
10929     // [1][2]
10930     uint acValue = atomicCounterIncrement(ac);  // Returns 5
10931     success = sampler1DAndAtomicCounter(uvec4(160, 168, 176, 184),
10932                     s[acValue - 4u][atomicCounterIncrement(ac) - 4u], a, aInitial + 7u) && success;
10933 
10934     return success;
10935 }
10936 
10937 void main(void)
10938 {
10939     outbuf.success = uint(sampler3DAndAtomicCounter(smplr, 0u, ac));
10940 }
10941 )";
10942     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
10943     EXPECT_GL_NO_ERROR();
10944 
10945     glUseProgram(program);
10946 
10947     unsigned int outputInitData = 0x12345678u;
10948     GLBuffer outputBuffer;
10949     glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
10950     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
10951     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
10952     EXPECT_GL_NO_ERROR();
10953 
10954     unsigned int acData = 0u;
10955     GLBuffer atomicCounterBuffer;
10956     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
10957     glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(acData), &acData, GL_STATIC_DRAW);
10958     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
10959     EXPECT_GL_NO_ERROR();
10960 
10961     const std::array<GLColor, 24> kTextureData = {
10962         GLColor(0, 0, 0, 0),   GLColor(8, 0, 0, 0),   GLColor(16, 0, 0, 0),  GLColor(24, 0, 0, 0),
10963         GLColor(32, 0, 0, 0),  GLColor(40, 0, 0, 0),  GLColor(48, 0, 0, 0),  GLColor(56, 0, 0, 0),
10964         GLColor(64, 0, 0, 0),  GLColor(72, 0, 0, 0),  GLColor(80, 0, 0, 0),  GLColor(88, 0, 0, 0),
10965         GLColor(96, 0, 0, 0),  GLColor(104, 0, 0, 0), GLColor(112, 0, 0, 0), GLColor(120, 0, 0, 0),
10966         GLColor(128, 0, 0, 0), GLColor(136, 0, 0, 0), GLColor(144, 0, 0, 0), GLColor(152, 0, 0, 0),
10967         GLColor(160, 0, 0, 0), GLColor(168, 0, 0, 0), GLColor(176, 0, 0, 0), GLColor(184, 0, 0, 0),
10968     };
10969     GLTexture textures[2][3][4];
10970 
10971     for (int dim1 = 0; dim1 < 2; ++dim1)
10972     {
10973         for (int dim2 = 0; dim2 < 3; ++dim2)
10974         {
10975             for (int dim3 = 0; dim3 < 4; ++dim3)
10976             {
10977                 int textureUnit = (dim1 * 3 + dim2) * 4 + dim3;
10978                 glActiveTexture(GL_TEXTURE0 + textureUnit);
10979                 glBindTexture(GL_TEXTURE_2D, textures[dim1][dim2][dim3]);
10980                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
10981                              &kTextureData[textureUnit]);
10982                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
10983                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10984 
10985                 std::stringstream uniformName;
10986                 uniformName << "smplr[" << dim1 << "][" << dim2 << "][" << dim3 << "]";
10987                 GLint samplerLocation = glGetUniformLocation(program, uniformName.str().c_str());
10988                 EXPECT_NE(samplerLocation, -1);
10989                 glUniform1i(samplerLocation, textureUnit);
10990             }
10991         }
10992     }
10993     ASSERT_GL_NO_ERROR();
10994 
10995     glDispatchCompute(1, 1, 1);
10996     EXPECT_GL_NO_ERROR();
10997 
10998     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
10999 
11000     // read back
11001     const GLuint *ptr = reinterpret_cast<const GLuint *>(
11002         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
11003     EXPECT_EQ(ptr[0], 1u);
11004 
11005     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
11006 }
11007 
11008 // Test that array of array of samplers can be indexed correctly with dynamic indices.  Uses
11009 // samplers in structs.
TEST_P(GLSLTest_ES31,ArrayOfArrayOfSamplerInStructDynamicIndex)11010 TEST_P(GLSLTest_ES31, ArrayOfArrayOfSamplerInStructDynamicIndex)
11011 {
11012     // Skip if EXT_gpu_shader5 is not enabled.
11013     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
11014 
11015     int maxTextureImageUnits = 0;
11016     glGetIntegerv(GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
11017     ANGLE_SKIP_TEST_IF(maxTextureImageUnits < 24);
11018 
11019     // http://anglebug.com/5072
11020     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
11021 
11022     // anglebug.com/3832 - no sampler array params on Android
11023     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
11024 
11025     // http://anglebug.com/5546
11026     ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
11027 
11028     constexpr char kComputeShader[] = R"(#version 310 es
11029 #extension GL_EXT_gpu_shader5 : require
11030 
11031 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
11032 
11033 layout(binding = 1, std430) buffer Output {
11034   uint success;
11035 } outbuf;
11036 
11037 struct I
11038 {
11039     uint index;
11040 };
11041 
11042 struct S
11043 {
11044     sampler2D smplr[4];
11045     I nested;
11046 };
11047 
11048 struct T
11049 {
11050     S nested[3];
11051     uint tIndex;
11052 };
11053 
11054 uniform T u[2];
11055 
11056 uint getValue(in sampler2D s)
11057 {
11058     return uint(texture(s, vec2(0.5, 0.5)).x * 255.0);
11059 }
11060 
11061 bool sampler1DTest(uvec4 sExpect, in sampler2D s[4])
11062 {
11063     uvec4 sResult = uvec4(getValue(s[0]), getValue(s[1]),
11064                           getValue(s[2]), getValue(s[3]));
11065 
11066     return sExpect == sResult;
11067 }
11068 
11069 bool samplerTest(T t, uint N)
11070 {
11071     // u[N].tIndex == 0 + N*4
11072     // u[N].nested[0].nested.index == 1 + N*4
11073     // u[N].nested[1].nested.index == 2 + N*4
11074     // u[N].nested[2].nested.index == 3 + N*4
11075 
11076     uvec4 colorOffset = N * 3u * 4u * uvec4(8);
11077 
11078     bool success = true;
11079     // [N][0]
11080     success = sampler1DTest(uvec4(0, 8, 16, 24) + colorOffset,
11081                     t.nested[t.nested[0].nested.index - t.tIndex - 1u].smplr) && success;
11082     // [N][1]
11083     success = sampler1DTest(uvec4(32, 40, 48, 56) + colorOffset,
11084                     t.nested[t.nested[1].nested.index - t.tIndex - 1u].smplr) && success;
11085     // [N][2]
11086     success = sampler1DTest(uvec4(64, 72, 80, 88) + colorOffset,
11087                     t.nested[t.nested[2].nested.index - t.tIndex - 1u].smplr) && success;
11088 
11089     return success;
11090 }
11091 
11092 bool uniformTest(T t, uint N)
11093 {
11094     // Also verify that expressions that involve structs-with-samplers are correct when not
11095     // referecing the sampler.
11096 
11097     bool success = true;
11098     success = (t.nested[0].nested.index - t.tIndex == 1u) && success;
11099     success = (t.nested[1].nested.index - t.tIndex == 2u) && success;
11100     success = (t.nested[2].nested.index - t.tIndex == 3u) && success;
11101 
11102     success = (t.nested[t.nested[0].nested.index - t.tIndex - 1u].nested.index - t.tIndex == 1u)
11103                 && success;
11104     success = (t.nested[t.nested[0].nested.index - t.tIndex     ].nested.index - t.tIndex == 2u)
11105                 && success;
11106     success = (t.nested[t.nested[0].nested.index - t.tIndex + 1u].nested.index - t.tIndex == 3u)
11107                 && success;
11108 
11109     success = (t.nested[
11110                           t.nested[
11111                                      t.nested[2].nested.index - t.tIndex - 1u  // 2
11112                                   ].nested.index - t.tIndex - 2u               // 1
11113                        ].nested.index - t.tIndex                               // 2
11114                 == 2u) && success;
11115 
11116     return success;
11117 }
11118 
11119 void main(void)
11120 {
11121     bool success = samplerTest(u[0], 0u) && samplerTest(u[1], 1u)
11122                     && uniformTest(u[0], 0u) && uniformTest(u[1], 1u);
11123     outbuf.success = uint(success);
11124 }
11125 )";
11126     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
11127     EXPECT_GL_NO_ERROR();
11128 
11129     glUseProgram(program);
11130 
11131     unsigned int outputInitData = 0x12345678u;
11132     GLBuffer outputBuffer;
11133     glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
11134     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
11135     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
11136     EXPECT_GL_NO_ERROR();
11137 
11138     const std::array<GLColor, 24> kTextureData = {
11139         GLColor(0, 0, 0, 0),   GLColor(8, 0, 0, 0),   GLColor(16, 0, 0, 0),  GLColor(24, 0, 0, 0),
11140         GLColor(32, 0, 0, 0),  GLColor(40, 0, 0, 0),  GLColor(48, 0, 0, 0),  GLColor(56, 0, 0, 0),
11141         GLColor(64, 0, 0, 0),  GLColor(72, 0, 0, 0),  GLColor(80, 0, 0, 0),  GLColor(88, 0, 0, 0),
11142         GLColor(96, 0, 0, 0),  GLColor(104, 0, 0, 0), GLColor(112, 0, 0, 0), GLColor(120, 0, 0, 0),
11143         GLColor(128, 0, 0, 0), GLColor(136, 0, 0, 0), GLColor(144, 0, 0, 0), GLColor(152, 0, 0, 0),
11144         GLColor(160, 0, 0, 0), GLColor(168, 0, 0, 0), GLColor(176, 0, 0, 0), GLColor(184, 0, 0, 0),
11145     };
11146     GLTexture textures[2][3][4];
11147 
11148     for (int dim1 = 0; dim1 < 2; ++dim1)
11149     {
11150         for (int dim2 = 0; dim2 < 3; ++dim2)
11151         {
11152             for (int dim3 = 0; dim3 < 4; ++dim3)
11153             {
11154                 int textureUnit = (dim1 * 3 + dim2) * 4 + dim3;
11155                 glActiveTexture(GL_TEXTURE0 + textureUnit);
11156                 glBindTexture(GL_TEXTURE_2D, textures[dim1][dim2][dim3]);
11157                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
11158                              &kTextureData[textureUnit]);
11159                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
11160                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
11161 
11162                 std::stringstream uniformName;
11163                 uniformName << "u[" << dim1 << "].nested[" << dim2 << "].smplr[" << dim3 << "]";
11164                 GLint samplerLocation = glGetUniformLocation(program, uniformName.str().c_str());
11165                 EXPECT_NE(samplerLocation, -1);
11166                 glUniform1i(samplerLocation, textureUnit);
11167             }
11168 
11169             std::stringstream uniformName;
11170             uniformName << "u[" << dim1 << "].nested[" << dim2 << "].nested.index";
11171             GLint nestedIndexLocation = glGetUniformLocation(program, uniformName.str().c_str());
11172             EXPECT_NE(nestedIndexLocation, -1);
11173             glUniform1ui(nestedIndexLocation, dim1 * 4 + dim2 + 1);
11174         }
11175 
11176         std::stringstream uniformName;
11177         uniformName << "u[" << dim1 << "].tIndex";
11178         GLint indexLocation = glGetUniformLocation(program, uniformName.str().c_str());
11179         EXPECT_NE(indexLocation, -1);
11180         glUniform1ui(indexLocation, dim1 * 4);
11181     }
11182     ASSERT_GL_NO_ERROR();
11183 
11184     glDispatchCompute(1, 1, 1);
11185     EXPECT_GL_NO_ERROR();
11186 
11187     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
11188 
11189     // read back
11190     const GLuint *ptr = reinterpret_cast<const GLuint *>(
11191         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
11192     EXPECT_EQ(ptr[0], 1u);
11193 
11194     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
11195 }
11196 
11197 // Test that array of array of samplers work when indexed with an expression that's derived from an
11198 // array of array of samplers.
TEST_P(GLSLTest_ES31,ArrayOfArrayOfSamplerIndexedWithArrayOfArrayOfSamplers)11199 TEST_P(GLSLTest_ES31, ArrayOfArrayOfSamplerIndexedWithArrayOfArrayOfSamplers)
11200 {
11201     // Skip if EXT_gpu_shader5 is not enabled.
11202     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
11203 
11204     // anglebug.com/3832 - no sampler array params on Android
11205     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
11206 
11207     constexpr char kComputeShader[] = R"(#version 310 es
11208 #extension GL_EXT_gpu_shader5 : require
11209 
11210 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
11211 
11212 layout(binding = 1, std430) buffer Output {
11213   uint success;
11214 } outbuf;
11215 
11216 uniform sampler2D smplr[2][3];
11217 
11218 uint getValue(in sampler2D s)
11219 {
11220     return uint(texture(s, vec2(0.5, 0.5)).x * 255.0);
11221 }
11222 
11223 bool runTest(in sampler2D s[2][3])
11224 {
11225     // s[0][0] should contain 2
11226     // s[0][1] should contain 0
11227     // s[0][2] should contain 1
11228     // s[1][0] should contain 1
11229     // s[1][1] should contain 2
11230     // s[1][2] should contain 0
11231 
11232     uint result = getValue(
11233                        s[
11234                            getValue(
11235                                 s[
11236                                     getValue(s[0][1])   // 0
11237                                 ][
11238                                     getValue(s[0][0])   // 2
11239                                 ]
11240                            )                      // s[0][2] -> 1
11241                        ][
11242                            getValue(
11243                                 s[
11244                                     getValue(s[1][0])   // 1
11245                                 ][
11246                                     getValue(s[1][1])   // 2
11247                                 ]
11248                            )                      // s[1][2] -> 0
11249                        ]
11250                   );                      // s[1][0] -> 1
11251 
11252     return result == 1u;
11253 }
11254 
11255 void main(void)
11256 {
11257     outbuf.success = uint(runTest(smplr));
11258 }
11259 )";
11260     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
11261     EXPECT_GL_NO_ERROR();
11262 
11263     glUseProgram(program);
11264 
11265     unsigned int outputInitData = 0x12345678u;
11266     GLBuffer outputBuffer;
11267     glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
11268     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
11269     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
11270     EXPECT_GL_NO_ERROR();
11271 
11272     const std::array<GLColor, 6> kTextureData = {
11273         GLColor(2, 0, 0, 0), GLColor(0, 0, 0, 0), GLColor(1, 0, 0, 0),
11274         GLColor(1, 0, 0, 0), GLColor(2, 0, 0, 0), GLColor(0, 0, 0, 0),
11275     };
11276     GLTexture textures[2][3];
11277 
11278     for (int dim1 = 0; dim1 < 2; ++dim1)
11279     {
11280         for (int dim2 = 0; dim2 < 3; ++dim2)
11281         {
11282             int textureUnit = dim1 * 3 + dim2;
11283             glActiveTexture(GL_TEXTURE0 + textureUnit);
11284             glBindTexture(GL_TEXTURE_2D, textures[dim1][dim2]);
11285             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
11286                          &kTextureData[textureUnit]);
11287             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
11288             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
11289 
11290             std::stringstream uniformName;
11291             uniformName << "smplr[" << dim1 << "][" << dim2 << "]";
11292             GLint samplerLocation = glGetUniformLocation(program, uniformName.str().c_str());
11293             EXPECT_NE(samplerLocation, -1);
11294             glUniform1i(samplerLocation, textureUnit);
11295         }
11296     }
11297     ASSERT_GL_NO_ERROR();
11298 
11299     glDispatchCompute(1, 1, 1);
11300     EXPECT_GL_NO_ERROR();
11301 
11302     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
11303 
11304     // read back
11305     const GLuint *ptr = reinterpret_cast<const GLuint *>(
11306         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
11307     EXPECT_EQ(ptr[0], 1u);
11308 
11309     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
11310 }
11311 
11312 // Test that multiple nested assignments are handled correctly.
TEST_P(GLSLTest_ES31,MixedRowAndColumnMajorMatrices_WriteSideEffect)11313 TEST_P(GLSLTest_ES31, MixedRowAndColumnMajorMatrices_WriteSideEffect)
11314 {
11315     // http://anglebug.com/3831
11316     ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGL());
11317 
11318     // Fails on windows AMD on GL: http://anglebug.com/3838
11319     ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL() && IsAMD());
11320     // http://anglebug.com/5384
11321     ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
11322 
11323     // Fails on D3D due to mistranslation: http://anglebug.com/3841
11324     ANGLE_SKIP_TEST_IF(IsD3D11());
11325 
11326     constexpr char kCS[] = R"(#version 310 es
11327 precision highp float;
11328 layout(local_size_x=1) in;
11329 
11330 layout(std140, column_major) uniform Ubo
11331 {
11332     mat4 m1;
11333     layout(row_major) mat4 m2;
11334 } ubo;
11335 
11336 layout(std140, row_major, binding = 0) buffer Ssbo
11337 {
11338     layout(column_major) mat4 m1;
11339     mat4 m2;
11340 } ssbo;
11341 
11342 layout(std140, binding = 1) buffer Result
11343 {
11344     uint success;
11345 } resultOut;
11346 
11347 void main()
11348 {
11349     bool result = true;
11350 
11351     // Only assign to SSBO from a single invocation.
11352     if (gl_GlobalInvocationID.x == 0u)
11353     {
11354         if ((ssbo.m2 = ssbo.m1 = ubo.m1) != ubo.m2)
11355         {
11356             result = false;
11357         }
11358 
11359         resultOut.success = uint(result);
11360     }
11361 })";
11362 
11363     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
11364     EXPECT_GL_NO_ERROR();
11365 
11366     constexpr size_t kMatrixCount                                     = 2;
11367     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
11368         {4, 4},
11369         {4, 4},
11370     };
11371     constexpr bool kMatrixIsColMajor[kMatrixCount] = {
11372         true,
11373         false,
11374     };
11375 
11376     float data[kMatrixCount * 4 * 4]  = {};
11377     float zeros[kMatrixCount * 4 * 4] = {};
11378 
11379     const uint32_t size =
11380         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
11381 
11382     GLBuffer ubo, ssbo;
11383 
11384     InitBuffer(program, "Ubo", ubo, 0, data, size, true);
11385     InitBuffer(program, "Ssbo", ssbo, 0, zeros, size, false);
11386     EXPECT_GL_NO_ERROR();
11387 
11388     GLBuffer outputBuffer;
11389     CreateOutputBuffer(&outputBuffer, 1);
11390 
11391     glUseProgram(program);
11392     glDispatchCompute(1, 1, 1);
11393     EXPECT_GL_NO_ERROR();
11394     EXPECT_TRUE(VerifySuccess(outputBuffer));
11395 
11396     EXPECT_TRUE(VerifyBuffer(ssbo, data, size));
11397 }
11398 
11399 // Test that assignments to array of array of matrices are handled correctly.
TEST_P(GLSLTest_ES31,MixedRowAndColumnMajorMatrices_WriteArrayOfArray)11400 TEST_P(GLSLTest_ES31, MixedRowAndColumnMajorMatrices_WriteArrayOfArray)
11401 {
11402     // Fails on windows AMD on GL: http://anglebug.com/3838
11403     ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL() && IsAMD());
11404     // http://anglebug.com/5384
11405     ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
11406 
11407     // Fails on D3D due to mistranslation: http://anglebug.com/3841
11408     ANGLE_SKIP_TEST_IF(IsD3D11());
11409 
11410     // Fails compiling shader on Android/Vulkan.  http://anglebug.com/4290
11411     ANGLE_SKIP_TEST_IF(IsAndroid() && IsVulkan());
11412 
11413     // Fails on ARM on Vulkan.  http://anglebug.com/4492
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 layout(std140, column_major) uniform Ubo
11421 {
11422     mat4 m1;
11423     layout(row_major) mat4 m2[2][3];
11424 } ubo;
11425 
11426 layout(std140, row_major, binding = 0) buffer Ssbo
11427 {
11428     layout(column_major) mat4 m1;
11429     mat4 m2[2][3];
11430 } ssbo;
11431 
11432 layout(std140, binding = 1) buffer Result
11433 {
11434     uint success;
11435 } resultOut;
11436 
11437 void main()
11438 {
11439     bool result = true;
11440 
11441     // Only assign to SSBO from a single invocation.
11442     if (gl_GlobalInvocationID.x == 0u)
11443     {
11444         ssbo.m1 = ubo.m1;
11445         ssbo.m2 = ubo.m2;
11446 
11447         resultOut.success = uint(result);
11448     }
11449 })";
11450 
11451     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
11452     EXPECT_GL_NO_ERROR();
11453 
11454     constexpr size_t kMatrixCount                                     = 7;
11455     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
11456         {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4},
11457     };
11458     constexpr bool kMatrixIsColMajor[kMatrixCount] = {
11459         true, false, false, false, false, false, false,
11460     };
11461 
11462     float data[kMatrixCount * 4 * 4]  = {};
11463     float zeros[kMatrixCount * 4 * 4] = {};
11464 
11465     const uint32_t size =
11466         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
11467 
11468     GLBuffer ubo, ssbo;
11469 
11470     InitBuffer(program, "Ubo", ubo, 0, data, size, true);
11471     InitBuffer(program, "Ssbo", ssbo, 0, zeros, size, false);
11472     EXPECT_GL_NO_ERROR();
11473 
11474     GLBuffer outputBuffer;
11475     CreateOutputBuffer(&outputBuffer, 1);
11476 
11477     glUseProgram(program);
11478     glDispatchCompute(1, 1, 1);
11479     EXPECT_GL_NO_ERROR();
11480     EXPECT_TRUE(VerifySuccess(outputBuffer));
11481 
11482     EXPECT_TRUE(VerifyBuffer(ssbo, data, size));
11483 }
11484 
11485 // Verify that types used differently (in different block storages, differently qualified etc) work
11486 // when copied around.
TEST_P(GLSLTest_ES31,TypesUsedInDifferentBlockStorages)11487 TEST_P(GLSLTest_ES31, TypesUsedInDifferentBlockStorages)
11488 {
11489     constexpr char kCS[] = R"(#version 310 es
11490 precision highp float;
11491 layout(local_size_x=1) in;
11492 
11493 struct Inner
11494 {
11495     mat3x2 m;
11496     float f[3];
11497     uvec2 u[2][4];
11498     ivec3 i;
11499     mat2x3 m2[3][2];
11500 };
11501 
11502 struct Outer
11503 {
11504     Inner i[2];
11505 };
11506 
11507 layout(std140, column_major) uniform Ubo140c
11508 {
11509     mat2 m;
11510     layout(row_major) Outer o;
11511 } ubo140cIn;
11512 
11513 layout(std430, row_major, binding = 0) buffer Ubo430r
11514 {
11515     mat2 m;
11516     layout(column_major) Outer o;
11517 } ubo430rIn;
11518 
11519 layout(std140, column_major, binding = 1) buffer Ssbo140c
11520 {
11521     layout(row_major) mat2 m[2];
11522     Outer o;
11523     layout(row_major) Inner i;
11524 } ssbo140cOut;
11525 
11526 layout(std430, row_major, binding = 2) buffer Ssbo430r
11527 {
11528     layout(column_major) mat2 m[2];
11529     Outer o;
11530     layout(column_major) Inner i;
11531 } ssbo430rOut;
11532 
11533 void writeArgToStd140(uvec2 u[2][4], int innerIndex)
11534 {
11535     ssbo140cOut.o.i[innerIndex].u = u;
11536 }
11537 
11538 void writeBlockArgToStd140(Inner i, int innerIndex)
11539 {
11540     ssbo140cOut.o.i[innerIndex] = i;
11541 }
11542 
11543 mat2x3[3][2] readFromStd140(int innerIndex)
11544 {
11545     return ubo140cIn.o.i[0].m2;
11546 }
11547 
11548 Inner readBlockFromStd430(int innerIndex)
11549 {
11550     return ubo430rIn.o.i[innerIndex];
11551 }
11552 
11553 void copyFromStd140(out Inner i)
11554 {
11555     i = ubo140cIn.o.i[1];
11556 }
11557 
11558 void main(){
11559     // Directly copy from one layout to another.
11560     ssbo140cOut.m[0] = ubo140cIn.m;
11561     ssbo140cOut.m[1] = ubo430rIn.m;
11562     ssbo140cOut.o.i[0].m = ubo140cIn.o.i[0].m;
11563     ssbo140cOut.o.i[0].f = ubo140cIn.o.i[0].f;
11564     ssbo140cOut.o.i[0].i = ubo140cIn.o.i[0].i;
11565 
11566     // Read from block and pass to function.
11567     writeArgToStd140(ubo140cIn.o.i[0].u, 0);
11568     writeBlockArgToStd140(ubo430rIn.o.i[0], 1);
11569 
11570     // Have function return value read from block.
11571     ssbo140cOut.o.i[0].m2 = readFromStd140(0);
11572 
11573     // Have function fill in value as out parameter.
11574     copyFromStd140(ssbo140cOut.i);
11575 
11576     // Initialize local variable.
11577     mat2 mStd140 = ubo140cIn.m;
11578 
11579     // Copy to variable, through multiple assignments.
11580     mat2 mStd430, temp;
11581     mStd430 = temp = ubo430rIn.m;
11582 
11583     // Copy from local variable
11584     ssbo430rOut.m[0] = mStd140;
11585     ssbo430rOut.m[1] = mStd430;
11586 
11587     // Construct from struct.
11588     Inner iStd140 = ubo140cIn.o.i[1];
11589     Outer oStd140 = Outer(Inner[2](iStd140, ubo430rIn.o.i[1]));
11590 
11591     // Copy struct from local variable.
11592     ssbo430rOut.o = oStd140;
11593 
11594     // Construct from arrays
11595     Inner iStd430 = Inner(ubo430rIn.o.i[1].m,
11596                           ubo430rIn.o.i[1].f,
11597                           ubo430rIn.o.i[1].u,
11598                           ubo430rIn.o.i[1].i,
11599                           ubo430rIn.o.i[1].m2);
11600     ssbo430rOut.i = iStd430;
11601 })";
11602 
11603     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
11604     EXPECT_GL_NO_ERROR();
11605 
11606     // Test data, laid out with padding (0) based on std140/std430 rules.
11607     // clang-format off
11608     const std::vector<float> ubo140cData = {
11609         // m (mat2, column-major)
11610         1, 2, 0, 0,     3, 4, 0, 0,
11611 
11612         // o.i[0].m (mat3x2, row-major)
11613         5, 7, 9, 0,     6, 8, 10, 0,
11614         // o.i[0].f (float[3])
11615         12, 0, 0, 0,    13, 0, 0, 0,    14, 0, 0, 0,
11616         // o.i[0].u (uvec2[2][4])
11617         15, 16, 0, 0,   17, 18, 0, 0,   19, 20, 0, 0,   21, 22, 0, 0,
11618         23, 24, 0, 0,   25, 26, 0, 0,   27, 28, 0, 0,   29, 30, 0, 0,
11619         // o.i[0].i (ivec3)
11620         31, 32, 33, 0,
11621         // o.i[0].m2 (mat2x3[3][2], row-major)
11622         34, 37, 0, 0,   35, 38, 0, 0,   36, 39, 0, 0,
11623         40, 43, 0, 0,   41, 44, 0, 0,   42, 45, 0, 0,
11624         46, 49, 0, 0,   47, 50, 0, 0,   48, 51, 0, 0,
11625         52, 55, 0, 0,   53, 56, 0, 0,   54, 57, 0, 0,
11626         58, 61, 0, 0,   59, 62, 0, 0,   60, 63, 0, 0,
11627         64, 67, 0, 0,   65, 68, 0, 0,   66, 69, 0, 0,
11628 
11629         // o.i[1].m (mat3x2, row-major)
11630         70, 72, 74, 0,     71, 73, 75, 0,
11631         // o.i[1].f (float[3])
11632         77, 0, 0, 0,    78, 0, 0, 0,    79, 0, 0, 0,
11633         // o.i[1].u (uvec2[2][4])
11634         80, 81, 0, 0,   82, 83, 0, 0,   84, 85, 0, 0,   86, 87, 0, 0,
11635         88, 89, 0, 0,   90, 91, 0, 0,   92, 93, 0, 0,   94, 95, 0, 0,
11636         // o.i[1].i (ivec3)
11637         96, 97, 98, 0,
11638         // o.i[1].m2 (mat2x3[3][2], row-major)
11639          99, 102, 0, 0,  100, 103, 0, 0,   101, 104, 0, 0,
11640         105, 108, 0, 0,  106, 109, 0, 0,   107, 110, 0, 0,
11641         111, 114, 0, 0,  112, 115, 0, 0,   113, 116, 0, 0,
11642         117, 120, 0, 0,  118, 121, 0, 0,   119, 122, 0, 0,
11643         123, 126, 0, 0,  124, 127, 0, 0,   125, 128, 0, 0,
11644         129, 132, 0, 0,  130, 133, 0, 0,   131, 134, 0, 0,
11645     };
11646     const std::vector<float> ubo430rData = {
11647         // m (mat2, row-major)
11648         135, 137,         136, 138,
11649 
11650         // o.i[0].m (mat3x2, column-major)
11651         139, 140,         141, 142,         143, 144,
11652         // o.i[0].f (float[3])
11653         146, 147, 148, 0,
11654         // o.i[0].u (uvec2[2][4])
11655         149, 150,         151, 152,         153, 154,         155, 156,
11656         157, 158,         159, 160,         161, 162,         163, 164, 0, 0,
11657         // o.i[0].i (ivec3)
11658         165, 166, 167, 0,
11659         // o.i[0].m2 (mat2x3[3][2], column-major)
11660         168, 169, 170, 0,   171, 172, 173, 0,
11661         174, 175, 176, 0,   177, 178, 179, 0,
11662         180, 181, 182, 0,   183, 184, 185, 0,
11663         186, 187, 188, 0,   189, 190, 191, 0,
11664         192, 193, 194, 0,   195, 196, 197, 0,
11665         198, 199, 200, 0,   201, 202, 203, 0,
11666 
11667         // o.i[1].m (mat3x2, column-major)
11668         204, 205,         206, 207,         208, 209,
11669         // o.i[1].f (float[3])
11670         211, 212, 213, 0,
11671         // o.i[1].u (uvec2[2][4])
11672         214, 215,         216, 217,         218, 219,         220, 221,
11673         222, 223,         224, 225,         226, 227,         228, 229, 0, 0,
11674         // o.i[1].i (ivec3)
11675         230, 231, 232, 0,
11676         // o.i[1].m2 (mat2x3[3][2], column-major)
11677         233, 234, 235, 0,   236, 237, 238, 0,
11678         239, 240, 241, 0,   242, 243, 244, 0,
11679         245, 246, 247, 0,   248, 249, 250, 0,
11680         251, 252, 253, 0,   254, 255, 256, 0,
11681         257, 258, 259, 0,   260, 261, 262, 0,
11682         263, 264, 265, 0,   266, 267, 268, 0,
11683     };
11684     const std::vector<float> ssbo140cExpect = {
11685         // m (mat2[2], row-major), m[0] copied from ubo140cIn.m, m[1] from ubo430rIn.m
11686         1, 3, 0, 0,     2, 4, 0, 0,
11687         135, 137, 0, 0, 136, 138, 0, 0,
11688 
11689         // o.i[0].m (mat3x2, column-major), copied from ubo140cIn.o.i[0].m
11690         5, 6, 0, 0,     7, 8, 0, 0,     9, 10, 0, 0,
11691         // o.i[0].f (float[3]), copied from ubo140cIn.o.i[0].f
11692         12, 0, 0, 0,    13, 0, 0, 0,    14, 0, 0, 0,
11693         // o.i[0].u (uvec2[2][4]), copied from ubo140cIn.o.i[0].u
11694         15, 16, 0, 0,   17, 18, 0, 0,   19, 20, 0, 0,   21, 22, 0, 0,
11695         23, 24, 0, 0,   25, 26, 0, 0,   27, 28, 0, 0,   29, 30, 0, 0,
11696         // o.i[0].i (ivec3), copied from ubo140cIn.o.i[0].i
11697         31, 32, 33, 0,
11698         // o.i[0].m2 (mat2x3[3][2], column-major), copied from ubo140cIn.o.i[0].m2
11699         34, 35, 36, 0,  37, 38, 39, 0,
11700         40, 41, 42, 0,  43, 44, 45, 0,
11701         46, 47, 48, 0,  49, 50, 51, 0,
11702         52, 53, 54, 0,  55, 56, 57, 0,
11703         58, 59, 60, 0,  61, 62, 63, 0,
11704         64, 65, 66, 0,  67, 68, 69, 0,
11705 
11706         // o.i[1].m (mat3x2, column-major), copied from ubo430rIn.o.i[0].m
11707         139, 140, 0, 0,   141, 142, 0, 0,   143, 144, 0, 0,
11708         // o.i[1].f (float[3]), copied from ubo430rIn.o.i[0].f
11709         146, 0, 0, 0,     147, 0, 0, 0,     148, 0, 0, 0,
11710         // o.i[1].u (uvec2[2][4]), copied from ubo430rIn.o.i[0].u
11711         149, 150, 0, 0,   151, 152, 0, 0,   153, 154, 0, 0,   155, 156, 0, 0,
11712         157, 158, 0, 0,   159, 160, 0, 0,   161, 162, 0, 0,   163, 164, 0, 0,
11713         // o.i[1].i (ivec3), copied from ubo430rIn.o.i[0].i
11714         165, 166, 167, 0,
11715         // o.i[1].m2 (mat2x3[3][2], column-major), copied from ubo430rIn.o.i[0].m2
11716         168, 169, 170, 0,   171, 172, 173, 0,
11717         174, 175, 176, 0,   177, 178, 179, 0,
11718         180, 181, 182, 0,   183, 184, 185, 0,
11719         186, 187, 188, 0,   189, 190, 191, 0,
11720         192, 193, 194, 0,   195, 196, 197, 0,
11721         198, 199, 200, 0,   201, 202, 203, 0,
11722 
11723         // i.m (mat3x2, row-major), copied from ubo140cIn.o.i[1].m
11724         70, 72, 74, 0,     71, 73, 75, 0,
11725         // i.f (float[3]), copied from ubo140cIn.o.i[1].f
11726         77, 0, 0, 0,    78, 0, 0, 0,    79, 0, 0, 0,
11727         // i.u (uvec2[2][4]), copied from ubo430rIn.o.i[1].u
11728         80, 81, 0, 0,   82, 83, 0, 0,   84, 85, 0, 0,   86, 87, 0, 0,
11729         88, 89, 0, 0,   90, 91, 0, 0,   92, 93, 0, 0,   94, 95, 0, 0,
11730         // i.i (ivec3), copied from ubo140cIn.o.i[1].i
11731         96, 97, 98, 0,
11732         // i.m2 (mat2x3[3][2], row-major), copied from ubo140cIn.o.i[1].m2
11733          99, 102, 0, 0,  100, 103, 0, 0,   101, 104, 0, 0,
11734         105, 108, 0, 0,  106, 109, 0, 0,   107, 110, 0, 0,
11735         111, 114, 0, 0,  112, 115, 0, 0,   113, 116, 0, 0,
11736         117, 120, 0, 0,  118, 121, 0, 0,   119, 122, 0, 0,
11737         123, 126, 0, 0,  124, 127, 0, 0,   125, 128, 0, 0,
11738         129, 132, 0, 0,  130, 133, 0, 0,   131, 134, 0, 0,
11739     };
11740     const std::vector<float> ssbo430rExpect = {
11741         // m (mat2[2], column-major), m[0] copied from ubo140cIn.m, m[1] from ubo430rIn.m
11742         1, 2,           3, 4,
11743         135, 136,       137, 138,
11744 
11745         // o.i[0].m (mat3x2, row-major), copied from ubo140cIn.o.i[1].m
11746         70, 72, 74, 0,  71, 73, 75, 0,
11747         // o.i[0].f (float[3]), copied from ubo140cIn.o.i[1].f
11748         77, 78, 79, 0,
11749         // o.i[0].u (uvec2[2][4]), copied from ubo140cIn.o.i[1].u
11750         80, 81,         82, 83,         84, 85,         86, 87,
11751         88, 89,         90, 91,         92, 93,         94, 95,
11752         // o.i[0].i (ivec3), copied from ubo140cIn.o.i[1].i
11753         96, 97, 98, 0,
11754         // o.i[0].m2 (mat2x3[3][2], row-major), copied from ubo140cIn.o.i[1].m2
11755          99, 102,        100, 103,         101, 104,
11756         105, 108,        106, 109,         107, 110,
11757         111, 114,        112, 115,         113, 116,
11758         117, 120,        118, 121,         119, 122,
11759         123, 126,        124, 127,         125, 128,
11760         129, 132,        130, 133,         131, 134,
11761 
11762         // o.i[1].m (mat3x2, row-major), copied from ubo430rIn.o.i[1].m
11763         204, 206, 208, 0,  205, 207, 209, 0,
11764         // o.i[1].f (float[3]), copied from ubo430rIn.o.i[1].f
11765         211, 212, 213, 0,
11766         // o.i[1].u (uvec2[2][4]), copied from ubo430rIn.o.i[1].u
11767         214, 215,         216, 217,         218, 219,         220, 221,
11768         222, 223,         224, 225,         226, 227,         228, 229,
11769         // o.i[1].i (ivec3), copied from ubo430rIn.o.i[1].i
11770         230, 231, 232, 0,
11771         // o.i[1].m2 (mat2x3[3][2], row-major), copied from ubo430rIn.o.i[1].m2
11772         233, 236,         234, 237,         235, 238,
11773         239, 242,         240, 243,         241, 244,
11774         245, 248,         246, 249,         247, 250,
11775         251, 254,         252, 255,         253, 256,
11776         257, 260,         258, 261,         259, 262,
11777         263, 266,         264, 267,         265, 268,
11778 
11779         // i.m (mat3x2, column-major), copied from ubo430rIn.o.i[1].m
11780         204, 205,          206, 207,         208, 209,
11781         // i.f (float[3]), copied from ubo430rIn.o.i[1].f
11782         211, 212, 213, 0,
11783         // i.u (uvec2[2][4]), copied from ubo430rIn.o.i[1].u
11784         214, 215,         216, 217,         218, 219,         220, 221,
11785         222, 223,         224, 225,         226, 227,         228, 229, 0, 0,
11786         // i.i (ivec3), copied from ubo430rIn.o.i[1].i
11787         230, 231, 232, 0,
11788         // i.m2 (mat2x3[3][2], column-major), copied from ubo430rIn.o.i[1].m2
11789         233, 234, 235, 0,   236, 237, 238, 0,
11790         239, 240, 241, 0,   242, 243, 244, 0,
11791         245, 246, 247, 0,   248, 249, 250, 0,
11792         251, 252, 253, 0,   254, 255, 256, 0,
11793         257, 258, 259, 0,   260, 261, 262, 0,
11794         263, 264, 265, 0,   266, 267, 268, 0,
11795     };
11796     const std::vector<float> zeros(std::max(ssbo140cExpect.size(), ssbo430rExpect.size()), 0);
11797     // clang-format on
11798 
11799     GLBuffer uboStd140ColMajor, uboStd430RowMajor;
11800     GLBuffer ssboStd140ColMajor, ssboStd430RowMajor;
11801 
11802     InitBuffer(program, "Ubo140c", uboStd140ColMajor, 0, ubo140cData.data(),
11803                static_cast<uint32_t>(ubo140cData.size()), true);
11804     InitBuffer(program, "Ubo430r", uboStd430RowMajor, 0, ubo430rData.data(),
11805                static_cast<uint32_t>(ubo430rData.size()), false);
11806     InitBuffer(program, "Ssbo140c", ssboStd140ColMajor, 1, zeros.data(),
11807                static_cast<uint32_t>(ssbo140cExpect.size()), false);
11808     InitBuffer(program, "Ssbo430r", ssboStd430RowMajor, 2, zeros.data(),
11809                static_cast<uint32_t>(ssbo430rExpect.size()), false);
11810     EXPECT_GL_NO_ERROR();
11811 
11812     glUseProgram(program);
11813     glDispatchCompute(1, 1, 1);
11814     EXPECT_GL_NO_ERROR();
11815 
11816     EXPECT_TRUE(VerifyBuffer(ssboStd140ColMajor, ssbo140cExpect.data(),
11817                              static_cast<uint32_t>(ssbo140cExpect.size())));
11818     EXPECT_TRUE(VerifyBuffer(ssboStd430RowMajor, ssbo430rExpect.data(),
11819                              static_cast<uint32_t>(ssbo430rExpect.size())));
11820 }
11821 
11822 // Verify that bool in interface blocks work.
TEST_P(GLSLTest_ES31,BoolInInterfaceBlocks)11823 TEST_P(GLSLTest_ES31, BoolInInterfaceBlocks)
11824 {
11825     constexpr char kCS[] = R"(#version 310 es
11826 precision highp float;
11827 layout(local_size_x=1) in;
11828 
11829 struct Inner
11830 {
11831     bool b;
11832     bvec2 b2;
11833     bvec3 b3;
11834     bvec4 b4;
11835     bool ba[5];
11836     bvec2 b2a[2][3];
11837 };
11838 
11839 struct Outer
11840 {
11841     Inner i[2];
11842 };
11843 
11844 layout(std140) uniform Ubo140
11845 {
11846     Outer o;
11847 };
11848 
11849 layout(std430, binding = 0) buffer Ubo430
11850 {
11851     Outer o;
11852 } ubo430In;
11853 
11854 layout(std140, binding = 1) buffer Ssbo140
11855 {
11856     bool valid;
11857     Inner i;
11858 } ssbo140Out;
11859 
11860 layout(std430, binding = 2) buffer Ssbo430
11861 {
11862     bool valid;
11863     Inner i;
11864 };
11865 
11866 void writeArgToStd430(bool ba[5])
11867 {
11868     i.ba = ba;
11869 }
11870 
11871 bool[5] readFromStd430(uint innerIndex)
11872 {
11873     return ubo430In.o.i[innerIndex].ba;
11874 }
11875 
11876 void copyFromStd430(out bvec2 b2a[2][3])
11877 {
11878     b2a = ubo430In.o.i[0].b2a;
11879 }
11880 
11881 bool destroyContent(inout Inner iOut)
11882 {
11883     iOut.b = true;
11884     iOut.b2 = bvec2(true);
11885     iOut.b3 = bvec3(true);
11886     iOut.b4 = bvec4(true);
11887     iOut.ba = bool[5](true, true, true, true, true);
11888     bvec2 true3[3] = bvec2[3](iOut.b2, iOut.b2, iOut.b2);
11889     iOut.b2a = bvec2[2][3](true3, true3);
11890     return true;
11891 }
11892 
11893 void main(){
11894     // Directly copy from one layout to another.
11895     i.b = o.i[0].b;
11896     i.b2 = o.i[0].b2;
11897     i.b2a = o.i[0].b2a;
11898 
11899     // Copy to temp with swizzle.
11900     bvec4 t1 = o.i[0].b3.yxzy;
11901     bvec4 t2 = o.i[0].b4.xxyy;
11902     bvec4 t3 = o.i[0].b4.zzww;
11903 
11904     // Copy from temp with swizzle.
11905     i.b3 = t1.ywz;
11906     i.b4.yz = bvec2(t2.z, t3.y);
11907     i.b4.wx = bvec2(t3.w, t2.x);
11908 
11909     // Copy by passing argument to function.
11910     writeArgToStd430(o.i[0].ba);
11911 
11912     // Copy by return value.
11913     ssbo140Out.i.ba = readFromStd430(0u);
11914 
11915     // Copy by out parameter.
11916     copyFromStd430(ssbo140Out.i.b2a);
11917 
11918     // Logical operations
11919     uvec4 t4 = ubo430In.o.i[0].b ? uvec4(0) : uvec4(1);
11920     ssbo140Out.i.b = all(equal(t4, uvec4(1))) && (ubo430In.o.i[0].b ? false : true);
11921     ssbo140Out.i.b2 = not(ubo430In.o.i[0].b2);
11922     ssbo140Out.i.b3 = bvec3(all(ubo430In.o.i[0].b3), any(ubo430In.o.i[0].b3), any(ubo430In.o.i[0].b3.yx));
11923     ssbo140Out.i.b4 = equal(ubo430In.o.i[0].b4, bvec4(true, false, true, false));
11924 
11925     ssbo140Out.valid = true;
11926     ssbo140Out.valid = ssbo140Out.valid && all(equal(bvec3(o.i[1].b, o.i[1].b2), o.i[1].b3));
11927     ssbo140Out.valid = ssbo140Out.valid &&
11928             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])));
11929     ssbo140Out.valid = ssbo140Out.valid && uint(o.i[1].ba[4]) == 1u;
11930     for (int x = 0; x < o.i[1].b2a.length(); ++x)
11931     {
11932         for (int y = 0; y < o.i[1].b2a[x].length(); ++y)
11933         {
11934             ssbo140Out.valid = ssbo140Out.valid && all(equal(uvec2(o.i[1].b2a[x][y]), uvec2(x % 2, y % 2)));
11935         }
11936     }
11937 
11938     valid = o.i[1] == ubo430In.o.i[1];
11939 
11940     // Make sure short-circuiting behavior is correct.
11941     bool falseVar = !valid && destroyContent(i);
11942     if (falseVar && destroyContent(ssbo140Out.i))
11943     {
11944         valid = false;
11945     }
11946 
11947     if (valid || o.i[uint((i.ba = bool[5](true, true, true, true, true))[1])].b)
11948     {
11949     }
11950     else
11951     {
11952         ssbo140Out.valid = false;
11953     }
11954 })";
11955 
11956     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
11957     EXPECT_GL_NO_ERROR();
11958 
11959     // Test data, laid out with padding (0) based on std140/std430 rules.
11960     // clang-format off
11961     const std::vector<uint32_t> ubo140Data = {
11962         // o.i[0].b (bool)
11963         true, 0,
11964         // o.i[0].b2 (bvec2)
11965         true, false,
11966         // o.i[0].b3 (bvec3)
11967         true, true, false, 0,
11968         // o.i[0].b4 (bvec4)
11969         false, true, false, true,
11970         // o.i[0].ba (bool[5])
11971         true, 0, 0, 0,
11972         false, 0, 0, 0,
11973         false, 0, 0, 0,
11974         true, 0, 0, 0,
11975         true, 0, 0, 0,
11976         // o.i[0].b2a (bool[2][3])
11977         false, true, 0, 0,  true, true, 0, 0,    true, false, 0, 0,
11978         true, false, 0, 0,  false, false, 0, 0,  true, true, 0, 0,
11979 
11980         // o.i[1].b (bool)
11981         false, 0,
11982         // o.i[1].b2 (bvec2)
11983         true, true,
11984         // o.i[1].b3 (bvec3), expected to be equal to (b, b2)
11985         false, true, true, 0,
11986         // o.i[1].b4 (bvec4)
11987         true, false, true, true,
11988         // o.i[1].ba (bool[5]), expected to be equal to (not(b4), 1)
11989         false, 0, 0, 0,
11990         true, 0, 0, 0,
11991         false, 0, 0, 0,
11992         false, 0, 0, 0,
11993         true, 0, 0, 0,
11994         // o.i[1].b2a (bvec2[2][3]), [x][y] expected to equal (x%2,y%2)
11995         false, false, 0, 0,  false, true, 0, 0,  false, false, 0, 0,
11996         true, false, 0, 0,   true, true, 0, 0,   true, false, 0, 0,
11997     };
11998     const std::vector<uint32_t> ubo430Data = {
11999         // o.i[0].b (bool)
12000         false, 0,
12001         // o.i[0].b2 (bvec2)
12002         true, true,
12003         // o.i[0].b3 (bvec3)
12004         false, false, true, 0,
12005         // o.i[0].b4 (bvec4)
12006         true, false, true, true,
12007         // o.i[0].ba (bool[5])
12008         false, false, false, true, false, 0,
12009         // o.i[0].b2a (bool[2][3])
12010         true, false,  true, false,  true, true,
12011         false, true,  true, true,   false, false, 0, 0,
12012 
12013         // o.i[1] expected to be equal to ubo140In.o.i[1]
12014         // o.i[1].b (bool)
12015         false, 0,
12016         // o.i[1].b2 (bvec2)
12017         true, true,
12018         // o.i[1].b3 (bvec3)
12019         false, true, true, 0,
12020         // o.i[1].b4 (bvec4)
12021         true, false, true, true,
12022         // o.i[1].ba (bool[5])
12023         false, true, false, false, true, 0,
12024         // o.i[1].b2a (bvec2[2][3])
12025         false, false,  false, true,  false, false,
12026         true, false,   true, true,   true, false,
12027     };
12028     const std::vector<uint32_t> ssbo140Expect = {
12029         // valid, expected to be true
12030         true, 0, 0, 0,
12031 
12032         // i.b (bool), ubo430In.o.i[0].b ? false : true
12033         true, 0,
12034         // i.b2 (bvec2), not(ubo430In.o.i[0].b2)
12035         false, false,
12036         // i.b3 (bvec3), all(ubo430In.o.i[0].b3), any(...b3), any(...b3.yx)
12037         false, true, false, 0,
12038         // i.b4 (bvec4), ubo430In.o.i[0].b4 == (true, false, true, false)
12039         true, true, true, false,
12040         // i.ba (bool[5]), copied from ubo430In.o.i[0].ba
12041         false, 0, 0, 0,
12042         false, 0, 0, 0,
12043         false, 0, 0, 0,
12044         true, 0, 0, 0,
12045         false, 0, 0, 0,
12046         // i.b2a (bool[2][3]), copied from ubo430In.o.i[0].b2a
12047         true, false, 0, 0,  true, false, 0, 0,   true, true, 0, 0,
12048         false, true, 0, 0,  true, true, 0, 0,    false, false, 0, 0,
12049     };
12050     const std::vector<uint32_t> ssbo430Expect = {
12051         // valid, expected to be true
12052         true, 0, 0, 0,
12053 
12054         // o.i[0].b (bool), copied from (Ubo140::)o.i[0].b
12055         true, 0,
12056         // o.i[0].b2 (bvec2), copied from (Ubo140::)o.i[0].b2
12057         true, false,
12058         // o.i[0].b3 (bvec3), copied from (Ubo140::)o.i[0].b3
12059         true, true, false, 0,
12060         // o.i[0].b4 (bvec4), copied from (Ubo140::)o.i[0].b4
12061         false, true, false, true,
12062         // o.i[0].ba (bool[5]), copied from (Ubo140::)o.i[0].ba
12063         true, false, false, true, true, 0,
12064         // o.i[0].b2a (bool[2][3]), copied from (Ubo140::)o.i[0].b2a
12065         false, true,  true, true,    true, false,
12066         true, false,  false, false,  true, true, 0, 0,
12067     };
12068     const std::vector<uint32_t> zeros(std::max(ssbo140Expect.size(), ssbo430Expect.size()), 0);
12069     // clang-format on
12070 
12071     GLBuffer uboStd140, uboStd430;
12072     GLBuffer ssboStd140, ssboStd430;
12073 
12074     InitBuffer(program, "Ubo140", uboStd140, 0, ubo140Data.data(),
12075                static_cast<uint32_t>(ubo140Data.size()), true);
12076     InitBuffer(program, "Ubo430", uboStd430, 0, ubo430Data.data(),
12077                static_cast<uint32_t>(ubo430Data.size()), false);
12078     InitBuffer(program, "Ssbo140", ssboStd140, 1, zeros.data(),
12079                static_cast<uint32_t>(ssbo140Expect.size()), false);
12080     InitBuffer(program, "Ssbo430", ssboStd430, 2, zeros.data(),
12081                static_cast<uint32_t>(ssbo430Expect.size()), false);
12082     EXPECT_GL_NO_ERROR();
12083 
12084     glUseProgram(program);
12085     glDispatchCompute(1, 1, 1);
12086     EXPECT_GL_NO_ERROR();
12087 
12088     EXPECT_TRUE(VerifyBuffer(ssboStd140, ssbo140Expect.data(),
12089                              static_cast<uint32_t>(ssbo140Expect.size())));
12090     EXPECT_TRUE(VerifyBuffer(ssboStd430, ssbo430Expect.data(),
12091                              static_cast<uint32_t>(ssbo430Expect.size())));
12092 }
12093 
12094 // Test that the precise keyword is not reserved before ES3.1.
TEST_P(GLSLTest_ES3,PreciseNotReserved)12095 TEST_P(GLSLTest_ES3, PreciseNotReserved)
12096 {
12097     // Skip in ES3.1+ as the precise keyword is reserved/core.
12098     ANGLE_SKIP_TEST_IF(getClientMajorVersion() > 3 ||
12099                        (getClientMajorVersion() == 3 && getClientMinorVersion() >= 1));
12100 
12101     constexpr char kFS[] = R"(#version 300 es
12102 precision mediump float;
12103 in float precise;
12104 out vec4 my_FragColor;
12105 void main() { my_FragColor = vec4(precise, 0, 0, 1.0); })";
12106 
12107     constexpr char kVS[] = R"(#version 300 es
12108 in vec4 a_position;
12109 out float precise;
12110 void main() { precise = a_position.x; gl_Position = a_position; })";
12111 
12112     GLuint program = CompileProgram(kVS, kFS);
12113     EXPECT_NE(0u, program);
12114 }
12115 
12116 // Test that the precise keyword is reserved on ES3.0 without GL_EXT_gpu_shader5.
TEST_P(GLSLTest_ES31,PreciseReservedWithoutExtension)12117 TEST_P(GLSLTest_ES31, PreciseReservedWithoutExtension)
12118 {
12119     // Skip if EXT_gpu_shader5 is enabled.
12120     ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
12121     // Skip in ES3.2+ as the precise keyword is core.
12122     ANGLE_SKIP_TEST_IF(getClientMajorVersion() > 3 ||
12123                        (getClientMajorVersion() == 3 && getClientMinorVersion() >= 2));
12124 
12125     constexpr char kFS[] = R"(#version 310 es
12126 precision mediump float;
12127 in float v_varying;
12128 out vec4 my_FragColor;
12129 void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); })";
12130 
12131     constexpr char kVS[] = R"(#version 310 es
12132 in vec4 a_position;
12133 precise out float v_varying;
12134 void main() { v_varying = a_position.x; gl_Position = a_position; })";
12135 
12136     // Should fail, as precise is a reserved keyword when the extension is not enabled.
12137     GLuint program = CompileProgram(kVS, kFS);
12138     EXPECT_EQ(0u, program);
12139 }
12140 
12141 // Test that reusing the same variable name for different uses across stages links fine.  Glslang
12142 // wrapper's SPIR-V transformation should ignore all names for non-shader-interface variables and
12143 // not get confused by them.
TEST_P(GLSLTest_ES31,VariableNameReuseAcrossStages)12144 TEST_P(GLSLTest_ES31, VariableNameReuseAcrossStages)
12145 {
12146     // Fails to compile the fragment shader with error "undeclared identifier '_g'"
12147     // http://anglebug.com/4404
12148     ANGLE_SKIP_TEST_IF(IsD3D11());
12149 
12150     constexpr char kVS[] = R"(#version 310 es
12151 precision mediump float;
12152 uniform highp vec4 a;
12153 in highp vec4 b;
12154 in highp vec4 c;
12155 in highp vec4 d;
12156 out highp vec4 e;
12157 
12158 vec4 f(vec4 a)
12159 {
12160     return a;
12161 }
12162 
12163 vec4 g(vec4 f)
12164 {
12165     return f + f;
12166 }
12167 
12168 void main() {
12169     e = f(b) + a;
12170     gl_Position = g(c) + f(d);
12171 }
12172 )";
12173 
12174     constexpr char kFS[] = R"(#version 310 es
12175 precision mediump float;
12176 in highp vec4 e;
12177 uniform sampler2D f;
12178 layout(rgba8) uniform highp readonly image2D g;
12179 uniform A
12180 {
12181     vec4 x;
12182 } c;
12183 layout(std140, binding=0) buffer B
12184 {
12185     vec4 x;
12186 } d[2];
12187 out vec4 col;
12188 
12189 vec4 h(vec4 c)
12190 {
12191     return texture(f, c.xy) + imageLoad(g, ivec2(c.zw));
12192 }
12193 
12194 vec4 i(vec4 x, vec4 y)
12195 {
12196     return vec4(x.xy, y.zw);
12197 }
12198 
12199 void main() {
12200     col = h(e) + i(c.x, d[0].x) + d[1].x;
12201 }
12202 )";
12203 
12204     GLuint program = CompileProgram(kVS, kFS);
12205     EXPECT_NE(0u, program);
12206 }
12207 
12208 // Test that reusing the same uniform variable name for different uses across stages links fine.
TEST_P(GLSLTest_ES31,UniformVariableNameReuseAcrossStages)12209 TEST_P(GLSLTest_ES31, UniformVariableNameReuseAcrossStages)
12210 {
12211     constexpr char kVS[] = R"(#version 310 es
12212 precision mediump float;
12213 in highp vec4 variableWithSameName;
12214 
12215 void main() {
12216     gl_Position = variableWithSameName;
12217 }
12218 )";
12219 
12220     constexpr char kFS[] = R"(#version 310 es
12221 precision mediump float;
12222 uniform vec4 variableWithSameName;
12223 out vec4 col;
12224 
12225 void main() {
12226     col = vec4(variableWithSameName);
12227 }
12228 )";
12229 
12230     GLuint program = CompileProgram(kVS, kFS);
12231     EXPECT_NE(0u, program);
12232 }
12233 
12234 // Verify that precision match validation of uniforms is performed only if they are statically used
TEST_P(GLSLTest_ES31,UniformPrecisionMatchValidation)12235 TEST_P(GLSLTest_ES31, UniformPrecisionMatchValidation)
12236 {
12237     // Nvidia driver bug: http://anglebug.com/5240
12238     ANGLE_SKIP_TEST_IF(IsOpenGL() && IsWindows() && IsNVIDIA());
12239 
12240     constexpr char kVSUnused[] = R"(#version 300 es
12241 precision highp float;
12242 uniform highp vec4 positionIn;
12243 
12244 void main()
12245 {
12246     gl_Position = vec4(1, 0, 0, 1);
12247 })";
12248 
12249     constexpr char kVSStaticUse[] = R"(#version 300 es
12250 precision highp float;
12251 uniform highp vec4 positionIn;
12252 
12253 void main()
12254 {
12255     gl_Position = positionIn;
12256 })";
12257 
12258     constexpr char kFSUnused[] = R"(#version 300 es
12259 precision highp float;
12260 uniform highp vec4 positionIn;
12261 out vec4 my_FragColor;
12262 
12263 void main()
12264 {
12265     my_FragColor = vec4(1, 0, 0, 1);
12266 })";
12267 
12268     constexpr char kFSStaticUse[] = R"(#version 300 es
12269 precision highp float;
12270 uniform mediump vec4 positionIn;
12271 out vec4 my_FragColor;
12272 
12273 void main()
12274 {
12275     my_FragColor = vec4(1, 0, 0, positionIn.z);
12276 })";
12277 
12278     GLuint program = 0;
12279 
12280     program = CompileProgram(kVSUnused, kFSUnused);
12281     EXPECT_NE(0u, program);
12282 
12283     program = CompileProgram(kVSUnused, kFSStaticUse);
12284     EXPECT_NE(0u, program);
12285 
12286     program = CompileProgram(kVSStaticUse, kFSUnused);
12287     EXPECT_NE(0u, program);
12288 
12289     program = CompileProgram(kVSStaticUse, kFSStaticUse);
12290     EXPECT_EQ(0u, program);
12291 }
12292 
12293 // Validate that link fails when two instanceless interface blocks with different block names but
12294 // same field names are present.
TEST_P(GLSLTest_ES31,AmbiguousInstancelessInterfaceBlockFields)12295 TEST_P(GLSLTest_ES31, AmbiguousInstancelessInterfaceBlockFields)
12296 {
12297     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
12298 
12299     constexpr char kVS[] = R"(#version 310 es
12300 in highp vec4 position;
12301 layout(binding = 0) buffer BlockA { mediump float a; };
12302 void main()
12303 {
12304     a = 0.0;
12305     gl_Position = position;
12306 })";
12307 
12308     constexpr char kFS[] = R"(#version 310 es
12309 precision mediump float;
12310 layout(location = 0) out mediump vec4 color;
12311 uniform BlockB { float a; };
12312 void main()
12313 {
12314     color = vec4(a, a, a, 1.0);
12315 })";
12316 
12317     GLuint program = CompileProgram(kVS, kFS);
12318     EXPECT_EQ(0u, program);
12319 }
12320 
12321 // Verify I/O block array locations
TEST_P(GLSLTest_ES31,IOBlockLocations)12322 TEST_P(GLSLTest_ES31, IOBlockLocations)
12323 {
12324     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
12325     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
12326 
12327     constexpr char kVS[] = R"(#version 310 es
12328 #extension GL_EXT_shader_io_blocks : require
12329 
12330 in highp vec4 position;
12331 
12332 layout(location = 0) out vec4 aOut;
12333 
12334 layout(location = 6) out VSBlock
12335 {
12336     vec4 b;     // location 6
12337     vec4 c;     // location 7
12338     layout(location = 1) vec4 d;
12339     vec4 e;     // location 2
12340     vec4 f[2];  // locations 3 and 4
12341 } blockOut;
12342 
12343 layout(location = 5) out vec4 gOut;
12344 
12345 void main()
12346 {
12347     aOut = vec4(0.03, 0.06, 0.09, 0.12);
12348     blockOut.b = vec4(0.15, 0.18, 0.21, 0.24);
12349     blockOut.c = vec4(0.27, 0.30, 0.33, 0.36);
12350     blockOut.d = vec4(0.39, 0.42, 0.45, 0.48);
12351     blockOut.e = vec4(0.51, 0.54, 0.57, 0.6);
12352     blockOut.f[0] = vec4(0.63, 0.66, 0.66, 0.69);
12353     blockOut.f[1] = vec4(0.72, 0.75, 0.78, 0.81);
12354     gOut = vec4(0.84, 0.87, 0.9, 0.93);
12355     gl_Position = position;
12356 })";
12357 
12358     constexpr char kGS[] = R"(#version 310 es
12359 #extension GL_EXT_geometry_shader : require
12360 layout (triangles) in;
12361 layout (triangle_strip, max_vertices = 3) out;
12362 
12363 // Input varyings
12364 layout(location = 0) in vec4 aIn[];
12365 
12366 layout(location = 6) in VSBlock
12367 {
12368     vec4 b;
12369     vec4 c;
12370     layout(location = 1) vec4 d;
12371     vec4 e;
12372     vec4 f[2];
12373 } blockIn[];
12374 
12375 layout(location = 5) in vec4 gIn[];
12376 
12377 // Output varyings
12378 layout(location = 1) out vec4 aOut;
12379 
12380 layout(location = 0) out GSBlock
12381 {
12382     vec4 b;     // location 0
12383     layout(location = 3) vec4 c;
12384     layout(location = 7) vec4 d;
12385     layout(location = 5) vec4 e[2];
12386     layout(location = 4) vec4 f;
12387 } blockOut;
12388 
12389 layout(location = 2) out vec4 gOut;
12390 
12391 void main()
12392 {
12393     int n;
12394     for (n = 0; n < gl_in.length(); n++)
12395     {
12396         gl_Position = gl_in[n].gl_Position;
12397 
12398         aOut = aIn[n];
12399         blockOut.b = blockIn[n].b;
12400         blockOut.c = blockIn[n].c;
12401         blockOut.d = blockIn[n].d;
12402         blockOut.e[0] = blockIn[n].e;
12403         blockOut.e[1] = blockIn[n].f[0];
12404         blockOut.f = blockIn[n].f[1];
12405         gOut = gIn[n];
12406 
12407         EmitVertex();
12408     }
12409     EndPrimitive();
12410 })";
12411 
12412     constexpr char kFS[] = R"(#version 310 es
12413 #extension GL_EXT_shader_io_blocks : require
12414 precision mediump float;
12415 
12416 layout(location = 0) out mediump vec4 color;
12417 
12418 layout(location = 1) in vec4 aIn;
12419 
12420 layout(location = 0) in GSBlock
12421 {
12422     vec4 b;
12423     layout(location = 3) vec4 c;
12424     layout(location = 7) vec4 d;
12425     layout(location = 5) vec4 e[2];
12426     layout(location = 4) vec4 f;
12427 } blockIn;
12428 
12429 layout(location = 2) in vec4 gIn;
12430 
12431 bool isEq(vec4 a, vec4 b) { return all(lessThan(abs(a-b), vec4(0.001))); }
12432 
12433 void main()
12434 {
12435     bool passR = isEq(aIn, vec4(0.03, 0.06, 0.09, 0.12));
12436     bool passG = isEq(blockIn.b, vec4(0.15, 0.18, 0.21, 0.24)) &&
12437                  isEq(blockIn.c, vec4(0.27, 0.30, 0.33, 0.36)) &&
12438                  isEq(blockIn.d, vec4(0.39, 0.42, 0.45, 0.48)) &&
12439                  isEq(blockIn.e[0], vec4(0.51, 0.54, 0.57, 0.6)) &&
12440                  isEq(blockIn.e[1], vec4(0.63, 0.66, 0.66, 0.69)) &&
12441                  isEq(blockIn.f, vec4(0.72, 0.75, 0.78, 0.81));
12442     bool passB = isEq(gIn, vec4(0.84, 0.87, 0.9, 0.93));
12443 
12444     color = vec4(passR, passG, passB, 1.0);
12445 })";
12446 
12447     ANGLE_GL_PROGRAM_WITH_GS(program, kVS, kGS, kFS);
12448     EXPECT_GL_NO_ERROR();
12449 
12450     GLTexture color;
12451     glBindTexture(GL_TEXTURE_2D, color);
12452     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
12453 
12454     GLFramebuffer fbo;
12455     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
12456     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
12457 
12458     drawQuad(program, "position", 0);
12459 
12460     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
12461 }
12462 
12463 // Test varying packing in presence of multiple I/O blocks
TEST_P(GLSLTest_ES31,MultipleIOBlocks)12464 TEST_P(GLSLTest_ES31, MultipleIOBlocks)
12465 {
12466     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
12467 
12468     constexpr char kVS[] = R"(#version 310 es
12469 #extension GL_EXT_shader_io_blocks : require
12470 
12471 in highp vec4 position;
12472 
12473 out VSBlock1
12474 {
12475     vec4 a;
12476     vec4 b[2];
12477 } blockOut1;
12478 
12479 out VSBlock2
12480 {
12481     vec4 c[2];
12482     vec4 d;
12483 } blockOut2;
12484 
12485 void main()
12486 {
12487     blockOut1.a = vec4(0.15, 0.18, 0.21, 0.24);
12488     blockOut1.b[0] = vec4(0.27, 0.30, 0.33, 0.36);
12489     blockOut1.b[1] = vec4(0.39, 0.42, 0.45, 0.48);
12490     blockOut2.c[0] = vec4(0.51, 0.54, 0.57, 0.6);
12491     blockOut2.c[1] = vec4(0.63, 0.66, 0.66, 0.69);
12492     blockOut2.d = vec4(0.72, 0.75, 0.78, 0.81);
12493     gl_Position = position;
12494 })";
12495 
12496     constexpr char kFS[] = R"(#version 310 es
12497 #extension GL_EXT_shader_io_blocks : require
12498 precision mediump float;
12499 
12500 layout(location = 0) out mediump vec4 color;
12501 
12502 in VSBlock1
12503 {
12504     vec4 a;
12505     vec4 b[2];
12506 } blockIn1;
12507 
12508 in VSBlock2
12509 {
12510     vec4 c[2];
12511     vec4 d;
12512 } blockIn2;
12513 
12514 bool isEq(vec4 a, vec4 b) { return all(lessThan(abs(a-b), vec4(0.001))); }
12515 
12516 void main()
12517 {
12518     bool passR = isEq(blockIn1.a, vec4(0.15, 0.18, 0.21, 0.24));
12519     bool passG = isEq(blockIn1.b[0], vec4(0.27, 0.30, 0.33, 0.36)) &&
12520                  isEq(blockIn1.b[1], vec4(0.39, 0.42, 0.45, 0.48));
12521     bool passB = isEq(blockIn2.c[0], vec4(0.51, 0.54, 0.57, 0.6)) &&
12522                  isEq(blockIn2.c[1], vec4(0.63, 0.66, 0.66, 0.69));
12523     bool passA = isEq(blockIn2.d, vec4(0.72, 0.75, 0.78, 0.81));
12524 
12525     color = vec4(passR, passG, passB, passA);
12526 })";
12527 
12528     ANGLE_GL_PROGRAM(program, kVS, kFS);
12529     EXPECT_GL_NO_ERROR();
12530 
12531     GLTexture color;
12532     glBindTexture(GL_TEXTURE_2D, color);
12533     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
12534 
12535     GLFramebuffer fbo;
12536     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
12537     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
12538 
12539     drawQuad(program, "position", 0);
12540 
12541     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
12542 }
12543 
12544 // Test varying packing in presence of I/O block arrays
TEST_P(GLSLTest_ES31,IOBlockArray)12545 TEST_P(GLSLTest_ES31, IOBlockArray)
12546 {
12547     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
12548 
12549     constexpr char kVS[] = R"(#version 310 es
12550 #extension GL_EXT_shader_io_blocks : require
12551 
12552 in highp vec4 position;
12553 
12554 out VSBlock1
12555 {
12556     vec4 b[2];
12557 } blockOut1[2];
12558 
12559 out VSBlock2
12560 {
12561     vec4 d;
12562 } blockOut2[3];
12563 
12564 void main()
12565 {
12566     blockOut1[0].b[0] = vec4(0.15, 0.18, 0.21, 0.24);
12567     blockOut1[0].b[1] = vec4(0.27, 0.30, 0.33, 0.36);
12568     blockOut1[1].b[0] = vec4(0.39, 0.42, 0.45, 0.48);
12569     blockOut1[1].b[1] = vec4(0.51, 0.54, 0.57, 0.6);
12570     blockOut2[0].d = vec4(0.63, 0.66, 0.66, 0.69);
12571     blockOut2[1].d = vec4(0.72, 0.75, 0.78, 0.81);
12572     blockOut2[2].d = vec4(0.84, 0.87, 0.9, 0.93);
12573     gl_Position = position;
12574 })";
12575 
12576     constexpr char kFS[] = R"(#version 310 es
12577 #extension GL_EXT_shader_io_blocks : require
12578 precision mediump float;
12579 
12580 layout(location = 0) out mediump vec4 color;
12581 
12582 in VSBlock1
12583 {
12584     vec4 b[2];
12585 } blockIn1[2];
12586 
12587 in VSBlock2
12588 {
12589     vec4 d;
12590 } blockIn2[3];
12591 
12592 bool isEq(vec4 a, vec4 b) { return all(lessThan(abs(a-b), vec4(0.001))); }
12593 
12594 void main()
12595 {
12596     bool passR = isEq(blockIn1[0].b[0], vec4(0.15, 0.18, 0.21, 0.24)) &&
12597                  isEq(blockIn1[0].b[1], vec4(0.27, 0.30, 0.33, 0.36));
12598     bool passG = isEq(blockIn1[1].b[0], vec4(0.39, 0.42, 0.45, 0.48)) &&
12599                  isEq(blockIn1[1].b[1], vec4(0.51, 0.54, 0.57, 0.6));
12600     bool passB = isEq(blockIn2[0].d, vec4(0.63, 0.66, 0.66, 0.69));
12601     bool passA = isEq(blockIn2[1].d, vec4(0.72, 0.75, 0.78, 0.81)) &&
12602                  isEq(blockIn2[2].d, vec4(0.84, 0.87, 0.9, 0.93));
12603 
12604     color = vec4(passR, passG, passB, passA);
12605 })";
12606 
12607     ANGLE_GL_PROGRAM(program, kVS, kFS);
12608     EXPECT_GL_NO_ERROR();
12609 
12610     GLTexture color;
12611     glBindTexture(GL_TEXTURE_2D, color);
12612     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
12613 
12614     GLFramebuffer fbo;
12615     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
12616     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
12617 
12618     drawQuad(program, "position", 0);
12619 
12620     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
12621 }
12622 
12623 // Validate that link fails with I/O block member name mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberNameMismatch)12624 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberNameMismatch)
12625 {
12626     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
12627 
12628     constexpr char kVS[] = R"(#version 310 es
12629 #extension GL_EXT_shader_io_blocks : require
12630 in highp vec4 position;
12631 out VSBlock { vec4 a; vec4 b[2]; } blockOut1;
12632 void main()
12633 {
12634     blockOut1.a = vec4(0);
12635     blockOut1.b[0] = vec4(0);
12636     blockOut1.b[1] = vec4(0);
12637     gl_Position = position;
12638 })";
12639 
12640     constexpr char kFS[] = R"(#version 310 es
12641 #extension GL_EXT_shader_io_blocks : require
12642 precision mediump float;
12643 layout(location = 0) out mediump vec4 color;
12644 in VSBlock { vec4 c; vec4 b[2]; } blockIn1;
12645 void main()
12646 {
12647     color = vec4(blockIn1.c.x, blockIn1.b[0].y, blockIn1.b[1].z, 1.0);
12648 })";
12649 
12650     GLuint program = CompileProgram(kVS, kFS);
12651     EXPECT_EQ(0u, program);
12652 }
12653 
12654 // Validate that link fails with I/O block member array size mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberArraySizeMismatch)12655 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberArraySizeMismatch)
12656 {
12657     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
12658 
12659     constexpr char kVS[] = R"(#version 310 es
12660 #extension GL_EXT_shader_io_blocks : require
12661 in highp vec4 position;
12662 out VSBlock { vec4 a; vec4 b[2]; } blockOut1;
12663 void main()
12664 {
12665     blockOut1.a = vec4(0);
12666     blockOut1.b[0] = vec4(0);
12667     blockOut1.b[1] = vec4(0);
12668     gl_Position = position;
12669 })";
12670 
12671     constexpr char kFS[] = R"(#version 310 es
12672 #extension GL_EXT_shader_io_blocks : require
12673 precision mediump float;
12674 layout(location = 0) out mediump vec4 color;
12675 in VSBlock { vec4 a; vec4 b[3]; } blockIn1;
12676 void main()
12677 {
12678     color = vec4(blockIn1.a.x, blockIn1.b[0].y, blockIn1.b[1].z, 1.0);
12679 })";
12680 
12681     GLuint program = CompileProgram(kVS, kFS);
12682     EXPECT_EQ(0u, program);
12683 }
12684 
12685 // Validate that link fails with I/O block member type mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberTypeMismatch)12686 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberTypeMismatch)
12687 {
12688     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
12689 
12690     constexpr char kVS[] = R"(#version 310 es
12691 #extension GL_EXT_shader_io_blocks : require
12692 in highp vec4 position;
12693 out VSBlock { vec4 a; vec4 b[2]; } blockOut1;
12694 void main()
12695 {
12696     blockOut1.a = vec4(0);
12697     blockOut1.b[0] = vec4(0);
12698     blockOut1.b[1] = vec4(0);
12699     gl_Position = position;
12700 })";
12701 
12702     constexpr char kFS[] = R"(#version 310 es
12703 #extension GL_EXT_shader_io_blocks : require
12704 precision mediump float;
12705 layout(location = 0) out mediump vec4 color;
12706 in VSBlock { vec3 a; vec4 b[2]; } blockIn1;
12707 void main()
12708 {
12709     color = vec4(blockIn1.a.x, blockIn1.b[0].y, blockIn1.b[1].z, 1.0);
12710 })";
12711 
12712     GLuint program = CompileProgram(kVS, kFS);
12713     EXPECT_EQ(0u, program);
12714 }
12715 
12716 // Validate that link fails with I/O block location mismatches
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkLocationMismatch)12717 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkLocationMismatch)
12718 {
12719     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
12720 
12721     constexpr char kVS[] = R"(#version 310 es
12722 #extension GL_EXT_shader_io_blocks : require
12723 in highp vec4 position;
12724 layout(location = 2) out VSBlock { vec4 a; vec4 b[2]; } blockOut1;
12725 void main()
12726 {
12727     blockOut1.a = vec4(0);
12728     blockOut1.b[0] = vec4(0);
12729     blockOut1.b[1] = vec4(0);
12730     gl_Position = position;
12731 })";
12732 
12733     constexpr char kFS[] = R"(#version 310 es
12734 #extension GL_EXT_shader_io_blocks : require
12735 precision mediump float;
12736 layout(location = 0) out mediump vec4 color;
12737 layout(location = 1) in VSBlock { vec4 a; vec4 b[2]; } blockIn1;
12738 void main()
12739 {
12740     color = vec4(blockIn1.a.x, blockIn1.b[0].y, blockIn1.b[1].z, 1.0);
12741 })";
12742 
12743     GLuint program = CompileProgram(kVS, kFS);
12744     EXPECT_EQ(0u, program);
12745 }
12746 
12747 // Validate that link fails with I/O block member location mismatches
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberLocationMismatch)12748 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberLocationMismatch)
12749 {
12750     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
12751 
12752     constexpr char kVS[] = R"(#version 310 es
12753 #extension GL_EXT_shader_io_blocks : require
12754 in highp vec4 position;
12755 out VSBlock { vec4 a; layout(location = 2) vec4 b[2]; } blockOut1;
12756 void main()
12757 {
12758     blockOut1.a = vec4(0);
12759     blockOut1.b[0] = vec4(0);
12760     blockOut1.b[1] = vec4(0);
12761     gl_Position = position;
12762 })";
12763 
12764     constexpr char kFS[] = R"(#version 310 es
12765 #extension GL_EXT_shader_io_blocks : require
12766 precision mediump float;
12767 layout(location = 0) out mediump vec4 color;
12768 in VSBlock { vec4 a; layout(location = 3) vec4 b[2]; } blockIn1;
12769 void main()
12770 {
12771     color = vec4(blockIn1.a.x, blockIn1.b[0].y, blockIn1.b[1].z, 1.0);
12772 })";
12773 
12774     GLuint program = CompileProgram(kVS, kFS);
12775     EXPECT_EQ(0u, program);
12776 }
12777 
12778 // Validate that link fails with I/O block member struct name mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberStructNameMismatch)12779 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberStructNameMismatch)
12780 {
12781     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
12782 
12783     constexpr char kVS[] = R"(#version 310 es
12784 #extension GL_EXT_shader_io_blocks : require
12785 in highp vec4 position;
12786 struct S1 { vec4 a; vec4 b[2]; };
12787 out VSBlock { S1 s; } blockOut1;
12788 void main()
12789 {
12790     blockOut1.s.a = vec4(0);
12791     blockOut1.s.b[0] = vec4(0);
12792     blockOut1.s.b[1] = vec4(0);
12793     gl_Position = position;
12794 })";
12795 
12796     constexpr char kFS[] = R"(#version 310 es
12797 #extension GL_EXT_shader_io_blocks : require
12798 precision mediump float;
12799 layout(location = 0) out mediump vec4 color;
12800 struct S2 { vec4 a; vec4 b[2]; };
12801 in VSBlock { S2 s; } blockIn1;
12802 void main()
12803 {
12804     color = vec4(blockIn1.s.a.x, blockIn1.s.b[0].y, blockIn1.s.b[1].z, 1.0);
12805 })";
12806 
12807     GLuint program = CompileProgram(kVS, kFS);
12808     EXPECT_EQ(0u, program);
12809 }
12810 
12811 // Validate that link fails with I/O block member struct member name mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberStructMemberNameMismatch)12812 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberStructMemberNameMismatch)
12813 {
12814     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
12815 
12816     constexpr char kVS[] = R"(#version 310 es
12817 #extension GL_EXT_shader_io_blocks : require
12818 in highp vec4 position;
12819 struct S { vec4 c; vec4 b[2]; };
12820 out VSBlock { S s; } blockOut1;
12821 void main()
12822 {
12823     blockOut1.s.c = vec4(0);
12824     blockOut1.s.b[0] = vec4(0);
12825     blockOut1.s.b[1] = vec4(0);
12826     gl_Position = position;
12827 })";
12828 
12829     constexpr char kFS[] = R"(#version 310 es
12830 #extension GL_EXT_shader_io_blocks : require
12831 precision mediump float;
12832 layout(location = 0) out mediump vec4 color;
12833 struct S { vec4 a; vec4 b[2]; };
12834 in VSBlock { S s; } blockIn1;
12835 void main()
12836 {
12837     color = vec4(blockIn1.s.a.x, blockIn1.s.b[0].y, blockIn1.s.b[1].z, 1.0);
12838 })";
12839 
12840     GLuint program = CompileProgram(kVS, kFS);
12841     EXPECT_EQ(0u, program);
12842 }
12843 
12844 // Validate that link fails with I/O block member struct member type mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberStructMemberTypeMismatch)12845 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberStructMemberTypeMismatch)
12846 {
12847     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
12848 
12849     constexpr char kVS[] = R"(#version 310 es
12850 #extension GL_EXT_shader_io_blocks : require
12851 in highp vec4 position;
12852 struct S { vec4 a; vec4 b[2]; };
12853 out VSBlock { S s; } blockOut1;
12854 void main()
12855 {
12856     blockOut1.s.a = vec4(0);
12857     blockOut1.s.b[0] = vec4(0);
12858     blockOut1.s.b[1] = vec4(0);
12859     gl_Position = position;
12860 })";
12861 
12862     constexpr char kFS[] = R"(#version 310 es
12863 #extension GL_EXT_shader_io_blocks : require
12864 precision mediump float;
12865 layout(location = 0) out mediump vec4 color;
12866 struct S { vec3 a; vec4 b[2]; };
12867 in VSBlock { S s; } blockIn1;
12868 void main()
12869 {
12870     color = vec4(blockIn1.s.a.x, blockIn1.s.b[0].y, blockIn1.s.b[1].z, 1.0);
12871 })";
12872 
12873     GLuint program = CompileProgram(kVS, kFS);
12874     EXPECT_EQ(0u, program);
12875 }
12876 
12877 // Validate that link fails with I/O block member struct member array size mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberStructMemberArraySizeMismatch)12878 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberStructMemberArraySizeMismatch)
12879 {
12880     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
12881 
12882     constexpr char kVS[] = R"(#version 310 es
12883 #extension GL_EXT_shader_io_blocks : require
12884 in highp vec4 position;
12885 struct S { vec4 a; vec4 b[3]; };
12886 out VSBlock { S s; } blockOut1;
12887 void main()
12888 {
12889     blockOut1.s.a = vec4(0);
12890     blockOut1.s.b[0] = vec4(0);
12891     blockOut1.s.b[1] = vec4(0);
12892     gl_Position = position;
12893 })";
12894 
12895     constexpr char kFS[] = R"(#version 310 es
12896 #extension GL_EXT_shader_io_blocks : require
12897 precision mediump float;
12898 layout(location = 0) out mediump vec4 color;
12899 struct S { vec4 a; vec4 b[2]; };
12900 in VSBlock { S s; } blockIn1;
12901 void main()
12902 {
12903     color = vec4(blockIn1.s.a.x, blockIn1.s.b[0].y, blockIn1.s.b[1].z, 1.0);
12904 })";
12905 
12906     GLuint program = CompileProgram(kVS, kFS);
12907     EXPECT_EQ(0u, program);
12908 }
12909 
12910 // Validate that link fails with I/O block member struct member count mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberStructMemberCountMismatch)12911 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberStructMemberCountMismatch)
12912 {
12913     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
12914 
12915     constexpr char kVS[] = R"(#version 310 es
12916 #extension GL_EXT_shader_io_blocks : require
12917 in highp vec4 position;
12918 struct S { vec4 a; vec4 b[2]; vec4 c; };
12919 out VSBlock { S s; } blockOut1;
12920 void main()
12921 {
12922     blockOut1.s.c = vec4(0);
12923     blockOut1.s.b[0] = vec4(0);
12924     blockOut1.s.b[1] = vec4(0);
12925     gl_Position = position;
12926 })";
12927 
12928     constexpr char kFS[] = R"(#version 310 es
12929 #extension GL_EXT_shader_io_blocks : require
12930 precision mediump float;
12931 layout(location = 0) out mediump vec4 color;
12932 struct S { vec4 a; vec4 b[2]; };
12933 in VSBlock { S s; } blockIn1;
12934 void main()
12935 {
12936     color = vec4(blockIn1.s.a.x, blockIn1.s.b[0].y, blockIn1.s.b[1].z, 1.0);
12937 })";
12938 
12939     GLuint program = CompileProgram(kVS, kFS);
12940     EXPECT_EQ(0u, program);
12941 }
12942 
12943 // Validate that link fails with I/O block member nested struct mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberNestedStructMismatch)12944 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberNestedStructMismatch)
12945 {
12946     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
12947 
12948     constexpr char kVS[] = R"(#version 310 es
12949 #extension GL_EXT_shader_io_blocks : require
12950 in highp vec4 position;
12951 struct S1 { vec4 c; vec4 b[2]; };
12952 struct S2 { S1 s; };
12953 struct S3 { S2 s; };
12954 out VSBlock { S3 s; } blockOut1;
12955 void main()
12956 {
12957     blockOut1.s.s.s.c = vec4(0);
12958     blockOut1.s.s.s.b[0] = vec4(0);
12959     blockOut1.s.s.s.b[1] = vec4(0);
12960     gl_Position = position;
12961 })";
12962 
12963     constexpr char kFS[] = R"(#version 310 es
12964 #extension GL_EXT_shader_io_blocks : require
12965 precision mediump float;
12966 layout(location = 0) out mediump vec4 color;
12967 struct S1 { vec4 a; vec4 b[2]; };
12968 struct S2 { S1 s; };
12969 struct S3 { S2 s; };
12970 in VSBlock { S3 s; } blockIn1;
12971 void main()
12972 {
12973     color = vec4(blockIn1.s.s.s.a.x, blockIn1.s.s.s.b[0].y, blockIn1.s.s.s.b[1].z, 1.0);
12974 })";
12975 
12976     GLuint program = CompileProgram(kVS, kFS);
12977     EXPECT_EQ(0u, program);
12978 }
12979 
12980 // Test that separating declarators works with structs that have been separately defined.
TEST_P(GLSLTest_ES31,SeparateDeclaratorsOfStructType)12981 TEST_P(GLSLTest_ES31, SeparateDeclaratorsOfStructType)
12982 {
12983     constexpr char kVS[] = R"(#version 310 es
12984 precision highp float;
12985 
12986 struct S
12987 {
12988     mat4 a;
12989     mat4 b;
12990 };
12991 
12992 S s1 = S(mat4(1), mat4(2)), s2[2][3], s3[2] = S[2](S(mat4(0), mat4(3)), S(mat4(4), mat4(5)));
12993 
12994 void main() {
12995     S s4[2][3] = s2, s5 = s3[0], s6[2] = S[2](s1, s5), s7 = s5;
12996 
12997     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);
12998 })";
12999 
13000     GLuint shader = glCreateShader(GL_VERTEX_SHADER);
13001 
13002     const char *sourceArray[1] = {kVS};
13003     GLint lengths[1]           = {static_cast<GLint>(sizeof(kVS) - 1)};
13004     glShaderSource(shader, 1, sourceArray, lengths);
13005     glCompileShader(shader);
13006 
13007     GLint compileResult;
13008     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
13009     EXPECT_NE(compileResult, 0);
13010 }
13011 
13012 // Test that separating declarators works with structs that are simultaneously defined.
TEST_P(GLSLTest_ES31,SeparateDeclaratorsOfStructTypeBeingSpecified)13013 TEST_P(GLSLTest_ES31, SeparateDeclaratorsOfStructTypeBeingSpecified)
13014 {
13015     constexpr char kVS[] = R"(#version 310 es
13016 precision highp float;
13017 
13018 struct S
13019 {
13020     mat4 a;
13021     mat4 b;
13022 } s1 = S(mat4(1), mat4(2)), s2[2][3], s3[2] = S[2](S(mat4(0), mat4(3)), S(mat4(4), mat4(5)));
13023 
13024 void main() {
13025     struct T
13026     {
13027         mat4 a;
13028         mat4 b;
13029     } s4[2][3], s5 = T(s3[0].a, s3[0].b), s6[2] = T[2](T(s1.a, s1.b), s5), s7 = s5;
13030 
13031     float f1 = s3[1].a[0].x, f2 = s2[0][2].b[1].y;
13032 
13033     gl_Position = vec4(f1, f2, s4[1][0].a[2].z, s6[0].b[3].w);
13034 })";
13035 
13036     GLuint shader = glCreateShader(GL_VERTEX_SHADER);
13037 
13038     const char *sourceArray[1] = {kVS};
13039     GLint lengths[1]           = {static_cast<GLint>(sizeof(kVS) - 1)};
13040     glShaderSource(shader, 1, sourceArray, lengths);
13041     glCompileShader(shader);
13042 
13043     GLint compileResult;
13044     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
13045     EXPECT_NE(compileResult, 0);
13046 }
13047 
13048 // Test that separating declarators works with structs that are simultaneously defined and that are
13049 // nameless.
TEST_P(GLSLTest_ES31,SeparateDeclaratorsOfNamelessStructType)13050 TEST_P(GLSLTest_ES31, SeparateDeclaratorsOfNamelessStructType)
13051 {
13052     constexpr char kVS[] = R"(#version 310 es
13053 precision highp float;
13054 
13055 struct
13056 {
13057     mat4 a;
13058     mat4 b;
13059 } s1, s2[2][3], s3[2];
13060 
13061 void main() {
13062     struct
13063     {
13064         mat4 a;
13065         mat4 b;
13066     } s4[2][3], s5, s6[2], s7 = s5;
13067 
13068     float f1 = s1.a[0].x + s3[1].a[0].x, f2 = s2[0][2].b[1].y + s7.b[1].z;
13069 
13070     gl_Position = vec4(f1, f2, s4[1][0].a[2].z, s6[0].b[3].w);
13071 })";
13072 
13073     GLuint shader = glCreateShader(GL_VERTEX_SHADER);
13074 
13075     const char *sourceArray[1] = {kVS};
13076     GLint lengths[1]           = {static_cast<GLint>(sizeof(kVS) - 1)};
13077     glShaderSource(shader, 1, sourceArray, lengths);
13078     glCompileShader(shader);
13079 
13080     GLint compileResult;
13081     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
13082     EXPECT_NE(compileResult, 0);
13083 }
13084 
13085 // Regression test for transformation bug which separates struct declarations from uniform
13086 // declarations.  The bug was that the uniform variable usage in the initializer of a new
13087 // declaration (y below) was not being processed.
TEST_P(GLSLTest,UniformStructBug)13088 TEST_P(GLSLTest, UniformStructBug)
13089 {
13090     constexpr char kVS[] = R"(precision highp float;
13091 
13092 uniform struct Global
13093 {
13094     float x;
13095 } u_global;
13096 
13097 void main() {
13098   float y = u_global.x;
13099 
13100   gl_Position = vec4(y);
13101 })";
13102 
13103     GLuint shader = glCreateShader(GL_VERTEX_SHADER);
13104 
13105     const char *sourceArray[1] = {kVS};
13106     GLint lengths[1]           = {static_cast<GLint>(sizeof(kVS) - 1)};
13107     glShaderSource(shader, 1, sourceArray, lengths);
13108     glCompileShader(shader);
13109 
13110     GLint compileResult;
13111     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
13112     EXPECT_NE(compileResult, 0);
13113 }
13114 
13115 // Regression test for transformation bug which separates struct declarations from uniform
13116 // declarations.  The bug was that the arrayness of the declaration was not being applied to the
13117 // replaced uniform variable.
TEST_P(GLSLTest_ES31,UniformStructBug2)13118 TEST_P(GLSLTest_ES31, UniformStructBug2)
13119 {
13120     constexpr char kVS[] = R"(#version 310 es
13121 precision highp float;
13122 
13123 uniform struct Global
13124 {
13125     float x;
13126 } u_global[2][3];
13127 
13128 void main() {
13129   float y = u_global[0][0].x;
13130 
13131   gl_Position = vec4(y);
13132 })";
13133 
13134     GLuint shader = glCreateShader(GL_VERTEX_SHADER);
13135 
13136     const char *sourceArray[1] = {kVS};
13137     GLint lengths[1]           = {static_cast<GLint>(sizeof(kVS) - 1)};
13138     glShaderSource(shader, 1, sourceArray, lengths);
13139     glCompileShader(shader);
13140 
13141     GLint compileResult;
13142     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
13143     EXPECT_NE(compileResult, 0);
13144 }
13145 
13146 // Regression test based on fuzzer issue resulting in an AST validation failure.  Struct definition
13147 // was not found in the tree.  Tests that struct declaration in function return value is visible to
13148 // instantiations later on.
TEST_P(GLSLTest,MissingStructDeclarationBug)13149 TEST_P(GLSLTest, MissingStructDeclarationBug)
13150 {
13151     constexpr char kVS[] = R"(
13152 struct S
13153 {
13154     vec4 i;
13155 } p();
13156 void main()
13157 {
13158     S s;
13159 })";
13160 
13161     GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
13162     EXPECT_NE(0u, shader);
13163     glDeleteShader(shader);
13164 }
13165 
13166 // Regression test based on fuzzer issue resulting in an AST validation failure.  Struct definition
13167 // was not found in the tree.  Tests that struct declaration in function return value is visible to
13168 // other struct declarations.
TEST_P(GLSLTest,MissingStructDeclarationBug2)13169 TEST_P(GLSLTest, MissingStructDeclarationBug2)
13170 {
13171     constexpr char kVS[] = R"(
13172 struct T
13173 {
13174     vec4 I;
13175 } p();
13176 struct
13177 {
13178     T c;
13179 };
13180 void main()
13181 {
13182 })";
13183 
13184     GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
13185     EXPECT_NE(0u, shader);
13186     glDeleteShader(shader);
13187 }
13188 
13189 // Regression test for bug in HLSL code generation where the for loop init expression was expected
13190 // to always have an initializer.
TEST_P(GLSLTest,HandleExcessiveLoopBug)13191 TEST_P(GLSLTest, HandleExcessiveLoopBug)
13192 {
13193     constexpr char kVS[] = R"(void main(){for(int i;i>6;);})";
13194 
13195     GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
13196     EXPECT_NE(0u, shader);
13197     glDeleteShader(shader);
13198 }
13199 
13200 // Regression test for a validation bug in the translator where func(void, int) was accepted even
13201 // though it's illegal, and the function was callable as if the void parameter isn't there.
TEST_P(GLSLTest,NoParameterAfterVoid)13202 TEST_P(GLSLTest, NoParameterAfterVoid)
13203 {
13204     constexpr char kVS[] = R"(void f(void, int a){}
13205 void main(){f(1);})";
13206 
13207     GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
13208     EXPECT_EQ(0u, shader);
13209     glDeleteShader(shader);
13210 }
13211 
13212 // Similar to NoParameterAfterVoid, but tests func(void, void).
TEST_P(GLSLTest,NoParameterAfterVoid2)13213 TEST_P(GLSLTest, NoParameterAfterVoid2)
13214 {
13215     constexpr char kVS[] = R"(void f(void, void){}
13216 void main(){f();})";
13217 
13218     GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
13219     EXPECT_EQ(0u, shader);
13220     glDeleteShader(shader);
13221 }
13222 
13223 // Test that providing more components to a matrix constructor than necessary works.  Based on a
13224 // clusterfuzz test that caught an OOB array write in glslang.
TEST_P(GLSLTest,MatrixConstructor)13225 TEST_P(GLSLTest, MatrixConstructor)
13226 {
13227     constexpr char kVS[] = R"(attribute vec4 aPosition;
13228 varying vec4 vColor;
13229 void main()
13230 {
13231     gl_Position = aPosition;
13232     vec4 color = vec4(aPosition.xy, 0, 1);
13233     mat4 m4 = mat4(color, color.yzwx, color.zwx, color.zwxy, color.wxyz);
13234     vColor = m4[0];
13235 })";
13236 
13237     GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
13238     EXPECT_NE(0u, shader);
13239     glDeleteShader(shader);
13240 }
13241 
13242 // Test that scalar(nonScalar) constructors work.
TEST_P(GLSLTest_ES3,ScalarConstructor)13243 TEST_P(GLSLTest_ES3, ScalarConstructor)
13244 {
13245     constexpr char kFS[] = R"(#version 300 es
13246 precision mediump float;
13247 uniform vec4 u;
13248 out vec4 color;
13249 void main()
13250 {
13251     float f1 = float(u);
13252     mat3 m = mat3(u, u, u);
13253     int i = int(m);
13254     color = vec4(f1, float(i), 0, 1);
13255 })";
13256 
13257     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
13258     glUseProgram(program);
13259 
13260     GLint uloc = glGetUniformLocation(program, "u");
13261     ASSERT_NE(uloc, -1);
13262     glUniform4f(uloc, 1.0, 0.4, 0.2, 0.7);
13263 
13264     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
13265     EXPECT_GL_NO_ERROR();
13266 
13267     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
13268 }
13269 
13270 // Test that initializing global variables with non-constant values work
TEST_P(GLSLTest_ES3,InitGlobalNonConstant)13271 TEST_P(GLSLTest_ES3, InitGlobalNonConstant)
13272 {
13273     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_non_constant_global_initializers"));
13274 
13275     constexpr char kVS[] = R"(#version 300 es
13276 #extension GL_EXT_shader_non_constant_global_initializers : require
13277 uniform vec4 u;
13278 out vec4 color;
13279 
13280 vec4 global1 = u;
13281 vec4 global2 = u + vec4(1);
13282 vec4 global3 = global1 * global2;
13283 void main()
13284 {
13285     color = global3;
13286 })";
13287 
13288     GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
13289     EXPECT_NE(0u, shader);
13290     glDeleteShader(shader);
13291 }
13292 
13293 // Test that initializing global variables with complex constants work
TEST_P(GLSLTest_ES3,InitGlobalComplexConstant)13294 TEST_P(GLSLTest_ES3, InitGlobalComplexConstant)
13295 {
13296     constexpr char kFS[] = R"(#version 300 es
13297 precision highp float;
13298 out vec4 color;
13299 
13300 struct T
13301 {
13302     float f;
13303 };
13304 
13305 struct S
13306 {
13307     vec4 v;
13308     mat3x4 m[2];
13309     T t;
13310 };
13311 
13312 S s = S(
13313         vec4(0, 1, 2, 3),
13314         mat3x4[2](
13315                   mat3x4(
13316                          vec4(4, 5, 6, 7),
13317                          vec4(8, 9, 10, 11),
13318                          vec4(12, 13, 14, 15)
13319                   ),
13320                   mat3x4(
13321                          vec4(16, 17, 18, 19),
13322                          vec4(20, 21, 22, 23),
13323                          vec4(24, 25, 26, 27)
13324                   )
13325         ),
13326         T(28.0)
13327        );
13328 
13329 void main()
13330 {
13331     vec4 result = vec4(0, 1, 0, 1);
13332 
13333     if (s.v != vec4(0, 1, 2, 3))
13334         result = vec4(1, 0, 0, 0);
13335 
13336     for (int index = 0; index < 2; ++index)
13337     {
13338         for (int column = 0; column < 3; ++column)
13339         {
13340             int expect = index * 12 + column * 4 + 4;
13341             if (s.m[index][column] != vec4(expect, expect + 1, expect + 2, expect + 3))
13342                 result = vec4(float(index + 1) / 2.0, 0, float(column + 1) / 3.0, 1);
13343         }
13344     }
13345 
13346     if (s.t.f != 28.0)
13347         result = vec4(0, 0, 1, 0);
13348 
13349     color = result;
13350 })";
13351 
13352     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
13353 
13354     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
13355     EXPECT_GL_NO_ERROR();
13356 
13357     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
13358 }
13359 
13360 // Test that built-ins with out parameters work
TEST_P(GLSLTest_ES31,BuiltInsWithOutParameters)13361 TEST_P(GLSLTest_ES31, BuiltInsWithOutParameters)
13362 {
13363     constexpr char kFS[] = R"(#version 310 es
13364 precision highp float;
13365 precision highp int;
13366 
13367 out vec4 color;
13368 
13369 uniform float f;    // = 3.41
13370 uniform uvec4 u1;   // = 0xFEDCBA98, 0x13579BDF, 0xFEDCBA98, 0x13579BDF
13371 uniform uvec4 u2;   // = 0xECA86420, 0x12345678, 0x12345678, 0xECA86420
13372 
13373 struct S
13374 {
13375     float fvalue;
13376     int ivalues[2];
13377     uvec4 uvalues[3];
13378 };
13379 
13380 struct T
13381 {
13382     S s[2];
13383 };
13384 
13385 void main()
13386 {
13387     float integer;
13388     float fraction = modf(f, integer);
13389 
13390     T t;
13391 
13392     t.s[0].fvalue     = frexp(f, t.s[0].ivalues[0]);
13393     float significand = t.s[0].fvalue;
13394     int exponent      = t.s[0].ivalues[0];
13395 
13396     t.s[0].uvalues[0] = uaddCarry(u1, u2, t.s[0].uvalues[1].yxwz);
13397     uvec4 addResult   = t.s[0].uvalues[0];
13398     uvec4 addCarry    = t.s[0].uvalues[1].yxwz;
13399 
13400     t.s[0].uvalues[2].wx = usubBorrow(u1.wx, u2.wx, t.s[1].uvalues[0].wx);
13401     uvec2 subResult      = t.s[0].uvalues[2].wx;
13402     uvec2 subBorrow      = t.s[1].uvalues[0].wx;
13403 
13404     umulExtended(u1, u2, t.s[1].uvalues[1], t.s[1].uvalues[2]);
13405     uvec4 mulMsb = t.s[1].uvalues[1];
13406     uvec4 mulLsb = t.s[1].uvalues[2];
13407 
13408     ivec2 imulMsb, imulLsb;
13409     imulExtended(ivec2(u1.wz), ivec2(u2.wz), imulMsb.yx, imulLsb.yx);
13410 
13411     bool modfPassed = abs(fraction - 0.41) < 0.0001 && integer == 3.0;
13412     bool frexpPassed = abs(significand - 0.8525) < 0.0001 && exponent == 2;
13413     bool addPassed =
13414         addResult == uvec4(0xEB851EB8, 0x258BF257, 0x11111110, 0xFFFFFFFF) &&
13415         addCarry == uvec4(1, 0, 1, 0);
13416     bool subPassed = subResult == uvec2(0x26AF37BF, 0x12345678) && subBorrow == uvec2(1, 0);
13417     bool mulPassed =
13418         mulMsb == uvec4(0xEB9B208C, 0x01601D49, 0x121FA00A, 0x11E17CC0) &&
13419         mulLsb == uvec4(0xA83AB300, 0xD6B9FA88, 0x35068740, 0x822E97E0);
13420     bool imulPassed =
13421         imulMsb == ivec2(0xFFEB4992, 0xFE89E0E1) &&
13422         imulLsb == ivec2(0x35068740, 0x822E97E0);
13423 
13424     color = vec4(modfPassed ? 1 : 0,
13425                  frexpPassed ? 1 : 0,
13426                  (addPassed ? 0.4 : 0.0) + (subPassed ? 0.6 : 0.0),
13427                  (mulPassed ? 0.4 : 0.0) + (imulPassed ? 0.6 : 0.0));
13428 })";
13429 
13430     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
13431     glUseProgram(program);
13432 
13433     GLint floc  = glGetUniformLocation(program, "f");
13434     GLint u1loc = glGetUniformLocation(program, "u1");
13435     GLint u2loc = glGetUniformLocation(program, "u2");
13436     ASSERT_NE(floc, -1);
13437     ASSERT_NE(u1loc, -1);
13438     ASSERT_NE(u2loc, -1);
13439     glUniform1f(floc, 3.41);
13440     glUniform4ui(u1loc, 0xFEDCBA98u, 0x13579BDFu, 0xFEDCBA98u, 0x13579BDFu);
13441     glUniform4ui(u2loc, 0xECA86420u, 0x12345678u, 0x12345678u, 0xECA86420u);
13442 
13443     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
13444     EXPECT_GL_NO_ERROR();
13445 
13446     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
13447 }
13448 
13449 // Test that interpolateAt* work with swizzle.  This test is disabled as swizzled interpolants are
13450 // only allowed in desktop GLSL.
TEST_P(GLSLTest_ES31,InterpolateAtWithSwizzle)13451 TEST_P(GLSLTest_ES31, InterpolateAtWithSwizzle)
13452 {
13453     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_multisample_interpolation"));
13454 
13455     constexpr char kVS[] = R"(#version 310 es
13456 
13457 out vec4 interpolant;
13458 
13459 void main()
13460 {
13461     // The following triangle is being drawn over the framebuffer.
13462     //
13463     //   (-1,3) |\
13464     //          |   \
13465     //          |      \
13466     //          |         \
13467     //          |            \
13468     //          +--------------+
13469     //          |              | \
13470     //          |              |    \
13471     //          | Framebuffer  |       \
13472     //          |              |          \
13473     //          |              |             \
13474     //  (-1,-1) +--------------+--------------- (3,-1)
13475     //
13476     // Interpolant is set such that interpolateAtCentroid would produce the desired value for
13477     // position == (0, 0), and interpolateAtOffset(0.5, -0.5) for position == (1,-1)
13478     if (gl_VertexID == 0)
13479     {
13480         gl_Position = vec4(-1, -1, 0, 1);
13481         interpolant = vec4(1.5, 0.5, 0, 0);
13482     }
13483     else if (gl_VertexID == 1)
13484     {
13485         gl_Position = vec4(3, -1, 0, 1);
13486         interpolant = vec4(0, 0, 1, 2);
13487     }
13488     else
13489     {
13490         gl_Position = vec4(-1, 3, 0, 1);
13491         interpolant = vec4(0, 1, -1, 2);
13492     }
13493 })";
13494 
13495     constexpr char kFS[] = R"(#version 310 es
13496 #extension GL_OES_shader_multisample_interpolation : require
13497 precision highp float;
13498 
13499 in vec4 interpolant;
13500 out vec4 color;
13501 
13502 void main()
13503 {
13504     // Should result in (0.75, 1.0)
13505     vec2 atCentroid = interpolateAtCentroid(interpolant.xw);
13506     // Selecting the bottom-right corner, this should result in (0.5, 0.25), but interpolateAtOffset
13507     // doesn't make guarantees regarding the range and granularity of the offset.  The interpolant
13508     // is given values such that the bottom-left/top-right diagonal is interpolated to a constant
13509     // value of (0, 0.5).  The top-left corner has the value (-0.5, 0.75).  We therefore make a
13510     // coarse test to make sure that atOffset.x > 0 and atOffset.y < 0.5, thus ensuring at least
13511     // that the offset is in the correct half of the pixel.
13512     vec2 atOffset = interpolateAtOffset(interpolant.zy, vec2(0.5, -0.5));
13513 
13514     color = vec4(atCentroid, atOffset.x > 0.0 ? 1 : 0, atOffset.y < 0.5 ? 1 : 0);
13515 })";
13516 
13517     GLRenderbuffer rbo;
13518     glBindRenderbuffer(GL_RENDERBUFFER, rbo);
13519     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
13520 
13521     GLFramebuffer fbo;
13522     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
13523     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
13524     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
13525 
13526     ANGLE_GL_PROGRAM(program, kVS, kFS);
13527     glUseProgram(program);
13528 
13529     glViewport(0, 0, 1, 1);
13530     glDrawArrays(GL_TRIANGLES, 0, 3);
13531     EXPECT_GL_NO_ERROR();
13532 
13533     EXPECT_PIXEL_NEAR(0, 0, 191, 255, 255, 255, 1);
13534 }
13535 
13536 class GLSLTestLoops : public GLSLTest
13537 {
13538   protected:
runTest(const char * fs)13539     void runTest(const char *fs)
13540     {
13541         ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fs);
13542 
13543         drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
13544         EXPECT_GL_NO_ERROR();
13545 
13546         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
13547     }
13548 };
13549 
13550 // Test basic for loops
TEST_P(GLSLTestLoops,BasicFor)13551 TEST_P(GLSLTestLoops, BasicFor)
13552 {
13553     constexpr char kFS[] = R"(#version 300 es
13554 precision mediump float;
13555 out vec4 color;
13556 
13557 void main()
13558 {
13559     int result = 0;
13560     for (int i = 0; i < 10; ++i)
13561         for (int j = 0; j < 8; ++j)
13562         {
13563             for (int k = 0; k < 2; ++k, ++j) ++result;
13564             for (int k = 0; k < 3; ++k)      ++result;
13565             for (int k = 0; k < 0; ++k)      ++result;
13566         }
13567 
13568     color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
13569 })";
13570 
13571     runTest(kFS);
13572 }
13573 
13574 // Test for loop without condition
TEST_P(GLSLTestLoops,ForNoCondition)13575 TEST_P(GLSLTestLoops, ForNoCondition)
13576 {
13577     constexpr char kFS[] = R"(#version 300 es
13578 precision mediump float;
13579 out vec4 color;
13580 
13581 void main()
13582 {
13583     int result = 0;
13584     for (int i = 0; i < 10; ++i)
13585         for (int j = 0; ; ++j)
13586         {
13587             for (int k = 0; k < 2; ++k, ++j) ++result;
13588             for (int k = 0; k < 3; ++k)      ++result;
13589             for (int k = 0; k < 0; ++k)      ++result;
13590 
13591             if (j >= 8)
13592                 break;
13593         }
13594 
13595     color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
13596 })";
13597 
13598     runTest(kFS);
13599 }
13600 
13601 // Test for loop without init and expression
TEST_P(GLSLTestLoops,ForNoInitConditionOrExpression)13602 TEST_P(GLSLTestLoops, ForNoInitConditionOrExpression)
13603 {
13604     constexpr char kFS[] = R"(#version 300 es
13605 precision mediump float;
13606 out vec4 color;
13607 
13608 void main()
13609 {
13610     int result = 0;
13611     for (int i = 0; i < 10; ++i)
13612     {
13613         int j = 0;
13614         for (;;)
13615         {
13616             for (int k = 0; k < 2; ++k, ++j) ++result;
13617             for (int k = 0; k < 3; ++k)      ++result;
13618             for (int k = 0; k < 0; ++k)      ++result;
13619 
13620             if (j >= 8)
13621                 break;
13622             ++j;
13623         }
13624     }
13625 
13626     color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
13627 })";
13628 
13629     runTest(kFS);
13630 }
13631 
13632 // Test for loop with continue
TEST_P(GLSLTestLoops,ForContinue)13633 TEST_P(GLSLTestLoops, ForContinue)
13634 {
13635     constexpr char kFS[] = R"(#version 300 es
13636 precision mediump float;
13637 out vec4 color;
13638 
13639 void main()
13640 {
13641     int result = 0;
13642     for (int i = 0; i < 10; ++i)
13643         for (int j = 0; j < 8; ++j)
13644         {
13645             for (int k = 0; k < 2; ++k, ++j) ++result;
13646             for (int k = 0; k < 3; ++k)      ++result;
13647             if (i > 3)
13648                 continue;
13649             for (int k = 0; k < 0; ++k)      ++result;
13650         }
13651 
13652     color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
13653 })";
13654 
13655     runTest(kFS);
13656 }
13657 
13658 // Test for loop with continue at the end of block
TEST_P(GLSLTestLoops,ForUnconditionalContinue)13659 TEST_P(GLSLTestLoops, ForUnconditionalContinue)
13660 {
13661     constexpr char kFS[] = R"(#version 300 es
13662 precision mediump float;
13663 out vec4 color;
13664 
13665 void main()
13666 {
13667     int result = 0;
13668     for (int i = 0; i < 10; ++i)
13669         for (int j = 0; j < 8; ++j)
13670         {
13671             for (int k = 0; k < 2; ++k, ++j) ++result;
13672             for (int k = 0; k < 3; ++k)      ++result;
13673             for (int k = 0; k < 0; ++k)      ++result;
13674             continue;
13675         }
13676 
13677     color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
13678 })";
13679 
13680     runTest(kFS);
13681 }
13682 
13683 // Test for loop with break at the end of block
TEST_P(GLSLTestLoops,ForUnconditionalBreak)13684 TEST_P(GLSLTestLoops, ForUnconditionalBreak)
13685 {
13686     constexpr char kFS[] = R"(#version 300 es
13687 precision mediump float;
13688 out vec4 color;
13689 
13690 void main()
13691 {
13692     int result = 0;
13693     for (int i = 0; i < 10; ++i)
13694         for (int j = 0; j < 8; ++j)
13695         {
13696             for (int k = 0; k < 2; ++k, ++j) ++result;
13697             for (int k = 0; k < 3; ++k)      ++result;
13698             for (int k = 0; k < 0; ++k)      ++result;
13699             break;
13700         }
13701 
13702     color = result == 50 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
13703 })";
13704 
13705     runTest(kFS);
13706 }
13707 
13708 // Test for loop with break and continue
TEST_P(GLSLTestLoops,ForBreakContinue)13709 TEST_P(GLSLTestLoops, ForBreakContinue)
13710 {
13711     constexpr char kFS[] = R"(#version 300 es
13712 precision mediump float;
13713 out vec4 color;
13714 
13715 void main()
13716 {
13717     int result = 0;
13718     for (int i = 0; i < 10; ++i)
13719         for (int j = 0; j < 8; ++j)
13720         {
13721             if (j < 2) continue;
13722             if (j > 6) break;
13723             if (i < 3) continue;
13724             if (i > 8) break;
13725             ++result;
13726         }
13727 
13728     color = result == 30 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
13729 })";
13730 
13731     runTest(kFS);
13732 }
13733 
13734 // Test basic while loops
TEST_P(GLSLTestLoops,BasicWhile)13735 TEST_P(GLSLTestLoops, BasicWhile)
13736 {
13737     constexpr char kFS[] = R"(#version 300 es
13738 precision mediump float;
13739 out vec4 color;
13740 
13741 void main()
13742 {
13743     int result = 0;
13744     int i = 0;
13745     while (i < 10)
13746     {
13747         int j = 0;
13748         while (j < 8)
13749         {
13750             int k = 0;
13751             while (k < 2) { ++result; ++k; ++j; }
13752             while (k < 5) { ++result; ++k; }
13753             while (k < 4) { ++result; }
13754             ++j;
13755         }
13756         ++i;
13757     }
13758 
13759     color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
13760 })";
13761 
13762     runTest(kFS);
13763 }
13764 
13765 // Test while loops with continue
TEST_P(GLSLTestLoops,WhileContinue)13766 TEST_P(GLSLTestLoops, WhileContinue)
13767 {
13768     constexpr char kFS[] = R"(#version 300 es
13769 precision mediump float;
13770 out vec4 color;
13771 
13772 void main()
13773 {
13774     int result = 0;
13775     int i = 0;
13776     while (i < 10)
13777     {
13778         int j = 0;
13779         while (j < 8)
13780         {
13781             int k = 0;
13782             while (k < 2) { ++result; ++k; ++j; }
13783             while (k < 5) { ++result; ++k; }
13784             if (i > 3)
13785             {
13786                 ++j;
13787                 continue;
13788             }
13789             while (k < 4) { ++result; }
13790             ++j;
13791         }
13792         ++i;
13793     }
13794 
13795     color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
13796 })";
13797 
13798     runTest(kFS);
13799 }
13800 
13801 // Test while loops with continue at the end of block
TEST_P(GLSLTestLoops,WhileUnconditionalContinue)13802 TEST_P(GLSLTestLoops, WhileUnconditionalContinue)
13803 {
13804     constexpr char kFS[] = R"(#version 300 es
13805 precision mediump float;
13806 out vec4 color;
13807 
13808 void main()
13809 {
13810     int result = 0;
13811     int i = 0;
13812     while (i < 10)
13813     {
13814         int j = 0;
13815         while (j < 8)
13816         {
13817             int k = 0;
13818             while (k < 2) { ++result; ++k; ++j; }
13819             while (k < 5) { ++result; ++k; }
13820             while (k < 4) { ++result; }
13821             ++j;
13822             continue;
13823         }
13824         ++i;
13825     }
13826 
13827     color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
13828 })";
13829 
13830     runTest(kFS);
13831 }
13832 
13833 // Test while loops with break
TEST_P(GLSLTestLoops,WhileBreak)13834 TEST_P(GLSLTestLoops, WhileBreak)
13835 {
13836     constexpr char kFS[] = R"(#version 300 es
13837 precision mediump float;
13838 out vec4 color;
13839 
13840 void main()
13841 {
13842     int result = 0;
13843     int i = 0;
13844     while (i < 10)
13845     {
13846         int j = 0;
13847         while (true)
13848         {
13849             int k = 0;
13850             while (k < 2) { ++result; ++k; ++j; }
13851             while (k < 5) { ++result; ++k; }
13852             while (k < 4) { ++result; }
13853             ++j;
13854             if (j >= 8)
13855                 break;
13856         }
13857         ++i;
13858     }
13859 
13860     color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
13861 })";
13862 
13863     runTest(kFS);
13864 }
13865 
13866 // Test while loops with continue at the end of block
TEST_P(GLSLTestLoops,WhileUnconditionalBreak)13867 TEST_P(GLSLTestLoops, WhileUnconditionalBreak)
13868 {
13869     constexpr char kFS[] = R"(#version 300 es
13870 precision mediump float;
13871 out vec4 color;
13872 
13873 void main()
13874 {
13875     int result = 0;
13876     int i = 0;
13877     while (i < 10)
13878     {
13879         int j = 0;
13880         while (j < 8)
13881         {
13882             int k = 0;
13883             while (k < 2) { ++result; ++k; ++j; }
13884             while (k < 5) { ++result; ++k; }
13885             while (k < 4) { ++result; }
13886             ++j;
13887             break;
13888         }
13889         ++i;
13890     }
13891 
13892     color = result == 50 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
13893 })";
13894 
13895     runTest(kFS);
13896 }
13897 
13898 // Test basic do-while loops
TEST_P(GLSLTestLoops,BasicDoWhile)13899 TEST_P(GLSLTestLoops, BasicDoWhile)
13900 {
13901     constexpr char kFS[] = R"(#version 300 es
13902 precision mediump float;
13903 out vec4 color;
13904 
13905 void main()
13906 {
13907     int result = 0;
13908     int i = 0;
13909     do
13910     {
13911         int j = 0;
13912         do
13913         {
13914             int k = 0;
13915             do { ++result; ++k; ++j; } while (k < 2);
13916             do { ++result; ++k;      } while (k < 5);
13917             do { ++result;           } while (k < 3);
13918             ++j;
13919         } while (j < 8);
13920         ++i;
13921     } while (i < 10);
13922 
13923     color = result == 180 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
13924 })";
13925 
13926     runTest(kFS);
13927 }
13928 
13929 // Test do-while loops with continue
TEST_P(GLSLTestLoops,DoWhileContinue)13930 TEST_P(GLSLTestLoops, DoWhileContinue)
13931 {
13932     constexpr char kFS[] = R"(#version 300 es
13933 precision mediump float;
13934 out vec4 color;
13935 
13936 void main()
13937 {
13938     int result = 0;
13939     int i = 0;
13940     do
13941     {
13942         int j = 0;
13943         do
13944         {
13945             int k = 0;
13946             do { ++result; ++k; ++j; } while (k < 2);
13947             if (i > 3)
13948             {
13949                 ++j;
13950                 continue;
13951             }
13952             do { ++result; ++k;      } while (k < 5);
13953             do { ++result;           } while (k < 3);
13954             ++j;
13955         } while (j < 8);
13956         ++i;
13957     } while (i < 10);
13958 
13959     color = result == 108 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
13960 })";
13961 
13962     runTest(kFS);
13963 }
13964 
13965 // Test do-while loops with continue at the end of block
TEST_P(GLSLTestLoops,DoWhileUnconditionalContinue)13966 TEST_P(GLSLTestLoops, DoWhileUnconditionalContinue)
13967 {
13968     constexpr char kFS[] = R"(#version 300 es
13969 precision mediump float;
13970 out vec4 color;
13971 
13972 void main()
13973 {
13974     int result = 0;
13975     int i = 0;
13976     do
13977     {
13978         int j = 0;
13979         do
13980         {
13981             int k = 0;
13982             do { ++result; ++k; ++j; continue; } while (k < 2);
13983             do { ++result; ++k;      continue; } while (k < 5);
13984             do { ++result;           continue; } while (k < 3);
13985             ++j;
13986         } while (j < 8);
13987         ++i;
13988     } while (i < 10);
13989 
13990     color = result == 180 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
13991 })";
13992 
13993     runTest(kFS);
13994 }
13995 
13996 // Test do-while loops with break
TEST_P(GLSLTestLoops,DoWhileBreak)13997 TEST_P(GLSLTestLoops, DoWhileBreak)
13998 {
13999     constexpr char kFS[] = R"(#version 300 es
14000 precision mediump float;
14001 out vec4 color;
14002 
14003 void main()
14004 {
14005     int result = 0;
14006     int i = 0;
14007     do
14008     {
14009         int j = 0;
14010         do
14011         {
14012             int k = 0;
14013             do { ++result; ++k; ++j; } while (k < 2);
14014             do { ++result; ++k;      } while (k < 5);
14015             do { ++result;           } while (k < 3);
14016             ++j;
14017             if (j >= 8)
14018                 break;
14019         } while (true);
14020         ++i;
14021     } while (i < 10);
14022 
14023     color = result == 180 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
14024 })";
14025 
14026     runTest(kFS);
14027 }
14028 
14029 // Test do-while loops with break at the end of block
TEST_P(GLSLTestLoops,DoWhileUnconditionalBreak)14030 TEST_P(GLSLTestLoops, DoWhileUnconditionalBreak)
14031 {
14032     constexpr char kFS[] = R"(#version 300 es
14033 precision mediump float;
14034 out vec4 color;
14035 
14036 void main()
14037 {
14038     int result = 0;
14039     int i = 0;
14040     do
14041     {
14042         int j = 0;
14043         do
14044         {
14045             int k = 0;
14046             do { ++result; ++k; ++j; break; } while (k < 2);
14047             do { ++result; ++k;      break; } while (k < 5);
14048             do { ++result;           break; } while (k < 3);
14049             ++j;
14050         } while (j < 8);
14051         ++i;
14052     } while (i < 10);
14053 
14054     color = result == 120 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
14055 })";
14056 
14057     runTest(kFS);
14058 }
14059 
14060 // Test for loop with continue inside switch.
TEST_P(GLSLTestLoops,ForContinueInSwitch)14061 TEST_P(GLSLTestLoops, ForContinueInSwitch)
14062 {
14063     constexpr char kFS[] = R"(#version 300 es
14064 precision mediump float;
14065 out vec4 color;
14066 
14067 void main()
14068 {
14069     int result = 0;
14070     for (int i = 0; i < 10; ++i)
14071         for (int j = 0; j < 8; ++j)
14072         {
14073             switch (j)
14074             {
14075                 case 2:
14076                 case 3:
14077                 case 4:
14078                     ++result;
14079                     // fallthrough
14080                 case 5:
14081                 case 6:
14082                     ++result;
14083                     break;
14084                 default:
14085                     continue;
14086             }
14087         }
14088 
14089     color = result == 80 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
14090 })";
14091 
14092     runTest(kFS);
14093 }
14094 
14095 // Test while loop with continue inside switch
TEST_P(GLSLTestLoops,WhileContinueInSwitch)14096 TEST_P(GLSLTestLoops, WhileContinueInSwitch)
14097 {
14098     constexpr char kFS[] = R"(#version 300 es
14099 precision mediump float;
14100 out vec4 color;
14101 
14102 void main()
14103 {
14104     int result = 0;
14105     int i = 0;
14106     while (i < 10)
14107     {
14108         int j = 0;
14109         while (j < 8)
14110         {
14111             switch (j)
14112             {
14113                 case 2:
14114                 default:
14115                 case 3:
14116                 case 4:
14117                     ++j;
14118                     ++result;
14119                     continue;
14120                 case 0:
14121                 case 1:
14122                 case 7:
14123                     break;
14124             }
14125             ++j;
14126         }
14127         ++i;
14128     }
14129 
14130     color = result == 50 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
14131 })";
14132 
14133     runTest(kFS);
14134 }
14135 
14136 // Test do-while loops with continue in switch
TEST_P(GLSLTestLoops,DoWhileContinueInSwitch)14137 TEST_P(GLSLTestLoops, DoWhileContinueInSwitch)
14138 {
14139     constexpr char kFS[] = R"(#version 300 es
14140 precision mediump float;
14141 out vec4 color;
14142 
14143 void main()
14144 {
14145     int result = 0;
14146     int i = 0;
14147     do
14148     {
14149         int j = 0;
14150         do
14151         {
14152             switch (j)
14153             {
14154                 case 0:
14155                     ++j;
14156                     continue;
14157                 default:
14158                 case 2:
14159                 case 3:
14160                 case 4:
14161                     ++j;
14162                     ++result;
14163                     if (j >= 2 && j <= 6)
14164                         break;
14165                     else
14166                         continue;
14167             }
14168             ++result;
14169         } while (j < 8);
14170         ++i;
14171     } while (i < 10);
14172 
14173     color = result == 120 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
14174 })";
14175 
14176     runTest(kFS);
14177 }
14178 
14179 // Test that precision is retained for constants (which are constant folded).  Adapted from a WebGL
14180 // test.
TEST_P(GLSLTest,ConstantFoldedConstantsRetainPrecision)14181 TEST_P(GLSLTest, ConstantFoldedConstantsRetainPrecision)
14182 {
14183     constexpr char kFS[] = R"(
14184 // It is assumed that uTest is set to 0. It's here to make the expression not constant.
14185 uniform mediump float uTest;
14186 void main() {
14187     // exact representation of 4096.5 requires 13 bits of relative precision.
14188     const highp float c = 4096.5;
14189     mediump float a = 0.0;
14190     // Below, addition should be evaluated at highp, since one of the operands has the highp qualifier.
14191     // Thus fract should also be evaluated at highp.
14192     // See OpenGL ES Shading Language spec section 4.5.2.
14193     // This should make the result 0.5, since highp provides at least 16 bits of relative precision.
14194     // (exceptions for operation precision are allowed for a small number of computationally
14195     // intensive built-in functions, but it is reasonable to think that fract is not one of those).
14196     // However, if fract() is incorrectly evaluated at minimum precision fulfilling mediump criteria,
14197     // or at IEEE half float precision, the result is 0.0.
14198     a = fract(c + uTest);
14199     // Multiply by 2.0 to make the color green.
14200     gl_FragColor = vec4(0.0, 2.0 * a, 0.0, 1.0);
14201 })";
14202 
14203     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
14204 
14205     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
14206     EXPECT_GL_NO_ERROR();
14207 
14208     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
14209 }
14210 
TEST_P(GLSLTest,VectorAndMatrixScalarizationDoesNotAffectRendering)14211 TEST_P(GLSLTest, VectorAndMatrixScalarizationDoesNotAffectRendering)
14212 {
14213     ANGLE_SKIP_TEST_IF(IsWindows() && IsNVIDIA() && (IsOpenGL() || IsOpenGLES()));
14214 
14215     constexpr char kFS[] = R"(
14216 precision mediump float;
14217 
14218 varying vec2 v_texCoord;
14219 
14220 float a = 0.;
14221 #define A 0.
14222 
14223 #define r(a)    mat2( cos( a + vec4(0,-1.5708,1.5708,0) ) )
14224 vec2 c;
14225 #define f(U,a)  ( c = (U) * r(a) , sin(10.*c.x) )
14226 
14227 void main() {
14228     vec2 U = v_texCoord;
14229 
14230     gl_FragColor = U.y > .5
14231         ? vec4( f(U,a) , f(U*4.,a) , 0,1.0)   // top
14232         : vec4( f(U,A) , f(U*4.,A) , 0,1.0);  // bottom
14233 }
14234 
14235 )";
14236 
14237     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), kFS);
14238     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
14239 
14240     // Make sure we rendered something.
14241     EXPECT_PIXEL_NE(0, 0, 0, 0, 0, 0);
14242 
14243     // Comapare one line in top half to one line in bottom half.
14244     int compareWidth  = getWindowWidth();
14245     int compareHeight = getWindowHeight() / 4;
14246 
14247     ASSERT_GE(compareWidth, 2);
14248     ASSERT_GE(compareHeight, 2);
14249 
14250     GLubyte pixelValue[4];
14251     constexpr int tolerance = 12;
14252 
14253     for (int x = 0; x < compareWidth; ++x)
14254     {
14255         glReadPixels(x, compareHeight, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixelValue);
14256         EXPECT_PIXEL_NEAR(x, getWindowHeight() - compareHeight, pixelValue[0], pixelValue[1],
14257                           pixelValue[2], pixelValue[3], tolerance);
14258     }
14259     EXPECT_GL_NO_ERROR();
14260 }
14261 
14262 // Tests initializing a shader IO block using the shader translator option.
TEST_P(GLSLTest_ES31_InitShaderVariables,InitIOBlock)14263 TEST_P(GLSLTest_ES31_InitShaderVariables, InitIOBlock)
14264 {
14265     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14266 
14267     const char kVS[] = R"(#version 310 es
14268 #extension GL_EXT_shader_io_blocks : require
14269 in vec4 position;
14270 out BlockType {
14271     vec4 blockMember;
14272 } BlockTypeOut;
14273 
14274 void main()
14275 {
14276     gl_Position = position;
14277 })";
14278 
14279     const char kFS[] = R"(#version 310 es
14280 #extension GL_EXT_shader_io_blocks : require
14281 precision mediump float;
14282 out vec4 colorOut;
14283 in BlockType {
14284     vec4 blockMember;
14285 } BlockTypeOut;
14286 
14287 void main()
14288 {
14289     if (BlockTypeOut.blockMember == vec4(0)) {
14290         colorOut = vec4(0, 1, 0, 1);
14291     } else {
14292         colorOut = vec4(1, 0, 0, 1);
14293     }
14294 })";
14295 
14296     ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
14297     drawQuad(testProgram, "position", 0.5f, 1.0f, true);
14298     ASSERT_GL_NO_ERROR();
14299     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
14300 }
14301 
14302 // Tests initializing a nameless shader IO block using the shader translator option.
TEST_P(GLSLTest_ES31_InitShaderVariables,InitIOBlockNameless)14303 TEST_P(GLSLTest_ES31_InitShaderVariables, InitIOBlockNameless)
14304 {
14305     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14306 
14307     const char kVS[] = R"(#version 310 es
14308 #extension GL_EXT_shader_io_blocks : require
14309 in vec4 position;
14310 out BlockType {
14311     vec4 blockMember;
14312 };
14313 
14314 void main()
14315 {
14316     gl_Position = position;
14317 })";
14318 
14319     const char kFS[] = R"(#version 310 es
14320 #extension GL_EXT_shader_io_blocks : require
14321 precision mediump float;
14322 out vec4 colorOut;
14323 in BlockType {
14324     vec4 blockMember;
14325 };
14326 
14327 void main()
14328 {
14329     if (blockMember == vec4(0)) {
14330         colorOut = vec4(0, 1, 0, 1);
14331     } else {
14332         colorOut = vec4(1, 0, 0, 1);
14333     }
14334 })";
14335 
14336     ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
14337     drawQuad(testProgram, "position", 0.5f, 1.0f, true);
14338     ASSERT_GL_NO_ERROR();
14339     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
14340 }
14341 
14342 // Tests initializing a shader IO block with an array using the shader translator option.
TEST_P(GLSLTest_ES31_InitShaderVariables,InitIOBlockWithArray)14343 TEST_P(GLSLTest_ES31_InitShaderVariables, InitIOBlockWithArray)
14344 {
14345     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14346 
14347     const char kVS[] = R"(#version 310 es
14348 #extension GL_EXT_shader_io_blocks : require
14349 in vec4 position;
14350 out BlockType {
14351     vec4 blockMember[2];
14352 } BlockTypeOut;
14353 
14354 void main()
14355 {
14356     gl_Position = position;
14357 })";
14358 
14359     const char kFS[] = R"(#version 310 es
14360 #extension GL_EXT_shader_io_blocks : require
14361 precision mediump float;
14362 out vec4 colorOut;
14363 in BlockType {
14364     vec4 blockMember[2];
14365 } BlockTypeOut;
14366 
14367 void main()
14368 {
14369     if (BlockTypeOut.blockMember[0] == vec4(0) &&
14370         BlockTypeOut.blockMember[1] == vec4(0)) {
14371         colorOut = vec4(0, 1, 0, 1);
14372     } else {
14373         colorOut = vec4(1, 0, 0, 1);
14374     }
14375 })";
14376 
14377     ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
14378     drawQuad(testProgram, "position", 0.5f, 1.0f, true);
14379     ASSERT_GL_NO_ERROR();
14380     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
14381 }
14382 
14383 // Tests initializing a shader IO block array using the shader translator option.
TEST_P(GLSLTest_ES31_InitShaderVariables,InitIOBlockArray)14384 TEST_P(GLSLTest_ES31_InitShaderVariables, InitIOBlockArray)
14385 {
14386     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14387 
14388     const char kVS[] = R"(#version 310 es
14389 #extension GL_EXT_shader_io_blocks : require
14390 in vec4 position;
14391 out BlockType {
14392     vec4 blockMember;
14393 } BlockTypeOut[2];
14394 
14395 void main()
14396 {
14397     gl_Position = position;
14398 })";
14399 
14400     const char kFS[] = R"(#version 310 es
14401 #extension GL_EXT_shader_io_blocks : require
14402 precision mediump float;
14403 out vec4 colorOut;
14404 in BlockType {
14405     vec4 blockMember;
14406 } BlockTypeOut[2];
14407 
14408 void main()
14409 {
14410     if (BlockTypeOut[0].blockMember == vec4(0) &&
14411         BlockTypeOut[1].blockMember == vec4(0)) {
14412         colorOut = vec4(0, 1, 0, 1);
14413     } else {
14414         colorOut = vec4(1, 0, 0, 1);
14415     }
14416 })";
14417 
14418     ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
14419     drawQuad(testProgram, "position", 0.5f, 1.0f, true);
14420     ASSERT_GL_NO_ERROR();
14421     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
14422 }
14423 
14424 // Tests initializing a shader IO block with a struct using the shader translator option.
TEST_P(GLSLTest_ES31_InitShaderVariables,InitIOBlockWithStruct)14425 TEST_P(GLSLTest_ES31_InitShaderVariables, InitIOBlockWithStruct)
14426 {
14427     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14428 
14429     const char kVS[] = R"(#version 310 es
14430 #extension GL_EXT_shader_io_blocks : require
14431 in vec4 position;
14432 struct s {
14433     float f;
14434     vec2 v;
14435 };
14436 out BlockType {
14437     s blockMember;
14438 } BlockTypeOut;
14439 
14440 void main()
14441 {
14442     gl_Position = position;
14443 })";
14444 
14445     const char kFS[] = R"(#version 310 es
14446 #extension GL_EXT_shader_io_blocks : require
14447 precision mediump float;
14448 out vec4 colorOut;
14449 struct s {
14450     float f;
14451     vec2 v;
14452 };
14453 in BlockType {
14454     s blockMember;
14455 } BlockTypeOut;
14456 
14457 void main()
14458 {
14459     if (BlockTypeOut.blockMember.f == 0.0 &&
14460         BlockTypeOut.blockMember.v == vec2(0)) {
14461         colorOut = vec4(0, 1, 0, 1);
14462     } else {
14463         colorOut = vec4(1, 0, 0, 1);
14464     }
14465 })";
14466 
14467     ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
14468     drawQuad(testProgram, "position", 0.5f, 1.0f, true);
14469     ASSERT_GL_NO_ERROR();
14470     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
14471 }
14472 
14473 // Tests initializing an IO block with a complicated set of types, using the shader translator.
TEST_P(GLSLTest_ES31_InitShaderVariables,InitIOBlockWithComplexTypes)14474 TEST_P(GLSLTest_ES31_InitShaderVariables, InitIOBlockWithComplexTypes)
14475 {
14476     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14477 
14478     const char kVS[] = R"(#version 310 es
14479 #extension GL_EXT_shader_io_blocks : require
14480 in vec4 position;
14481 struct s {
14482     float f;
14483     vec2 v;
14484 };
14485 out BlockType {
14486     vec4 v;
14487     s s1;
14488     s s2[2];
14489 } BlockTypeOut;
14490 
14491 void main()
14492 {
14493     gl_Position = position;
14494 })";
14495 
14496     const char kFS[] = R"(#version 310 es
14497 #extension GL_EXT_shader_io_blocks : require
14498 precision mediump float;
14499 out vec4 colorOut;
14500 struct s {
14501     float f;
14502     vec2 v;
14503 };
14504 in BlockType {
14505     vec4 v;
14506     s s1;
14507     s s2[2];
14508 } BlockTypeOut;
14509 
14510 void main()
14511 {
14512     s sz = s(0.0, vec2(0));
14513     if (BlockTypeOut.v == vec4(0) &&
14514         BlockTypeOut.s1 == sz &&
14515         BlockTypeOut.s2[0] == sz &&
14516         BlockTypeOut.s2[1] == sz) {
14517         colorOut = vec4(0, 1, 0, 1);
14518     } else {
14519         colorOut = vec4(1, 0, 0, 1);
14520     }
14521 })";
14522 
14523     ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
14524     drawQuad(testProgram, "position", 0.5f, 1.0f, true);
14525     ASSERT_GL_NO_ERROR();
14526     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
14527 }
14528 
14529 // Tests an unsuccessful re-link using glBindAttribLocation.
TEST_P(GLSLTest_ES3,UnsuccessfulRelinkWithBindAttribLocation)14530 TEST_P(GLSLTest_ES3, UnsuccessfulRelinkWithBindAttribLocation)
14531 {
14532     // Make a simple program.
14533     ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
14534 
14535     // Install the executable.
14536     glUseProgram(testProgram);
14537 
14538     // Re-link with a bad XFB varying and a bound attrib location.
14539     const char *tfVaryings = "gl_FragColor";
14540     glTransformFeedbackVaryings(testProgram, 1, &tfVaryings, GL_SEPARATE_ATTRIBS);
14541     glBindAttribLocation(testProgram, 8, essl1_shaders::PositionAttrib());
14542     glLinkProgram(testProgram);
14543     GLint linkStatus = 999;
14544     glGetProgramiv(testProgram, GL_LINK_STATUS, &linkStatus);
14545     ASSERT_GL_NO_ERROR();
14546     ASSERT_EQ(linkStatus, GL_FALSE);
14547 
14548     // Under normal GL this is not an error.
14549     glDrawArrays(GL_TRIANGLES, 79, 16);
14550     EXPECT_GL_NO_ERROR();
14551 }
14552 
14553 // Tests an unsuccessful re-link using glBindAttribLocation under WebGL.
TEST_P(WebGL2GLSLTest,UnsuccessfulRelinkWithBindAttribLocation)14554 TEST_P(WebGL2GLSLTest, UnsuccessfulRelinkWithBindAttribLocation)
14555 {
14556     // Make a simple program.
14557     ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
14558 
14559     // Install the executable.
14560     glUseProgram(testProgram);
14561 
14562     // Re-link with a bad XFB varying and a bound attrib location.
14563     const char *tfVaryings = "gl_FragColor";
14564     glTransformFeedbackVaryings(testProgram, 1, &tfVaryings, GL_SEPARATE_ATTRIBS);
14565     glBindAttribLocation(testProgram, 8, essl1_shaders::PositionAttrib());
14566     glLinkProgram(testProgram);
14567     GLint linkStatus = 999;
14568     glGetProgramiv(testProgram, GL_LINK_STATUS, &linkStatus);
14569     ASSERT_GL_NO_ERROR();
14570     ASSERT_EQ(linkStatus, GL_FALSE);
14571 
14572     // Under WebGL this is an error.
14573     glDrawArrays(GL_TRIANGLES, 79, 16);
14574     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
14575 }
14576 
14577 // Covers a HLSL compiler bug.
TEST_P(GLSLTest_ES3,ComplexCrossExpression)14578 TEST_P(GLSLTest_ES3, ComplexCrossExpression)
14579 {
14580     constexpr char kFS[] = R"(#version 300 es
14581 precision mediump float;
14582 vec3 a = vec3(0.0);
14583 out vec4 color;
14584 void main()
14585 {
14586     cross(max(vec3(0.0), reflect(dot(a, vec3(0.0)), 0.0)), vec3(0.0));
14587 })";
14588 
14589     ANGLE_GL_PROGRAM(testProgram, essl3_shaders::vs::Simple(), kFS);
14590     drawQuad(testProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
14591     ASSERT_GL_NO_ERROR();
14592 }
14593 
14594 // Regression test for a crash in SPIR-V output when faced with an array of struct constant.
TEST_P(GLSLTest_ES3,ArrayOfStructConstantBug)14595 TEST_P(GLSLTest_ES3, ArrayOfStructConstantBug)
14596 {
14597     constexpr char kFS[] = R"(#version 300 es
14598 struct S {
14599     int foo;
14600 };
14601 void main() {
14602     S a[3];
14603     a = S[3](S(0), S(1), S(2));
14604 })";
14605 
14606     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
14607 
14608     const char *sourceArray[1] = {kFS};
14609     GLint lengths[1]           = {static_cast<GLint>(sizeof(kFS) - 1)};
14610     glShaderSource(shader, 1, sourceArray, lengths);
14611     glCompileShader(shader);
14612 
14613     GLint compileResult;
14614     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
14615     EXPECT_NE(compileResult, 0);
14616 }
14617 
14618 // Regression test for a bug in SPIR-V output where float+matrix was mishandled.
TEST_P(GLSLTest_ES3,FloatPlusMatrix)14619 TEST_P(GLSLTest_ES3, FloatPlusMatrix)
14620 {
14621     constexpr char kFS[] = R"(#version 300 es
14622 
14623 precision mediump float;
14624 
14625 layout(location=0) out vec4 color;
14626 
14627 uniform float f;
14628 
14629 void main()
14630 {
14631     mat3x2 m = f + mat3x2(0);
14632     color = vec4(m[0][0]);
14633 })";
14634 
14635     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
14636 
14637     const char *sourceArray[1] = {kFS};
14638     GLint lengths[1]           = {static_cast<GLint>(sizeof(kFS) - 1)};
14639     glShaderSource(shader, 1, sourceArray, lengths);
14640     glCompileShader(shader);
14641 
14642     GLint compileResult;
14643     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
14644     EXPECT_NE(compileResult, 0);
14645 }
14646 
14647 // Regression test for a bug in SPIR-V output where a transformation creates float(constant) without
14648 // folding it into a TIntermConstantUnion.  This transformation is clamping non-constant indices in
14649 // WebGL.  The |false ? i : 5| as index caused the transformation to consider this a non-constant
14650 // index.
TEST_P(WebGL2GLSLTest,IndexClampConstantIndexBug)14651 TEST_P(WebGL2GLSLTest, IndexClampConstantIndexBug)
14652 {
14653     constexpr char kFS[] = R"(#version 300 es
14654 precision highp float;
14655 
14656 layout(location=0) out float f;
14657 
14658 uniform int i;
14659 
14660 void main()
14661 {
14662     float data[10];
14663     f = data[false ? i : 5];
14664 })";
14665 
14666     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
14667 
14668     const char *sourceArray[1] = {kFS};
14669     GLint lengths[1]           = {static_cast<GLint>(sizeof(kFS) - 1)};
14670     glShaderSource(shader, 1, sourceArray, lengths);
14671     glCompileShader(shader);
14672 
14673     GLint compileResult;
14674     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
14675     EXPECT_NE(compileResult, 0);
14676 }
14677 }  // anonymous namespace
14678 
14679 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(GLSLTest, WithGlslang(ES2_VULKAN()));
14680 
14681 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(GLSLTestNoValidation);
14682 
14683 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLTest_ES3);
14684 ANGLE_INSTANTIATE_TEST_ES3_AND(GLSLTest_ES3, WithGlslang(ES3_VULKAN()));
14685 
14686 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLTestLoops);
14687 ANGLE_INSTANTIATE_TEST_ES3_AND(GLSLTestLoops, WithGlslang(ES3_VULKAN()));
14688 
14689 ANGLE_INSTANTIATE_TEST_ES2_AND(WebGLGLSLTest, WithGlslang(ES2_VULKAN()));
14690 
14691 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WebGL2GLSLTest);
14692 ANGLE_INSTANTIATE_TEST_ES3_AND(WebGL2GLSLTest, WithGlslang(ES3_VULKAN()));
14693 
14694 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLTest_ES31);
14695 ANGLE_INSTANTIATE_TEST_ES31_AND(GLSLTest_ES31, WithGlslang(ES31_VULKAN()));
14696 
14697 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLTest_ES31_InitShaderVariables);
14698 ANGLE_INSTANTIATE_TEST(GLSLTest_ES31_InitShaderVariables, WithInitShaderVariables(ES31_VULKAN()));
14699