• 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 class GLSLTest : public ANGLETest<>
17 {
18   protected:
GLSLTest()19     GLSLTest()
20     {
21         setWindowWidth(128);
22         setWindowHeight(128);
23         setConfigRedBits(8);
24         setConfigGreenBits(8);
25         setConfigBlueBits(8);
26         setConfigAlphaBits(8);
27     }
28 
GenerateVaryingType(GLint vectorSize)29     std::string GenerateVaryingType(GLint vectorSize)
30     {
31         char varyingType[10];
32 
33         if (vectorSize == 1)
34         {
35             snprintf(varyingType, sizeof(varyingType), "float");
36         }
37         else
38         {
39             snprintf(varyingType, sizeof(varyingType), "vec%d", vectorSize);
40         }
41 
42         return std::string(varyingType);
43     }
44 
GenerateVectorVaryingDeclaration(GLint vectorSize,GLint arraySize,GLint id)45     std::string GenerateVectorVaryingDeclaration(GLint vectorSize, GLint arraySize, GLint id)
46     {
47         char buff[100];
48 
49         if (arraySize == 1)
50         {
51             snprintf(buff, sizeof(buff), "varying %s v%d;\n",
52                      GenerateVaryingType(vectorSize).c_str(), id);
53         }
54         else
55         {
56             snprintf(buff, sizeof(buff), "varying %s v%d[%d];\n",
57                      GenerateVaryingType(vectorSize).c_str(), id, arraySize);
58         }
59 
60         return std::string(buff);
61     }
62 
GenerateVectorVaryingSettingCode(GLint vectorSize,GLint arraySize,GLint id)63     std::string GenerateVectorVaryingSettingCode(GLint vectorSize, GLint arraySize, GLint id)
64     {
65         std::string returnString;
66         char buff[100];
67 
68         if (arraySize == 1)
69         {
70             snprintf(buff, sizeof(buff), "\t v%d = %s(1.0);\n", id,
71                      GenerateVaryingType(vectorSize).c_str());
72             returnString += buff;
73         }
74         else
75         {
76             for (int i = 0; i < arraySize; i++)
77             {
78                 snprintf(buff, sizeof(buff), "\t v%d[%d] = %s(1.0);\n", id, i,
79                          GenerateVaryingType(vectorSize).c_str());
80                 returnString += buff;
81             }
82         }
83 
84         return returnString;
85     }
86 
GenerateVectorVaryingUseCode(GLint arraySize,GLint id)87     std::string GenerateVectorVaryingUseCode(GLint arraySize, GLint id)
88     {
89         if (arraySize == 1)
90         {
91             char buff[100];
92             snprintf(buff, sizeof(buff), "v%d + ", id);
93             return std::string(buff);
94         }
95         else
96         {
97             std::string returnString;
98             for (int i = 0; i < arraySize; i++)
99             {
100                 char buff[100];
101                 snprintf(buff, sizeof(buff), "v%d[%d] + ", id, i);
102                 returnString += buff;
103             }
104             return returnString;
105         }
106     }
107 
GenerateGLSLWithVaryings(GLint floatCount,GLint floatArrayCount,GLint vec2Count,GLint vec2ArrayCount,GLint vec3Count,GLint vec3ArrayCount,GLint vec4Count,GLint vec4ArrayCount,bool useFragCoord,bool usePointCoord,bool usePointSize,std::string * fragmentShader,std::string * vertexShader)108     void GenerateGLSLWithVaryings(GLint floatCount,
109                                   GLint floatArrayCount,
110                                   GLint vec2Count,
111                                   GLint vec2ArrayCount,
112                                   GLint vec3Count,
113                                   GLint vec3ArrayCount,
114                                   GLint vec4Count,
115                                   GLint vec4ArrayCount,
116                                   bool useFragCoord,
117                                   bool usePointCoord,
118                                   bool usePointSize,
119                                   std::string *fragmentShader,
120                                   std::string *vertexShader)
121     {
122         // Generate a string declaring the varyings, to share between the fragment shader and the
123         // vertex shader.
124         std::string varyingDeclaration;
125 
126         unsigned int varyingCount = 0;
127 
128         for (GLint i = 0; i < floatCount; i++)
129         {
130             varyingDeclaration += GenerateVectorVaryingDeclaration(1, 1, varyingCount);
131             varyingCount += 1;
132         }
133 
134         for (GLint i = 0; i < floatArrayCount; i++)
135         {
136             varyingDeclaration += GenerateVectorVaryingDeclaration(1, 2, varyingCount);
137             varyingCount += 1;
138         }
139 
140         for (GLint i = 0; i < vec2Count; i++)
141         {
142             varyingDeclaration += GenerateVectorVaryingDeclaration(2, 1, varyingCount);
143             varyingCount += 1;
144         }
145 
146         for (GLint i = 0; i < vec2ArrayCount; i++)
147         {
148             varyingDeclaration += GenerateVectorVaryingDeclaration(2, 2, varyingCount);
149             varyingCount += 1;
150         }
151 
152         for (GLint i = 0; i < vec3Count; i++)
153         {
154             varyingDeclaration += GenerateVectorVaryingDeclaration(3, 1, varyingCount);
155             varyingCount += 1;
156         }
157 
158         for (GLint i = 0; i < vec3ArrayCount; i++)
159         {
160             varyingDeclaration += GenerateVectorVaryingDeclaration(3, 2, varyingCount);
161             varyingCount += 1;
162         }
163 
164         for (GLint i = 0; i < vec4Count; i++)
165         {
166             varyingDeclaration += GenerateVectorVaryingDeclaration(4, 1, varyingCount);
167             varyingCount += 1;
168         }
169 
170         for (GLint i = 0; i < vec4ArrayCount; i++)
171         {
172             varyingDeclaration += GenerateVectorVaryingDeclaration(4, 2, varyingCount);
173             varyingCount += 1;
174         }
175 
176         // Generate the vertex shader
177         vertexShader->clear();
178         vertexShader->append(varyingDeclaration);
179         vertexShader->append("\nvoid main()\n{\n");
180 
181         unsigned int currentVSVarying = 0;
182 
183         for (GLint i = 0; i < floatCount; i++)
184         {
185             vertexShader->append(GenerateVectorVaryingSettingCode(1, 1, currentVSVarying));
186             currentVSVarying += 1;
187         }
188 
189         for (GLint i = 0; i < floatArrayCount; i++)
190         {
191             vertexShader->append(GenerateVectorVaryingSettingCode(1, 2, currentVSVarying));
192             currentVSVarying += 1;
193         }
194 
195         for (GLint i = 0; i < vec2Count; i++)
196         {
197             vertexShader->append(GenerateVectorVaryingSettingCode(2, 1, currentVSVarying));
198             currentVSVarying += 1;
199         }
200 
201         for (GLint i = 0; i < vec2ArrayCount; i++)
202         {
203             vertexShader->append(GenerateVectorVaryingSettingCode(2, 2, currentVSVarying));
204             currentVSVarying += 1;
205         }
206 
207         for (GLint i = 0; i < vec3Count; i++)
208         {
209             vertexShader->append(GenerateVectorVaryingSettingCode(3, 1, currentVSVarying));
210             currentVSVarying += 1;
211         }
212 
213         for (GLint i = 0; i < vec3ArrayCount; i++)
214         {
215             vertexShader->append(GenerateVectorVaryingSettingCode(3, 2, currentVSVarying));
216             currentVSVarying += 1;
217         }
218 
219         for (GLint i = 0; i < vec4Count; i++)
220         {
221             vertexShader->append(GenerateVectorVaryingSettingCode(4, 1, currentVSVarying));
222             currentVSVarying += 1;
223         }
224 
225         for (GLint i = 0; i < vec4ArrayCount; i++)
226         {
227             vertexShader->append(GenerateVectorVaryingSettingCode(4, 2, currentVSVarying));
228             currentVSVarying += 1;
229         }
230 
231         if (usePointSize)
232         {
233             vertexShader->append("gl_PointSize = 1.0;\n");
234         }
235 
236         vertexShader->append("}\n");
237 
238         // Generate the fragment shader
239         fragmentShader->clear();
240         fragmentShader->append("precision highp float;\n");
241         fragmentShader->append(varyingDeclaration);
242         fragmentShader->append("\nvoid main() \n{ \n\tvec4 retColor = vec4(0,0,0,0);\n");
243 
244         unsigned int currentFSVarying = 0;
245 
246         // Make use of the float varyings
247         fragmentShader->append("\tretColor += vec4(");
248 
249         for (GLint i = 0; i < floatCount; i++)
250         {
251             fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying));
252             currentFSVarying += 1;
253         }
254 
255         for (GLint i = 0; i < floatArrayCount; i++)
256         {
257             fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying));
258             currentFSVarying += 1;
259         }
260 
261         fragmentShader->append("0.0, 0.0, 0.0, 0.0);\n");
262 
263         // Make use of the vec2 varyings
264         fragmentShader->append("\tretColor += vec4(");
265 
266         for (GLint i = 0; i < vec2Count; i++)
267         {
268             fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying));
269             currentFSVarying += 1;
270         }
271 
272         for (GLint i = 0; i < vec2ArrayCount; i++)
273         {
274             fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying));
275             currentFSVarying += 1;
276         }
277 
278         fragmentShader->append("vec2(0.0, 0.0), 0.0, 0.0);\n");
279 
280         // Make use of the vec3 varyings
281         fragmentShader->append("\tretColor += vec4(");
282 
283         for (GLint i = 0; i < vec3Count; i++)
284         {
285             fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying));
286             currentFSVarying += 1;
287         }
288 
289         for (GLint i = 0; i < vec3ArrayCount; i++)
290         {
291             fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying));
292             currentFSVarying += 1;
293         }
294 
295         fragmentShader->append("vec3(0.0, 0.0, 0.0), 0.0);\n");
296 
297         // Make use of the vec4 varyings
298         fragmentShader->append("\tretColor += ");
299 
300         for (GLint i = 0; i < vec4Count; i++)
301         {
302             fragmentShader->append(GenerateVectorVaryingUseCode(1, currentFSVarying));
303             currentFSVarying += 1;
304         }
305 
306         for (GLint i = 0; i < vec4ArrayCount; i++)
307         {
308             fragmentShader->append(GenerateVectorVaryingUseCode(2, currentFSVarying));
309             currentFSVarying += 1;
310         }
311 
312         fragmentShader->append("vec4(0.0, 0.0, 0.0, 0.0);\n");
313 
314         // Set gl_FragColor, and use special variables if requested
315         fragmentShader->append("\tgl_FragColor = retColor");
316 
317         if (useFragCoord)
318         {
319             fragmentShader->append(" + gl_FragCoord");
320         }
321 
322         if (usePointCoord)
323         {
324             fragmentShader->append(" + vec4(gl_PointCoord, 0.0, 0.0)");
325         }
326 
327         fragmentShader->append(";\n}");
328     }
329 
VaryingTestBase(GLint floatCount,GLint floatArrayCount,GLint vec2Count,GLint vec2ArrayCount,GLint vec3Count,GLint vec3ArrayCount,GLint vec4Count,GLint vec4ArrayCount,bool useFragCoord,bool usePointCoord,bool usePointSize,bool expectSuccess)330     void VaryingTestBase(GLint floatCount,
331                          GLint floatArrayCount,
332                          GLint vec2Count,
333                          GLint vec2ArrayCount,
334                          GLint vec3Count,
335                          GLint vec3ArrayCount,
336                          GLint vec4Count,
337                          GLint vec4ArrayCount,
338                          bool useFragCoord,
339                          bool usePointCoord,
340                          bool usePointSize,
341                          bool expectSuccess)
342     {
343         std::string fragmentShaderSource;
344         std::string vertexShaderSource;
345 
346         GenerateGLSLWithVaryings(floatCount, floatArrayCount, vec2Count, vec2ArrayCount, vec3Count,
347                                  vec3ArrayCount, vec4Count, vec4ArrayCount, useFragCoord,
348                                  usePointCoord, usePointSize, &fragmentShaderSource,
349                                  &vertexShaderSource);
350 
351         GLuint program = CompileProgram(vertexShaderSource.c_str(), fragmentShaderSource.c_str());
352 
353         if (expectSuccess)
354         {
355             EXPECT_NE(0u, program);
356         }
357         else
358         {
359             EXPECT_EQ(0u, program);
360         }
361     }
362 
CompileGLSLWithUniformsAndSamplers(GLint vertexUniformCount,GLint fragmentUniformCount,GLint vertexSamplersCount,GLint fragmentSamplersCount,bool expectSuccess)363     void CompileGLSLWithUniformsAndSamplers(GLint vertexUniformCount,
364                                             GLint fragmentUniformCount,
365                                             GLint vertexSamplersCount,
366                                             GLint fragmentSamplersCount,
367                                             bool expectSuccess)
368     {
369         std::stringstream vertexShader;
370         std::stringstream fragmentShader;
371 
372         // Generate the vertex shader
373         vertexShader << "precision mediump float;\n";
374 
375         for (int i = 0; i < vertexUniformCount; i++)
376         {
377             vertexShader << "uniform vec4 v" << i << ";\n";
378         }
379 
380         for (int i = 0; i < vertexSamplersCount; i++)
381         {
382             vertexShader << "uniform sampler2D s" << i << ";\n";
383         }
384 
385         vertexShader << "void main()\n{\n";
386 
387         for (int i = 0; i < vertexUniformCount; i++)
388         {
389             vertexShader << "    gl_Position +=  v" << i << ";\n";
390         }
391 
392         for (int i = 0; i < vertexSamplersCount; i++)
393         {
394             vertexShader << "    gl_Position +=  texture2D(s" << i << ", vec2(0.0, 0.0));\n";
395         }
396 
397         if (vertexUniformCount == 0 && vertexSamplersCount == 0)
398         {
399             vertexShader << "   gl_Position = vec4(0.0);\n";
400         }
401 
402         vertexShader << "}\n";
403 
404         // Generate the fragment shader
405         fragmentShader << "precision mediump float;\n";
406 
407         for (int i = 0; i < fragmentUniformCount; i++)
408         {
409             fragmentShader << "uniform vec4 v" << i << ";\n";
410         }
411 
412         for (int i = 0; i < fragmentSamplersCount; i++)
413         {
414             fragmentShader << "uniform sampler2D s" << i << ";\n";
415         }
416 
417         fragmentShader << "void main()\n{\n";
418 
419         for (int i = 0; i < fragmentUniformCount; i++)
420         {
421             fragmentShader << "    gl_FragColor +=  v" << i << ";\n";
422         }
423 
424         for (int i = 0; i < fragmentSamplersCount; i++)
425         {
426             fragmentShader << "    gl_FragColor +=  texture2D(s" << i << ", vec2(0.0, 0.0));\n";
427         }
428 
429         if (fragmentUniformCount == 0 && fragmentSamplersCount == 0)
430         {
431             fragmentShader << "    gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n";
432         }
433 
434         fragmentShader << "}\n";
435 
436         GLuint program = CompileProgram(vertexShader.str().c_str(), fragmentShader.str().c_str());
437 
438         if (expectSuccess)
439         {
440             EXPECT_NE(0u, program);
441         }
442         else
443         {
444             EXPECT_EQ(0u, program);
445         }
446     }
447 
QueryErrorMessage(GLuint program)448     std::string QueryErrorMessage(GLuint program)
449     {
450         GLint infoLogLength;
451         glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);
452         EXPECT_GL_NO_ERROR();
453 
454         if (infoLogLength >= 1)
455         {
456             std::vector<GLchar> infoLog(infoLogLength);
457             glGetProgramInfoLog(program, static_cast<GLsizei>(infoLog.size()), nullptr,
458                                 infoLog.data());
459             EXPECT_GL_NO_ERROR();
460             return infoLog.data();
461         }
462 
463         return "";
464     }
465 
validateComponentsInErrorMessage(const char * vertexShader,const char * fragmentShader,const char * expectedErrorType,const char * expectedVariableFullName)466     void validateComponentsInErrorMessage(const char *vertexShader,
467                                           const char *fragmentShader,
468                                           const char *expectedErrorType,
469                                           const char *expectedVariableFullName)
470     {
471         GLuint vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
472         GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);
473 
474         GLuint program = glCreateProgram();
475         glAttachShader(program, vs);
476         glAttachShader(program, fs);
477         glLinkProgram(program);
478 
479         glDetachShader(program, vs);
480         glDetachShader(program, fs);
481         glDeleteShader(vs);
482         glDeleteShader(fs);
483 
484         const std::string errorMessage = QueryErrorMessage(program);
485         printf("%s\n", errorMessage.c_str());
486 
487         EXPECT_NE(std::string::npos, errorMessage.find(expectedErrorType));
488         EXPECT_NE(std::string::npos, errorMessage.find(expectedVariableFullName));
489 
490         glDeleteProgram(program);
491         ASSERT_GL_NO_ERROR();
492     }
493 
verifyAttachment2DColor(unsigned int index,GLuint textureName,GLenum target,GLint level,GLColor color)494     void verifyAttachment2DColor(unsigned int index,
495                                  GLuint textureName,
496                                  GLenum target,
497                                  GLint level,
498                                  GLColor color)
499     {
500         glReadBuffer(GL_COLOR_ATTACHMENT0 + index);
501         ASSERT_GL_NO_ERROR();
502 
503         EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, color)
504             << "index " << index;
505     }
506 
ExpectedExtensionMacros(std::vector<std::string> expected)507     std::string ExpectedExtensionMacros(std::vector<std::string> expected)
508     {
509         std::string shader;
510         for (const auto &ext : expected)
511         {
512             if (IsGLExtensionEnabled(ext))
513             {
514                 shader += "\n#ifndef " + ext + "\n#error !defined(" + ext + ")\n#endif\n";
515             }
516         }
517         return shader;
518     }
519 
UnexpectedExtensionMacros(std::vector<std::string> unexpected)520     std::string UnexpectedExtensionMacros(std::vector<std::string> unexpected)
521     {
522         std::string shader;
523         for (const auto &ext : unexpected)
524         {
525             shader += "\n#ifdef " + ext + "\n#error defined(" + ext + ")\n#endif\n";
526         }
527         return shader;
528     }
529 };
530 
531 class GLSLTestNoValidation : public GLSLTest
532 {
533   public:
GLSLTestNoValidation()534     GLSLTestNoValidation() { setNoErrorEnabled(true); }
535 };
536 
537 class GLSLTest_ES3 : public GLSLTest
538 {};
539 
540 class GLSLTest_ES31 : public GLSLTest
541 {
542   protected:
543     void testArrayOfArrayOfSamplerDynamicIndex(const APIExtensionVersion usedExtension);
544     void testTessellationTextureBufferAccess(const APIExtensionVersion usedExtension);
545 };
546 
547 // Tests the "init output variables" ANGLE shader translator option.
548 class GLSLTest_ES3_InitShaderVariables : public GLSLTest
549 {};
550 class GLSLTest_ES31_InitShaderVariables : public GLSLTest
551 {};
552 
BuildBigInitialStackShader(int length)553 std::string BuildBigInitialStackShader(int length)
554 {
555     std::string result;
556     result += "void main() { \n";
557     for (int i = 0; i < length; i++)
558     {
559         result += "  if (true) { \n";
560     }
561     result += "  int temp; \n";
562     for (int i = 0; i <= length; i++)
563     {
564         result += "} \n";
565     }
566     return result;
567 }
568 
569 // Tests a shader from conformance.olges/GL/build/build_017_to_024
570 // This shader uses chained assign-equals ops with swizzle, often reusing the same variable
571 // as part of a swizzle.
TEST_P(GLSLTest,SwizzledChainedAssignIncrement)572 TEST_P(GLSLTest, SwizzledChainedAssignIncrement)
573 {
574     constexpr char kFS[] =
575         R"(
576         precision mediump float;
577         void main() {
578             vec2 v = vec2(1,5);
579             // at the end of next statement, values in
580             // v.x = 12, v.y = 12
581             v.xy += v.yx += v.xy;
582             // v1 and v2, both are initialized with (12,12)
583             vec2 v1 = v, v2 = v;
584             v1.xy += v2.yx += ++(v.xy);  // v1 = 37, v2 = 25 each
585             v1.xy += v2.yx += (v.xy)++;  // v1 = 75, v2 = 38 each
586             gl_FragColor = vec4(v1,v2)/255.;  // 75, 75, 38, 38
587         })";
588 
589     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
590     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
591     ASSERT_GL_NO_ERROR();
592     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(75, 75, 38, 38));
593 }
594 
TEST_P(GLSLTest,NamelessScopedStructs)595 TEST_P(GLSLTest, NamelessScopedStructs)
596 {
597     constexpr char kFS[] = R"(precision mediump float;
598 void main()
599 {
600     struct
601     {
602         float q;
603     } b;
604 
605     gl_FragColor = vec4(1, 0, 0, 1);
606     gl_FragColor.a += b.q;
607 })";
608 
609     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
610 }
611 
TEST_P(GLSLTest_ES3,CompareEqualityOfArrayOfVectors)612 TEST_P(GLSLTest_ES3, CompareEqualityOfArrayOfVectors)
613 {
614     constexpr char kFS[] = R"(#version 300 es
615 precision mediump float;
616 out vec4 fragColor;
617 uniform vec3 a[3];
618 uniform vec3 b[3];
619 void main() {
620   bool same = a == b;
621   fragColor = vec4(0);
622   if (same) {
623     fragColor = vec4(1);
624   }
625 }
626 )";
627 
628     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
629     glUseProgram(program);
630 
631     GLint aLocation = glGetUniformLocation(program, "a");
632     GLint bLocation = glGetUniformLocation(program, "b");
633     EXPECT_NE(aLocation, -1);
634     EXPECT_NE(bLocation, -1);
635 
636     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
637     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
638 
639     static float almostZeros[] = {0, 0, 0, 0, 0, 0, 0, 1, 0};
640     glUniform3fv(bLocation, 9, almostZeros);
641 
642     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
643     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
644 
645     glUniform3fv(aLocation, 9, almostZeros);
646     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
647     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
648 
649     ASSERT_GL_NO_ERROR();
650 }
651 
TEST_P(GLSLTest_ES3,CompareEqualityOfArrayOfMatrices)652 TEST_P(GLSLTest_ES3, CompareEqualityOfArrayOfMatrices)
653 {
654     constexpr char kFS[] = R"(#version 300 es
655 precision mediump float;
656 out vec4 fragColor;
657 uniform mat3 a[3];
658 uniform mat3 b[3];
659 void main() {
660   bool same = a == b;
661   fragColor = vec4(0);
662   if (same) {
663     fragColor = vec4(1);
664   }
665 }
666 )";
667 
668     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
669     glUseProgram(program);
670 
671     GLint aLocation = glGetUniformLocation(program, "a");
672     GLint bLocation = glGetUniformLocation(program, "b");
673     EXPECT_NE(aLocation, -1);
674     EXPECT_NE(bLocation, -1);
675 
676     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
677     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
678 
679     static float almostZeros[] = {
680         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
681     };
682     glUniformMatrix3fv(bLocation, 27, false, almostZeros);
683 
684     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
685     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
686 
687     glUniformMatrix3fv(aLocation, 27, false, almostZeros);
688     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
689     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
690 
691     ASSERT_GL_NO_ERROR();
692 }
693 
TEST_P(GLSLTest_ES3,CompareEqualityOfArrayOfFloats)694 TEST_P(GLSLTest_ES3, CompareEqualityOfArrayOfFloats)
695 {
696     constexpr char kFS[] = R"(#version 300 es
697 precision mediump float;
698 out vec4 fragColor;
699 uniform float a[3];
700 uniform float b[3];
701 void main() {
702   bool same = a == b;
703   fragColor = vec4(0);
704   if (same) {
705     fragColor = vec4(1);
706   }
707 }
708 )";
709 
710     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
711     glUseProgram(program);
712 
713     GLint aLocation = glGetUniformLocation(program, "a");
714     GLint bLocation = glGetUniformLocation(program, "b");
715     EXPECT_NE(aLocation, -1);
716     EXPECT_NE(bLocation, -1);
717 
718     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
719     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
720 
721     static float almostZeros[] = {
722         0,
723         0,
724         1,
725     };
726     glUniform1fv(bLocation, 3, almostZeros);
727 
728     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
729     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
730 
731     glUniform1fv(aLocation, 3, almostZeros);
732     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
733     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
734 
735     ASSERT_GL_NO_ERROR();
736 }
737 
TEST_P(GLSLTest_ES3,CompareInequalityOfArrayOfVectors)738 TEST_P(GLSLTest_ES3, CompareInequalityOfArrayOfVectors)
739 {
740     constexpr char kFS[] = R"(#version 300 es
741 precision mediump float;
742 out vec4 fragColor;
743 uniform vec3 a[3];
744 uniform vec3 b[3];
745 void main() {
746   bool notSame = a != b;
747   fragColor = vec4(0);
748   if (notSame) {
749     fragColor = vec4(1);
750   }
751 }
752 )";
753 
754     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
755     glUseProgram(program);
756 
757     GLint aLocation = glGetUniformLocation(program, "a");
758     GLint bLocation = glGetUniformLocation(program, "b");
759     EXPECT_NE(aLocation, -1);
760     EXPECT_NE(bLocation, -1);
761 
762     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
763     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
764 
765     static float almostZeros[] = {0, 0, 0, 0, 0, 0, 0, 1, 0};
766     glUniform3fv(bLocation, 9, almostZeros);
767 
768     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
769     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
770 
771     glUniform3fv(aLocation, 9, almostZeros);
772     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
773     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
774 
775     ASSERT_GL_NO_ERROR();
776 }
777 
TEST_P(GLSLTest_ES3,CompareInequalityOfArrayOfMatrices)778 TEST_P(GLSLTest_ES3, CompareInequalityOfArrayOfMatrices)
779 {
780     constexpr char kFS[] = R"(#version 300 es
781 precision mediump float;
782 out vec4 fragColor;
783 uniform mat3 a[3];
784 uniform mat3 b[3];
785 void main() {
786   bool notSame = a != b;
787   fragColor = vec4(0);
788   if (notSame) {
789     fragColor = vec4(1);
790   }
791 }
792 )";
793 
794     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
795     glUseProgram(program);
796 
797     GLint aLocation = glGetUniformLocation(program, "a");
798     GLint bLocation = glGetUniformLocation(program, "b");
799     EXPECT_NE(aLocation, -1);
800     EXPECT_NE(bLocation, -1);
801 
802     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
803     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
804 
805     static float almostZeros[] = {
806         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
807     };
808     glUniformMatrix3fv(bLocation, 27, false, almostZeros);
809 
810     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
811     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
812 
813     glUniformMatrix3fv(aLocation, 27, false, almostZeros);
814     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
815     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
816 
817     ASSERT_GL_NO_ERROR();
818 }
819 
TEST_P(GLSLTest_ES3,CompareInequalityOfArrayOfFloats)820 TEST_P(GLSLTest_ES3, CompareInequalityOfArrayOfFloats)
821 {
822     constexpr char kFS[] = R"(#version 300 es
823 precision mediump float;
824 out vec4 fragColor;
825 uniform float a[3];
826 uniform float b[3];
827 void main() {
828   bool notSame = a != b;
829   fragColor = vec4(0);
830   if (notSame) {
831     fragColor = vec4(1);
832   }
833 }
834 )";
835 
836     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
837     glUseProgram(program);
838 
839     GLint aLocation = glGetUniformLocation(program, "a");
840     GLint bLocation = glGetUniformLocation(program, "b");
841     EXPECT_NE(aLocation, -1);
842     EXPECT_NE(bLocation, -1);
843 
844     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
845     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
846 
847     static float almostZeros[] = {
848         0,
849         0,
850         1,
851     };
852     glUniform1fv(bLocation, 3, almostZeros);
853 
854     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
855     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
856 
857     glUniform1fv(aLocation, 3, almostZeros);
858     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
859     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
860 
861     ASSERT_GL_NO_ERROR();
862 }
863 
864 // Test that array of fragment shader outputs is processed properly and draws
865 // E.g. was issue with "out vec4 frag_color[4];"
TEST_P(GLSLTest_ES3,FragmentShaderOutputArray)866 TEST_P(GLSLTest_ES3, FragmentShaderOutputArray)
867 {
868     GLuint fbo;
869     glGenFramebuffers(1, &fbo);
870     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
871 
872     GLuint textures[4];
873     glGenTextures(4, textures);
874 
875     for (size_t texIndex = 0; texIndex < ArraySize(textures); texIndex++)
876     {
877         glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
878         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
879                      GL_UNSIGNED_BYTE, nullptr);
880     }
881 
882     GLint maxDrawBuffers;
883     glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
884     ASSERT_GE(maxDrawBuffers, 4);
885 
886     GLuint readFramebuffer;
887     glGenFramebuffers(1, &readFramebuffer);
888     glBindFramebuffer(GL_READ_FRAMEBUFFER, readFramebuffer);
889 
890     constexpr char kFS[] = R"(#version 300 es
891 precision highp float;
892 
893 out vec4 frag_color[4];
894 
895 void main()
896 {
897     frag_color[0] = vec4(1.0, 0.0, 0.0, 1.0);
898     frag_color[1] = vec4(0.0, 1.0, 0.0, 1.0);
899     frag_color[2] = vec4(0.0, 0.0, 1.0, 1.0);
900     frag_color[3] = vec4(1.0, 1.0, 1.0, 1.0);
901 }
902 )";
903 
904     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
905 
906     GLenum allBufs[4] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2,
907                          GL_COLOR_ATTACHMENT3};
908 
909     constexpr GLuint kMaxBuffers = 4;
910 
911     // Enable all draw buffers.
912     for (GLuint texIndex = 0; texIndex < kMaxBuffers; texIndex++)
913     {
914         glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
915         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
916                                textures[texIndex], 0);
917         glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
918                                textures[texIndex], 0);
919     }
920     glDrawBuffers(kMaxBuffers, allBufs);
921 
922     // Draw with simple program.
923     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
924     ASSERT_GL_NO_ERROR();
925 
926     verifyAttachment2DColor(0, textures[0], GL_TEXTURE_2D, 0, GLColor::red);
927     verifyAttachment2DColor(1, textures[1], GL_TEXTURE_2D, 0, GLColor::green);
928     verifyAttachment2DColor(2, textures[2], GL_TEXTURE_2D, 0, GLColor::blue);
929     verifyAttachment2DColor(3, textures[3], GL_TEXTURE_2D, 0, GLColor::white);
930 }
931 
932 // Test that inactive fragment shader outputs don't cause a crash.
TEST_P(GLSLTest_ES3,InactiveFragmentShaderOutput)933 TEST_P(GLSLTest_ES3, InactiveFragmentShaderOutput)
934 {
935     constexpr char kFS[] = R"(#version 300 es
936 precision highp float;
937 
938 // Make color0 inactive but specify color1 first.  The Vulkan backend assigns bogus locations when
939 // compiling and fixes it up in SPIR-V.  If color0's location is not fixed, it will return location
940 // 1 (aliasing color1).  This will lead to a Vulkan validation warning about attachment 0 not being
941 // written to, which shouldn't be fatal.
942 layout(location = 1) out vec4 color1;
943 layout(location = 0) out vec4 color0;
944 
945 void main()
946 {
947     color1 = vec4(0.0, 1.0, 0.0, 1.0);
948 }
949 )";
950 
951     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
952 
953     constexpr GLint kDrawBufferCount = 2;
954 
955     GLint maxDrawBuffers;
956     glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
957     ASSERT_GE(maxDrawBuffers, kDrawBufferCount);
958 
959     GLTexture textures[kDrawBufferCount];
960 
961     for (GLint texIndex = 0; texIndex < kDrawBufferCount; ++texIndex)
962     {
963         glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
964         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
965                      GL_UNSIGNED_BYTE, nullptr);
966     }
967 
968     GLenum allBufs[kDrawBufferCount] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
969 
970     GLFramebuffer fbo;
971     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
972 
973     // Enable all draw buffers.
974     for (GLint texIndex = 0; texIndex < kDrawBufferCount; ++texIndex)
975     {
976         glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
977         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
978                                textures[texIndex], 0);
979     }
980     glDrawBuffers(kDrawBufferCount, allBufs);
981 
982     // Draw with simple program.
983     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
984     ASSERT_GL_NO_ERROR();
985 }
986 
TEST_P(GLSLTest,ScopedStructsOrderBug)987 TEST_P(GLSLTest, ScopedStructsOrderBug)
988 {
989     constexpr char kFS[] = R"(precision mediump float;
990 
991 struct T
992 {
993     float f;
994 };
995 
996 void main()
997 {
998     T a;
999 
1000     struct T
1001     {
1002         float q;
1003     };
1004 
1005     T b;
1006 
1007     gl_FragColor = vec4(1, 0, 0, 1);
1008     gl_FragColor.a += a.f;
1009     gl_FragColor.a += b.q;
1010 })";
1011 
1012     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
1013 }
1014 
1015 // Test that defining a struct together with an inactive uniform, then using it in a scope that has
1016 // another struct with the same name declared works.
TEST_P(GLSLTest,ScopedStructsOrderBug2)1017 TEST_P(GLSLTest, ScopedStructsOrderBug2)
1018 {
1019     constexpr char kFS[] = R"(precision mediump float;
1020 
1021 uniform struct T
1022 {
1023     float f;
1024 } x;
1025 
1026 void main()
1027 {
1028     T a;
1029 
1030     struct T
1031     {
1032         float q;
1033     };
1034 
1035     T b;
1036 
1037     gl_FragColor = vec4(1, 0, 0, 1);
1038     gl_FragColor.a += a.f;
1039     gl_FragColor.a += b.q;
1040 })";
1041 
1042     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
1043 }
1044 
1045 // Test that inactive uniforms of struct type don't cause any errors.
TEST_P(GLSLTest,InactiveStructUniform)1046 TEST_P(GLSLTest, InactiveStructUniform)
1047 {
1048     constexpr char kVS[] = R"(
1049 uniform struct
1050 {
1051     vec4 c;
1052 } s;
1053 void main()
1054 {
1055 })";
1056 
1057     ANGLE_GL_PROGRAM(program, kVS, essl1_shaders::fs::Red());
1058 }
1059 
1060 // Test that struct with same name can be declared in inner scope.
TEST_P(GLSLTest,SameNameStructInInnerScope)1061 TEST_P(GLSLTest, SameNameStructInInnerScope)
1062 {
1063     constexpr char kVS[] = R"(
1064 void main() {
1065     gl_Position = vec4(0);
1066 })";
1067 
1068     constexpr char kFS[] = R"(
1069 struct S
1070 {
1071     mediump float f;
1072 };
1073 void main()
1074 {
1075     struct S
1076     {
1077         S n;
1078     };
1079 })";
1080 
1081     ANGLE_GL_PROGRAM(program, kVS, kFS);
1082 }
1083 
1084 // Regression test based on WebGL's conformance/glsl/misc/empty-declaration.html
TEST_P(GLSLTest,StructEmptyDeclaratorBug)1085 TEST_P(GLSLTest, StructEmptyDeclaratorBug)
1086 {
1087     constexpr char kVS[] = R"(
1088 struct S {
1089     float member;
1090 }, a;
1091 void main() {
1092     a.member = 0.0;
1093     gl_Position = vec4(a.member);
1094 })";
1095 
1096     constexpr char kFS[] = R"(precision mediump float;
1097 void main()
1098 {
1099     gl_FragColor = vec4(1.0,0.0,0.0,1.0);
1100 })";
1101 
1102     ANGLE_GL_PROGRAM(program, kVS, kFS);
1103 }
1104 
1105 // Regression test based on WebGL's conformance/ogles/GL/build/build_001_to_008.html
TEST_P(GLSLTest,StructConstantFoldingBug)1106 TEST_P(GLSLTest, StructConstantFoldingBug)
1107 {
1108     constexpr char kVS[] = R"(
1109 void main()
1110 {
1111 
1112    const struct s2 {
1113        int i;
1114        vec3 v3;
1115        bvec4 bv4;
1116    } s22  = s2(8, vec3(9, 10, 11), bvec4(true, false, true, false));
1117 
1118    struct s4 {
1119        int ii;
1120        vec4 v4;
1121       };
1122 
1123    const struct s1 {
1124       s2 ss;
1125       int i;
1126       float f;
1127       mat4 m;
1128       s4 s44;
1129    } s11 = s1(s22, 2, 4.0, mat4(5), s4(6, vec4(7, 8, 9, 10))) ;
1130 
1131   const int field3 = s11.i * s11.ss.i;  // constant folding (int * int)
1132   const vec4 field4 = s11.s44.v4 * s11.s44.v4; // constant folding (vec4 * vec4)
1133  // 49, 64, 81, 100
1134   const vec4 v4 = vec4(s11.ss.v3.y, s11.m[3][3], field3, field4[2]);  // 10.0, 5.0, 16.0, 81.0
1135   gl_Position = v4;
1136 })";
1137 
1138     constexpr char kFS[] = R"(precision mediump float;
1139 precision mediump float;
1140 void main()
1141 {
1142     gl_FragColor = vec4(1.0,0.0,0.0,1.0);
1143 })";
1144 
1145     ANGLE_GL_PROGRAM(program, kVS, kFS);
1146 }
1147 
1148 // Test that constant folding doesn't remove struct declaration.
TEST_P(GLSLTest,StructConstantFoldingBug2)1149 TEST_P(GLSLTest, StructConstantFoldingBug2)
1150 {
1151     constexpr char kVS[] = R"(
1152 uniform vec4 u;
1153 
1154 void main()
1155 {
1156 
1157    const struct s2 {
1158        int i;
1159        vec3 v3;
1160        bvec4 bv4;
1161    } s22  = s2(8, vec3(9, 10, 11), bvec4(true, false, true, false));
1162 
1163    s2 x;
1164    x.v3 = u.xyz;
1165 
1166    gl_Position = vec4(x.v3, float(s22.i));
1167 })";
1168 
1169     constexpr char kFS[] = R"(precision mediump float;
1170 precision mediump float;
1171 void main()
1172 {
1173     gl_FragColor = vec4(1.0,0.0,0.0,1.0);
1174 })";
1175 
1176     ANGLE_GL_PROGRAM(program, kVS, kFS);
1177 }
1178 
TEST_P(GLSLTest,ScopedStructsBug)1179 TEST_P(GLSLTest, ScopedStructsBug)
1180 {
1181     constexpr char kFS[] = R"(precision mediump float;
1182 
1183 struct T_0
1184 {
1185     float f;
1186 };
1187 
1188 void main()
1189 {
1190     gl_FragColor = vec4(1, 0, 0, 1);
1191 
1192     struct T
1193     {
1194         vec2 v;
1195     };
1196 
1197     T_0 a;
1198     T b;
1199 
1200     gl_FragColor.a += a.f;
1201     gl_FragColor.a += b.v.x;
1202 })";
1203 
1204     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
1205 }
1206 
TEST_P(GLSLTest,DxPositionBug)1207 TEST_P(GLSLTest, DxPositionBug)
1208 {
1209     constexpr char kVS[] = R"(attribute vec4 inputAttribute;
1210 varying float dx_Position;
1211 void main()
1212 {
1213     gl_Position = vec4(inputAttribute);
1214     dx_Position = 0.0;
1215 })";
1216 
1217     constexpr char kFS[] = R"(precision mediump float;
1218 
1219 varying float dx_Position;
1220 
1221 void main()
1222 {
1223     gl_FragColor = vec4(dx_Position, 0, 0, 1);
1224 })";
1225 
1226     ANGLE_GL_PROGRAM(program, kVS, kFS);
1227 }
1228 
1229 // Draw an array of points with the first vertex offset at 0 using gl_VertexID
TEST_P(GLSLTest_ES3,GLVertexIDOffsetZeroDrawArray)1230 TEST_P(GLSLTest_ES3, GLVertexIDOffsetZeroDrawArray)
1231 {
1232     constexpr int kStartIndex  = 0;
1233     constexpr int kArrayLength = 5;
1234     constexpr char kVS[]       = R"(#version 300 es
1235 precision highp float;
1236 void main() {
1237     gl_Position = vec4(float(gl_VertexID)/10.0, 0, 0, 1);
1238     gl_PointSize = 3.0;
1239 })";
1240 
1241     constexpr char kFS[] = R"(#version 300 es
1242 precision highp float;
1243 out vec4 outColor;
1244 void main() {
1245     outColor = vec4(1.0, 0.0, 0.0, 1.0);
1246 })";
1247 
1248     ANGLE_GL_PROGRAM(program, kVS, kFS);
1249 
1250     glUseProgram(program);
1251     glDrawArrays(GL_POINTS, kStartIndex, kArrayLength);
1252 
1253     double pointCenterX = static_cast<double>(getWindowWidth()) / 2.0;
1254     double pointCenterY = static_cast<double>(getWindowHeight()) / 2.0;
1255     for (int i = kStartIndex; i < kStartIndex + kArrayLength; i++)
1256     {
1257         double pointOffsetX = static_cast<double>(i * getWindowWidth()) / 20.0;
1258         EXPECT_PIXEL_COLOR_EQ(static_cast<int>(pointCenterX + pointOffsetX),
1259                               static_cast<int>(pointCenterY), GLColor::red);
1260     }
1261 }
1262 
GetFirstIntPixelRedValue()1263 GLint GetFirstIntPixelRedValue()
1264 {
1265     GLint pixel[4];
1266     glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_INT, pixel);
1267     return pixel[0];
1268 }
1269 
TEST_P(GLSLTest_ES3,GLVertexIDIntegerTextureDrawElements)1270 TEST_P(GLSLTest_ES3, GLVertexIDIntegerTextureDrawElements)
1271 {
1272     constexpr char kVS[] = R"(#version 300 es
1273     flat out highp int vVertexID;
1274 
1275     void main() {
1276         vVertexID = gl_VertexID;
1277         gl_PointSize = 1.0;
1278         gl_Position = vec4(0,0,0,1);
1279     })";
1280 
1281     constexpr char kFS[] = R"(#version 300 es
1282     flat in highp int vVertexID;
1283     out highp int oVertexID;
1284     void main() {
1285         oVertexID = vVertexID;
1286     })";
1287 
1288     ANGLE_GL_PROGRAM(program, kVS, kFS);
1289     glUseProgram(program);
1290     glViewport(0, 0, 1, 1);
1291 
1292     GLTexture tex;
1293     glBindTexture(GL_TEXTURE_2D, tex);
1294     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, 1, 1);
1295     GLFramebuffer fb;
1296     glBindFramebuffer(GL_FRAMEBUFFER, fb);
1297     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
1298 
1299     EXPECT_GL_NO_ERROR();
1300 
1301     GLint clearData[4] = {42};
1302     glClearBufferiv(GL_COLOR, 0, clearData);
1303     EXPECT_EQ(42, GetFirstIntPixelRedValue());
1304 
1305     const int kIndexDataSize = 5;
1306     GLushort indexData[]     = {1, 2, 5, 3, 10000};
1307     GLBuffer indexBuffer;
1308     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1309     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_STATIC_DRAW);
1310 
1311     for (size_t first = 0; first < kIndexDataSize; ++first)
1312     {
1313         for (size_t count = 1; first + count <= kIndexDataSize; ++count)
1314         {
1315             glDrawElements(GL_POINTS, count, GL_UNSIGNED_SHORT,
1316                            reinterpret_cast<const void *>(first * 2u));
1317             GLint expected = indexData[first + count - 1];
1318             GLint actual   = GetFirstIntPixelRedValue();
1319             EXPECT_EQ(expected, actual);
1320         }
1321     }
1322     EXPECT_GL_NO_ERROR();
1323 }
1324 
TEST_P(GLSLTest_ES3,GLVertexIDIntegerTextureDrawElementsU8)1325 TEST_P(GLSLTest_ES3, GLVertexIDIntegerTextureDrawElementsU8)
1326 {
1327     constexpr char kVS[] = R"(#version 300 es
1328     flat out highp int vVertexID;
1329 
1330     void main() {
1331         vVertexID = gl_VertexID;
1332         gl_PointSize = 1.0;
1333         gl_Position = vec4(0,0,0,1);
1334     })";
1335 
1336     constexpr char kFS[] = R"(#version 300 es
1337     flat in highp int vVertexID;
1338     out highp int oVertexID;
1339     void main() {
1340         oVertexID = vVertexID;
1341     })";
1342 
1343     ANGLE_GL_PROGRAM(program, kVS, kFS);
1344     glUseProgram(program);
1345     glViewport(0, 0, 1, 1);
1346 
1347     GLTexture tex;
1348     glBindTexture(GL_TEXTURE_2D, tex);
1349     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, 1, 1);
1350     GLFramebuffer fb;
1351     glBindFramebuffer(GL_FRAMEBUFFER, fb);
1352     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
1353 
1354     EXPECT_GL_NO_ERROR();
1355 
1356     GLint clearData[4] = {42};
1357     glClearBufferiv(GL_COLOR, 0, clearData);
1358     EXPECT_EQ(42, GetFirstIntPixelRedValue());
1359 
1360     const int kIndexDataSize = 5;
1361     GLubyte indexData[]      = {1, 2, 5, 3, 100};
1362     GLBuffer indexBuffer;
1363     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1364     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_STATIC_DRAW);
1365 
1366     for (size_t first = 0; first < kIndexDataSize; ++first)
1367     {
1368         for (size_t count = 1; first + count <= kIndexDataSize; ++count)
1369         {
1370             glDrawElements(GL_POINTS, count, GL_UNSIGNED_BYTE,
1371                            reinterpret_cast<const void *>(first));
1372             GLint expected = indexData[first + count - 1];
1373             GLint actual   = GetFirstIntPixelRedValue();
1374             EXPECT_EQ(expected, actual);
1375         }
1376     }
1377     EXPECT_GL_NO_ERROR();
1378 }
1379 
GLVertexIDIntegerTextureDrawElementsU8Line_Helper(size_t first,const GLubyte * indices)1380 void GLVertexIDIntegerTextureDrawElementsU8Line_Helper(size_t first, const GLubyte *indices)
1381 {
1382     glDrawElements(GL_LINES, 2, GL_UNSIGNED_BYTE, reinterpret_cast<const void *>(first));
1383 
1384     GLint pixels[8];
1385     glReadPixels(0, 0, 2, 1, GL_RGBA_INTEGER, GL_INT, pixels);
1386 
1387     GLint expected = indices[first + 1];
1388     EXPECT_EQ(expected, pixels[0]);
1389     EXPECT_EQ(expected, pixels[4]);
1390 }
1391 
TEST_P(GLSLTest_ES3,GLVertexIDIntegerTextureDrawElementsU8Line)1392 TEST_P(GLSLTest_ES3, GLVertexIDIntegerTextureDrawElementsU8Line)
1393 {
1394     constexpr char kVS[] = R"(#version 300 es
1395     flat out highp int vVertexID;
1396     layout(location = 0) in vec4 position;
1397 
1398     void main() {
1399         vVertexID = gl_VertexID;
1400         gl_Position = position;
1401     })";
1402 
1403     constexpr char kFS[] = R"(#version 300 es
1404     flat in highp int vVertexID;
1405     out highp int oVertexID;
1406     void main() {
1407         oVertexID = vVertexID;
1408     })";
1409 
1410     ANGLE_GL_PROGRAM(program, kVS, kFS);
1411     glUseProgram(program);
1412     glViewport(0, 0, 2, 1);
1413 
1414     GLTexture tex;
1415     glBindTexture(GL_TEXTURE_2D, tex);
1416     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, 2, 1);
1417     GLFramebuffer fb;
1418     glBindFramebuffer(GL_FRAMEBUFFER, fb);
1419     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
1420 
1421     EXPECT_GL_NO_ERROR();
1422 
1423     struct LR
1424     {
1425         LR() : X0(-1.0f), X1(1.0f) {}
1426         float X0;
1427         float X1;
1428     };
1429     constexpr int kNumVertices = 100;
1430     LR vertData[kNumVertices];
1431     GLBuffer buf;
1432     glBindBuffer(GL_ARRAY_BUFFER, buf);
1433     glBufferData(GL_ARRAY_BUFFER, sizeof(vertData), vertData, GL_STATIC_DRAW);
1434     glEnableVertexAttribArray(0);
1435     glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
1436 
1437     GLint clearData[4] = {42};
1438     glClearBufferiv(GL_COLOR, 0, clearData);
1439     EXPECT_EQ(42, GetFirstIntPixelRedValue());
1440 
1441     GLubyte indexData[] = {1, 4, 5, 2, 50, 61};
1442     GLBuffer indexBuffer;
1443     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1444     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_STATIC_DRAW);
1445 
1446     GLVertexIDIntegerTextureDrawElementsU8Line_Helper(0, indexData);
1447     GLVertexIDIntegerTextureDrawElementsU8Line_Helper(1, indexData);
1448     GLVertexIDIntegerTextureDrawElementsU8Line_Helper(2, indexData);
1449     GLVertexIDIntegerTextureDrawElementsU8Line_Helper(4, indexData);
1450 
1451     EXPECT_GL_NO_ERROR();
1452 }
1453 
1454 // Test gl_VertexID works with lines
TEST_P(GLSLTest_ES3,GLVertexIDIntegerTextureDrawElementsU8LineIds)1455 TEST_P(GLSLTest_ES3, GLVertexIDIntegerTextureDrawElementsU8LineIds)
1456 {
1457     // Draws lines via indices (glDrawElements). Each pair of indices
1458     // draws the next consecutive pixel. For 2 points, because we're
1459     // using int attributes, they must be "flat" and so the spec
1460     // says for a given line the value should come from the second
1461     // of the 2 points. (see: OpenGL ES 3.0.2 spec Table 2.12)
1462     // Each line is only 1 pixel long so every other pixel should
1463     // be the default value.
1464     constexpr char kVS[] = R"(#version 300 es
1465     flat out highp int vVertexID;
1466     layout(location = 0) in float position;
1467     uniform float width;
1468 
1469     void main() {
1470         vVertexID = gl_VertexID;
1471         gl_Position = vec4(position / width * 2.0 - 1.0, 0, 0, 1);
1472     })";
1473 
1474     constexpr char kFS[] = R"(#version 300 es
1475     flat in highp int vVertexID;
1476     out highp int oVertexID;
1477     void main() {
1478         oVertexID = vVertexID;
1479     })";
1480 
1481     GLubyte indexData[]          = {1, 4, 5, 2, 50, 61, 32, 33};
1482     constexpr size_t kNumIndices = sizeof(indexData) / sizeof(indexData[0]);
1483     GLBuffer indexBuffer;
1484     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1485     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_STATIC_DRAW);
1486 
1487     ANGLE_GL_PROGRAM(program, kVS, kFS);
1488     glUseProgram(program);
1489     glUniform1f(glGetUniformLocation(program, "width"), kNumIndices);
1490     glViewport(0, 0, kNumIndices, 1);
1491 
1492     GLTexture tex;
1493     glBindTexture(GL_TEXTURE_2D, tex);
1494     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, kNumIndices, 1);
1495     GLFramebuffer fb;
1496     glBindFramebuffer(GL_FRAMEBUFFER, fb);
1497     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
1498 
1499     constexpr int kNumVertices = 100;
1500     std::vector<float> vertData(kNumVertices, -1.0f);
1501     {
1502         int i = 0;
1503         for (GLubyte ndx : indexData)
1504         {
1505             vertData[ndx] = i++;
1506         }
1507     }
1508     GLBuffer buf;
1509     glBindBuffer(GL_ARRAY_BUFFER, buf);
1510     glBufferData(GL_ARRAY_BUFFER, vertData.size() * sizeof(float), vertData.data(), GL_STATIC_DRAW);
1511     glEnableVertexAttribArray(0);
1512     glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
1513 
1514     GLint kDefaultValue = 42;
1515     GLint clearData[4]  = {kDefaultValue};
1516     glClearBufferiv(GL_COLOR, 0, clearData);
1517     EXPECT_EQ(kDefaultValue, GetFirstIntPixelRedValue());
1518 
1519     EXPECT_GL_NO_ERROR();
1520 
1521     glDrawElements(GL_LINES, kNumIndices, GL_UNSIGNED_BYTE, 0);
1522 
1523     GLint pixels[kNumIndices * 4];
1524     glReadPixels(0, 0, kNumIndices, 1, GL_RGBA_INTEGER, GL_INT, pixels);
1525 
1526     for (size_t i = 0; i < kNumIndices; ++i)
1527     {
1528         const int expected = i % 2 ? kDefaultValue : indexData[i + 1];
1529         const int actual   = pixels[i * 4];
1530         EXPECT_EQ(expected, actual);
1531     }
1532 
1533     EXPECT_GL_NO_ERROR();
1534 }
1535 
1536 // Helper function for the GLVertexIDIntegerTextureDrawArrays test
GLVertexIDIntegerTextureDrawArrays_helper(int first,int count,GLenum err)1537 void GLVertexIDIntegerTextureDrawArrays_helper(int first, int count, GLenum err)
1538 {
1539     glDrawArrays(GL_POINTS, first, count);
1540 
1541     int pixel[4];
1542     glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_INT, pixel);
1543     // If we call this function with err as GL_NO_ERROR, then we expect no error and check the
1544     // pixels.
1545     if (err == static_cast<GLenum>(GL_NO_ERROR))
1546     {
1547         EXPECT_GL_NO_ERROR();
1548         EXPECT_EQ(pixel[0], first + count - 1);
1549     }
1550     else
1551     {
1552         // If we call this function with err set, we will allow the error, but check the pixels if
1553         // the error hasn't occurred.
1554         GLenum glError = glGetError();
1555         if (glError == err || glError == static_cast<GLenum>(GL_NO_ERROR))
1556         {
1557             EXPECT_EQ(pixel[0], first + count - 1);
1558         }
1559     }
1560 }
1561 
1562 // Ensure gl_VertexID gets passed to an integer texture properly when drawArrays is called. This
1563 // is based off the WebGL test:
1564 // https://github.com/KhronosGroup/WebGL/blob/master/sdk/tests/conformance2/rendering/vertex-id.html
TEST_P(GLSLTest_ES3,GLVertexIDIntegerTextureDrawArrays)1565 TEST_P(GLSLTest_ES3, GLVertexIDIntegerTextureDrawArrays)
1566 {
1567     constexpr char kVS[] = R"(#version 300 es
1568 flat out highp int vVertexID;
1569 void main() {
1570     vVertexID = gl_VertexID;
1571     gl_Position = vec4(0,0,0,1);
1572     gl_PointSize = 1.0;
1573 })";
1574 
1575     constexpr char kFS[] = R"(#version 300 es
1576 flat in highp int vVertexID;
1577 out highp int oVertexID;
1578 void main() {
1579     oVertexID = vVertexID;
1580 })";
1581 
1582     ANGLE_GL_PROGRAM(program, kVS, kFS);
1583     glUseProgram(program);
1584     glViewport(0, 0, 1, 1);
1585 
1586     GLTexture texture;
1587     glBindTexture(GL_TEXTURE_2D, texture);
1588     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, 1, 1);
1589     GLFramebuffer fbo;
1590     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1591     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1592     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1593     EXPECT_GL_NO_ERROR();
1594 
1595     // Clear the texture to 42 to ensure the first test case doesn't accidentally pass
1596     GLint val[4] = {42};
1597     glClearBufferiv(GL_COLOR, 0, val);
1598     int pixel[4];
1599     glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_INT, pixel);
1600     EXPECT_EQ(pixel[0], val[0]);
1601 
1602     GLVertexIDIntegerTextureDrawArrays_helper(0, 1, GL_NO_ERROR);
1603     GLVertexIDIntegerTextureDrawArrays_helper(1, 1, GL_NO_ERROR);
1604     GLVertexIDIntegerTextureDrawArrays_helper(10000, 1, GL_NO_ERROR);
1605     GLVertexIDIntegerTextureDrawArrays_helper(100000, 1, GL_NO_ERROR);
1606     GLVertexIDIntegerTextureDrawArrays_helper(1000000, 1, GL_NO_ERROR);
1607     GLVertexIDIntegerTextureDrawArrays_helper(0, 2, GL_NO_ERROR);
1608     GLVertexIDIntegerTextureDrawArrays_helper(1, 2, GL_NO_ERROR);
1609     GLVertexIDIntegerTextureDrawArrays_helper(10000, 2, GL_NO_ERROR);
1610     GLVertexIDIntegerTextureDrawArrays_helper(100000, 2, GL_NO_ERROR);
1611     GLVertexIDIntegerTextureDrawArrays_helper(1000000, 2, GL_NO_ERROR);
1612 
1613     int32_t int32Max = 0x7FFFFFFF;
1614     GLVertexIDIntegerTextureDrawArrays_helper(int32Max - 2, 1, GL_OUT_OF_MEMORY);
1615     GLVertexIDIntegerTextureDrawArrays_helper(int32Max - 1, 1, GL_OUT_OF_MEMORY);
1616 }
1617 
1618 // Draw an array of points with the first vertex offset at 5 using gl_VertexID
TEST_P(GLSLTest_ES3,GLVertexIDOffsetFiveDrawArray)1619 TEST_P(GLSLTest_ES3, GLVertexIDOffsetFiveDrawArray)
1620 {
1621     // Bug in Nexus drivers, offset does not work. (anglebug.com/42261941)
1622     ANGLE_SKIP_TEST_IF(IsNexus5X() && IsOpenGLES());
1623 
1624     constexpr int kStartIndex  = 5;
1625     constexpr int kArrayLength = 5;
1626     constexpr char kVS[]       = R"(#version 300 es
1627 precision highp float;
1628 void main() {
1629     gl_Position = vec4(float(gl_VertexID)/10.0, 0, 0, 1);
1630     gl_PointSize = 3.0;
1631 })";
1632 
1633     constexpr char kFS[] = R"(#version 300 es
1634 precision highp float;
1635 out vec4 outColor;
1636 void main() {
1637     outColor = vec4(1.0, 0.0, 0.0, 1.0);
1638 })";
1639 
1640     ANGLE_GL_PROGRAM(program, kVS, kFS);
1641 
1642     glUseProgram(program);
1643     glDrawArrays(GL_POINTS, kStartIndex, kArrayLength);
1644 
1645     double pointCenterX = static_cast<double>(getWindowWidth()) / 2.0;
1646     double pointCenterY = static_cast<double>(getWindowHeight()) / 2.0;
1647     for (int i = kStartIndex; i < kStartIndex + kArrayLength; i++)
1648     {
1649         double pointOffsetX = static_cast<double>(i * getWindowWidth()) / 20.0;
1650         EXPECT_PIXEL_COLOR_EQ(static_cast<int>(pointCenterX + pointOffsetX),
1651                               static_cast<int>(pointCenterY), GLColor::red);
1652     }
1653 }
1654 
TEST_P(GLSLTest,ElseIfRewriting)1655 TEST_P(GLSLTest, ElseIfRewriting)
1656 {
1657     constexpr char kVS[] =
1658         "attribute vec4 a_position;\n"
1659         "varying float v;\n"
1660         "void main() {\n"
1661         "  gl_Position = a_position;\n"
1662         "  v = 1.0;\n"
1663         "  if (a_position.x <= 0.5) {\n"
1664         "    v = 0.0;\n"
1665         "  } else if (a_position.x >= 0.5) {\n"
1666         "    v = 2.0;\n"
1667         "  }\n"
1668         "}\n";
1669 
1670     constexpr char kFS[] =
1671         "precision highp float;\n"
1672         "varying float v;\n"
1673         "void main() {\n"
1674         "  vec4 color = vec4(1.0, 0.0, 0.0, 1.0);\n"
1675         "  if (v >= 1.0) color = vec4(0.0, 1.0, 0.0, 1.0);\n"
1676         "  if (v >= 2.0) color = vec4(0.0, 0.0, 1.0, 1.0);\n"
1677         "  gl_FragColor = color;\n"
1678         "}\n";
1679 
1680     ANGLE_GL_PROGRAM(program, kVS, kFS);
1681 
1682     drawQuad(program, "a_position", 0.5f);
1683 
1684     EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
1685     EXPECT_PIXEL_EQ(getWindowWidth() - 1, 0, 0, 255, 0, 255);
1686 }
1687 
TEST_P(GLSLTest,TwoElseIfRewriting)1688 TEST_P(GLSLTest, TwoElseIfRewriting)
1689 {
1690     constexpr char kVS[] =
1691         "attribute vec4 a_position;\n"
1692         "varying float v;\n"
1693         "void main() {\n"
1694         "  gl_Position = a_position;\n"
1695         "  if (a_position.x == 0.0) {\n"
1696         "    v = 1.0;\n"
1697         "  } else if (a_position.x > 0.5) {\n"
1698         "    v = 0.0;\n"
1699         "  } else if (a_position.x > 0.75) {\n"
1700         "    v = 0.5;\n"
1701         "  }\n"
1702         "}\n";
1703 
1704     constexpr char kFS[] =
1705         "precision highp float;\n"
1706         "varying float v;\n"
1707         "void main() {\n"
1708         "  gl_FragColor = vec4(v, 0.0, 0.0, 1.0);\n"
1709         "}\n";
1710 
1711     ANGLE_GL_PROGRAM(program, kVS, kFS);
1712 }
1713 
TEST_P(GLSLTest,FrontFacingAndVarying)1714 TEST_P(GLSLTest, FrontFacingAndVarying)
1715 {
1716     EGLPlatformParameters platform = GetParam().eglParameters;
1717 
1718     constexpr char kVS[] = R"(attribute vec4 a_position;
1719 varying float v_varying;
1720 void main()
1721 {
1722     v_varying = a_position.x;
1723     gl_Position = a_position;
1724 })";
1725 
1726     constexpr char kFS[] = R"(precision mediump float;
1727 varying float v_varying;
1728 void main()
1729 {
1730     vec4 c;
1731 
1732     if (gl_FrontFacing)
1733     {
1734         c = vec4(v_varying, 0, 0, 1.0);
1735     }
1736     else
1737     {
1738         c = vec4(0, v_varying, 0, 1.0);
1739     }
1740     gl_FragColor = c;
1741 })";
1742 
1743     GLuint program = CompileProgram(kVS, kFS);
1744 
1745     // Compilation should fail on D3D11 feature level 9_3, since gl_FrontFacing isn't supported.
1746     if (platform.renderer == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
1747     {
1748         if (platform.majorVersion == 9 && platform.minorVersion == 3)
1749         {
1750             EXPECT_EQ(0u, program);
1751             return;
1752         }
1753     }
1754 
1755     // Otherwise, compilation should succeed
1756     EXPECT_NE(0u, program);
1757 }
1758 
1759 // Test that we can release the shader compiler and still compile things properly.
TEST_P(GLSLTest,ReleaseCompilerThenCompile)1760 TEST_P(GLSLTest, ReleaseCompilerThenCompile)
1761 {
1762     // Draw with the first program.
1763     ANGLE_GL_PROGRAM(program1, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
1764     drawQuad(program1, essl1_shaders::PositionAttrib(), 0.5f);
1765     ASSERT_GL_NO_ERROR();
1766     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1767 
1768     // Clear and release shader compiler.
1769     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
1770     glClear(GL_COLOR_BUFFER_BIT);
1771     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1772     glReleaseShaderCompiler();
1773     ASSERT_GL_NO_ERROR();
1774 
1775     // Draw with a second program.
1776     ANGLE_GL_PROGRAM(program2, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
1777     drawQuad(program2, essl1_shaders::PositionAttrib(), 0.5f);
1778     ASSERT_GL_NO_ERROR();
1779     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1780 }
1781 
1782 // Verify that linking shaders declaring different shading language versions fails.
TEST_P(GLSLTest_ES3,VersionMismatch)1783 TEST_P(GLSLTest_ES3, VersionMismatch)
1784 {
1785     GLuint program = CompileProgram(essl3_shaders::vs::Simple(), essl1_shaders::fs::Red());
1786     EXPECT_EQ(0u, program);
1787 
1788     program = CompileProgram(essl1_shaders::vs::Simple(), essl3_shaders::fs::Red());
1789     EXPECT_EQ(0u, program);
1790 }
1791 
1792 // Verify that declaring varying as invariant only in vertex shader fails in ESSL 1.00.
TEST_P(GLSLTest,InvariantVaryingOut)1793 TEST_P(GLSLTest, InvariantVaryingOut)
1794 {
1795     constexpr char kFS[] =
1796         "precision mediump float;\n"
1797         "varying float v_varying;\n"
1798         "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1799 
1800     constexpr char kVS[] =
1801         "attribute vec4 a_position;\n"
1802         "invariant varying float v_varying;\n"
1803         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1804 
1805     GLuint program = CompileProgram(kVS, kFS);
1806     EXPECT_EQ(0u, program);
1807 }
1808 
1809 // Verify that declaring varying as invariant only in vertex shader succeeds in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantVaryingOut)1810 TEST_P(GLSLTest_ES3, InvariantVaryingOut)
1811 {
1812     // TODO: ESSL 3.00 -> GLSL 1.20 translation should add "invariant" in fragment shader
1813     // for varyings which are invariant in vertex shader (http://anglebug.com/40096344)
1814     ANGLE_SKIP_TEST_IF(IsDesktopOpenGL());
1815 
1816     constexpr char kFS[] =
1817         "#version 300 es\n"
1818         "precision mediump float;\n"
1819         "in float v_varying;\n"
1820         "out vec4 my_FragColor;\n"
1821         "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1822 
1823     constexpr char kVS[] =
1824         "#version 300 es\n"
1825         "in vec4 a_position;\n"
1826         "invariant out float v_varying;\n"
1827         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1828 
1829     GLuint program = CompileProgram(kVS, kFS);
1830     EXPECT_NE(0u, program);
1831 }
1832 
1833 // Verify that declaring varying as invariant only in fragment shader fails in ESSL 1.00.
TEST_P(GLSLTest,InvariantVaryingIn)1834 TEST_P(GLSLTest, InvariantVaryingIn)
1835 {
1836     constexpr char kFS[] =
1837         "precision mediump float;\n"
1838         "invariant varying float v_varying;\n"
1839         "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1840 
1841     constexpr char kVS[] =
1842         "attribute vec4 a_position;\n"
1843         "varying float v_varying;\n"
1844         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1845 
1846     GLuint program = CompileProgram(kVS, kFS);
1847     EXPECT_EQ(0u, program);
1848 }
1849 
1850 // Verify that declaring varying as invariant only in fragment shader fails in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantVaryingIn)1851 TEST_P(GLSLTest_ES3, InvariantVaryingIn)
1852 {
1853     constexpr char kFS[] =
1854         "#version 300 es\n"
1855         "precision mediump float;\n"
1856         "invariant in float v_varying;\n"
1857         "out vec4 my_FragColor;\n"
1858         "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1859 
1860     constexpr char kVS[] =
1861         "#version 300 es\n"
1862         "in vec4 a_position;\n"
1863         "out float v_varying;\n"
1864         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1865 
1866     GLuint program = CompileProgram(kVS, kFS);
1867     EXPECT_EQ(0u, program);
1868 }
1869 
1870 // Verify that declaring varying as invariant in both shaders succeeds in ESSL 1.00.
TEST_P(GLSLTest,InvariantVaryingBoth)1871 TEST_P(GLSLTest, InvariantVaryingBoth)
1872 {
1873     constexpr char kFS[] =
1874         "precision mediump float;\n"
1875         "invariant varying float v_varying;\n"
1876         "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1877 
1878     constexpr char kVS[] =
1879         "attribute vec4 a_position;\n"
1880         "invariant varying float v_varying;\n"
1881         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1882 
1883     GLuint program = CompileProgram(kVS, kFS);
1884     EXPECT_NE(0u, program);
1885 }
1886 
1887 // Verify that declaring varying as invariant in both shaders fails in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantVaryingBoth)1888 TEST_P(GLSLTest_ES3, InvariantVaryingBoth)
1889 {
1890     constexpr char kFS[] =
1891         "#version 300 es\n"
1892         "precision mediump float;\n"
1893         "invariant in float v_varying;\n"
1894         "out vec4 my_FragColor;\n"
1895         "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1896 
1897     constexpr char kVS[] =
1898         "#version 300 es\n"
1899         "in vec4 a_position;\n"
1900         "invariant out float v_varying;\n"
1901         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1902 
1903     GLuint program = CompileProgram(kVS, kFS);
1904     EXPECT_EQ(0u, program);
1905 }
1906 
1907 // Verify that declaring gl_Position as invariant succeeds in ESSL 1.00.
TEST_P(GLSLTest,InvariantGLPosition)1908 TEST_P(GLSLTest, InvariantGLPosition)
1909 {
1910     constexpr char kFS[] =
1911         "precision mediump float;\n"
1912         "varying float v_varying;\n"
1913         "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1914 
1915     constexpr char kVS[] =
1916         "attribute vec4 a_position;\n"
1917         "invariant gl_Position;\n"
1918         "varying float v_varying;\n"
1919         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1920 
1921     GLuint program = CompileProgram(kVS, kFS);
1922     EXPECT_NE(0u, program);
1923 }
1924 
1925 // Verify that declaring gl_Position as invariant succeeds in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantGLPosition)1926 TEST_P(GLSLTest_ES3, InvariantGLPosition)
1927 {
1928     constexpr char kFS[] =
1929         "#version 300 es\n"
1930         "precision mediump float;\n"
1931         "in float v_varying;\n"
1932         "out vec4 my_FragColor;\n"
1933         "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1934 
1935     constexpr char kVS[] =
1936         "#version 300 es\n"
1937         "in vec4 a_position;\n"
1938         "invariant gl_Position;\n"
1939         "out float v_varying;\n"
1940         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1941 
1942     GLuint program = CompileProgram(kVS, kFS);
1943     EXPECT_NE(0u, program);
1944 }
1945 
1946 // Verify that using invariant(all) in both shaders fails in ESSL 1.00.
TEST_P(GLSLTest,InvariantAllBoth)1947 TEST_P(GLSLTest, InvariantAllBoth)
1948 {
1949     constexpr char kFS[] =
1950         "#pragma STDGL invariant(all)\n"
1951         "precision mediump float;\n"
1952         "varying float v_varying;\n"
1953         "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
1954 
1955     constexpr char kVS[] =
1956         "#pragma STDGL invariant(all)\n"
1957         "attribute vec4 a_position;\n"
1958         "varying float v_varying;\n"
1959         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
1960 
1961     GLuint program = CompileProgram(kVS, kFS);
1962     EXPECT_EQ(0u, program);
1963 }
1964 
1965 // Verify that using a struct as both invariant and non-invariant output works.
TEST_P(GLSLTest_ES31,StructBothInvariantAndNot)1966 TEST_P(GLSLTest_ES31, StructBothInvariantAndNot)
1967 {
1968     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
1969 
1970     constexpr char kVS[] = R"(#version 310 es
1971 #extension GL_EXT_shader_io_blocks : require
1972 
1973 struct S
1974 {
1975     vec4 s;
1976 };
1977 
1978 out Output
1979 {
1980     vec4 x;
1981     invariant S s;
1982 };
1983 
1984 out S s2;
1985 
1986 void main(){
1987     x = vec4(0);
1988     s.s = vec4(1);
1989     s2.s = vec4(2);
1990     S s3 = s;
1991     s.s = s3.s;
1992 })";
1993 
1994     GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
1995     EXPECT_NE(0u, shader);
1996     glDeleteShader(shader);
1997 }
1998 
1999 // Verify that using maximum size as atomic counter offset results in compilation failure.
TEST_P(GLSLTest_ES31,CompileWithMaxAtomicCounterOffsetFails)2000 TEST_P(GLSLTest_ES31, CompileWithMaxAtomicCounterOffsetFails)
2001 {
2002     GLint maxSize;
2003     glGetIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE, &maxSize);
2004 
2005     std::ostringstream srcStream;
2006     srcStream << "#version 310 es\n"
2007               << "layout(location = 0) out uvec4 color;\n"
2008               << "layout(binding = 0, offset = " << maxSize << ") uniform atomic_uint a_counter;\n"
2009               << "void main() {\n"
2010               << "color = uvec4(atomicCounterIncrement(a_counter)); \n"
2011               << "}";
2012     std::string fsStream = srcStream.str();
2013     const char *strFS    = fsStream.c_str();
2014 
2015     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, strFS);
2016     EXPECT_EQ(0u, shader);
2017 }
2018 
2019 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnFloat)2020 TEST_P(GLSLTest, MissingReturnFloat)
2021 {
2022     constexpr char kVS[] =
2023         "varying float v_varying;\n"
2024         "float f() { if (v_varying > 0.0) return 1.0; }\n"
2025         "void main() { gl_Position = vec4(f(), 0, 0, 1); }\n";
2026 
2027     GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
2028     EXPECT_NE(0u, program);
2029 }
2030 
2031 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnVec2)2032 TEST_P(GLSLTest, MissingReturnVec2)
2033 {
2034     constexpr char kVS[] =
2035         "varying float v_varying;\n"
2036         "vec2 f() { if (v_varying > 0.0) return vec2(1.0, 1.0); }\n"
2037         "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
2038 
2039     GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
2040     EXPECT_NE(0u, program);
2041 }
2042 
2043 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnVec3)2044 TEST_P(GLSLTest, MissingReturnVec3)
2045 {
2046     constexpr char kVS[] =
2047         "varying float v_varying;\n"
2048         "vec3 f() { if (v_varying > 0.0) return vec3(1.0, 1.0, 1.0); }\n"
2049         "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
2050 
2051     GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
2052     EXPECT_NE(0u, program);
2053 }
2054 
2055 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnVec4)2056 TEST_P(GLSLTest, MissingReturnVec4)
2057 {
2058     constexpr char kVS[] =
2059         "varying float v_varying;\n"
2060         "vec4 f() { if (v_varying > 0.0) return vec4(1.0, 1.0, 1.0, 1.0); }\n"
2061         "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
2062 
2063     GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
2064     EXPECT_NE(0u, program);
2065 }
2066 
2067 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnIVec4)2068 TEST_P(GLSLTest, MissingReturnIVec4)
2069 {
2070     constexpr char kVS[] =
2071         "varying float v_varying;\n"
2072         "ivec4 f() { if (v_varying > 0.0) return ivec4(1, 1, 1, 1); }\n"
2073         "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
2074 
2075     GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
2076     EXPECT_NE(0u, program);
2077 }
2078 
2079 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnMat4)2080 TEST_P(GLSLTest, MissingReturnMat4)
2081 {
2082     constexpr char kVS[] =
2083         "varying float v_varying;\n"
2084         "mat4 f() { if (v_varying > 0.0) return mat4(1.0); }\n"
2085         "void main() { gl_Position = vec4(f()[0][0], 0, 0, 1); }\n";
2086 
2087     GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
2088     EXPECT_NE(0u, program);
2089 }
2090 
2091 // Verify that functions without return statements still compile
TEST_P(GLSLTest,MissingReturnStruct)2092 TEST_P(GLSLTest, MissingReturnStruct)
2093 {
2094     constexpr char kVS[] =
2095         "varying float v_varying;\n"
2096         "struct s { float a; int b; vec2 c; };\n"
2097         "s f() { if (v_varying > 0.0) return s(1.0, 1, vec2(1.0, 1.0)); }\n"
2098         "void main() { gl_Position = vec4(f().a, 0, 0, 1); }\n";
2099 
2100     GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
2101     EXPECT_NE(0u, program);
2102 }
2103 
2104 // Verify that functions without return statements still compile
TEST_P(GLSLTest_ES3,MissingReturnArray)2105 TEST_P(GLSLTest_ES3, MissingReturnArray)
2106 {
2107     constexpr char kVS[] =
2108         "#version 300 es\n"
2109         "in float v_varying;\n"
2110         "vec2[2] f() { if (v_varying > 0.0) { return vec2[2](vec2(1.0, 1.0), vec2(1.0, 1.0)); } }\n"
2111         "void main() { gl_Position = vec4(f()[0].x, 0, 0, 1); }\n";
2112 
2113     GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
2114     EXPECT_NE(0u, program);
2115 }
2116 
2117 // Verify that functions without return statements still compile
TEST_P(GLSLTest_ES3,MissingReturnArrayOfStructs)2118 TEST_P(GLSLTest_ES3, MissingReturnArrayOfStructs)
2119 {
2120     constexpr char kVS[] =
2121         "#version 300 es\n"
2122         "in float v_varying;\n"
2123         "struct s { float a; int b; vec2 c; };\n"
2124         "s[2] f() { if (v_varying > 0.0) { return s[2](s(1.0, 1, vec2(1.0, 1.0)), s(1.0, 1, "
2125         "vec2(1.0, 1.0))); } }\n"
2126         "void main() { gl_Position = vec4(f()[0].a, 0, 0, 1); }\n";
2127 
2128     GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
2129     EXPECT_NE(0u, program);
2130 }
2131 
2132 // Verify that functions without return statements still compile
TEST_P(GLSLTest_ES3,MissingReturnStructOfArrays)2133 TEST_P(GLSLTest_ES3, MissingReturnStructOfArrays)
2134 {
2135     // TODO(crbug.com/998505): Test failing on Android FYI Release (NVIDIA Shield TV)
2136     ANGLE_SKIP_TEST_IF(IsNVIDIAShield());
2137 
2138     constexpr char kVS[] =
2139         "#version 300 es\n"
2140         "in float v_varying;\n"
2141         "struct s { float a[2]; int b[2]; vec2 c[2]; };\n"
2142         "s f() { if (v_varying > 0.0) { return s(float[2](1.0, 1.0), int[2](1, 1),"
2143         "vec2[2](vec2(1.0, 1.0), vec2(1.0, 1.0))); } }\n"
2144         "void main() { gl_Position = vec4(f().a[0], 0, 0, 1); }\n";
2145 
2146     GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
2147     EXPECT_NE(0u, program);
2148 }
2149 
2150 // Verify that non-const index used on an array returned by a function compiles
TEST_P(GLSLTest_ES3,ReturnArrayOfStructsThenNonConstIndex)2151 TEST_P(GLSLTest_ES3, ReturnArrayOfStructsThenNonConstIndex)
2152 {
2153     constexpr char kVS[] = R"(#version 300 es
2154 in float v_varying;
2155 struct s { float a; int b; vec2 c; };
2156 s[2] f()
2157 {
2158     return s[2](s(v_varying, 1, vec2(1.0, 1.0)), s(v_varying / 2.0, 1, vec2(1.0, 1.0)));
2159 }
2160 void main()
2161 {
2162     gl_Position = vec4(f()[uint(v_varying)].a, 0, 0, 1);
2163 })";
2164 
2165     GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
2166     EXPECT_NE(0u, program);
2167 }
2168 
2169 // Verify that using invariant(all) in both shaders fails in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantAllBoth)2170 TEST_P(GLSLTest_ES3, InvariantAllBoth)
2171 {
2172     constexpr char kFS[] =
2173         "#version 300 es\n"
2174         "#pragma STDGL invariant(all)\n"
2175         "precision mediump float;\n"
2176         "in float v_varying;\n"
2177         "out vec4 my_FragColor;\n"
2178         "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
2179 
2180     constexpr char kVS[] =
2181         "#version 300 es\n"
2182         "#pragma STDGL invariant(all)\n"
2183         "in vec4 a_position;\n"
2184         "out float v_varying;\n"
2185         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
2186 
2187     GLuint program = CompileProgram(kVS, kFS);
2188     EXPECT_EQ(0u, program);
2189 }
2190 
2191 // Verify that using invariant(all) only in fragment shader succeeds in ESSL 1.00.
TEST_P(GLSLTest,InvariantAllIn)2192 TEST_P(GLSLTest, InvariantAllIn)
2193 {
2194     constexpr char kFS[] =
2195         "#pragma STDGL invariant(all)\n"
2196         "precision mediump float;\n"
2197         "varying float v_varying;\n"
2198         "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
2199 
2200     constexpr char kVS[] =
2201         "attribute vec4 a_position;\n"
2202         "varying float v_varying;\n"
2203         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
2204 
2205     GLuint program = CompileProgram(kVS, kFS);
2206     EXPECT_NE(0u, program);
2207 }
2208 
2209 // Verify that using invariant(all) only in fragment shader fails in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantAllIn)2210 TEST_P(GLSLTest_ES3, InvariantAllIn)
2211 {
2212     constexpr char kFS[] =
2213         "#version 300 es\n"
2214         "#pragma STDGL invariant(all)\n"
2215         "precision mediump float;\n"
2216         "in float v_varying;\n"
2217         "out vec4 my_FragColor;\n"
2218         "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
2219 
2220     constexpr char kVS[] =
2221         "#version 300 es\n"
2222         "in vec4 a_position;\n"
2223         "out float v_varying;\n"
2224         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
2225 
2226     GLuint program = CompileProgram(kVS, kFS);
2227     EXPECT_EQ(0u, program);
2228 }
2229 
2230 // Verify that using invariant(all) only in vertex shader fails in ESSL 1.00.
TEST_P(GLSLTest,InvariantAllOut)2231 TEST_P(GLSLTest, InvariantAllOut)
2232 {
2233     constexpr char kFS[] =
2234         "precision mediump float;\n"
2235         "varying float v_varying;\n"
2236         "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
2237 
2238     constexpr char kVS[] =
2239         "#pragma STDGL invariant(all)\n"
2240         "attribute vec4 a_position;\n"
2241         "varying float v_varying;\n"
2242         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
2243 
2244     GLuint program = CompileProgram(kVS, kFS);
2245     EXPECT_EQ(0u, program);
2246 }
2247 
2248 // Verify that using invariant(all) only in vertex shader succeeds in ESSL 3.00.
TEST_P(GLSLTest_ES3,InvariantAllOut)2249 TEST_P(GLSLTest_ES3, InvariantAllOut)
2250 {
2251     // TODO: ESSL 3.00 -> GLSL 1.20 translation should add "invariant" in fragment shader
2252     // for varyings which are invariant in vertex shader,
2253     // because of invariant(all) being used in vertex shader (http://anglebug.com/40096344)
2254     ANGLE_SKIP_TEST_IF(IsDesktopOpenGL());
2255 
2256     constexpr char kFS[] =
2257         "#version 300 es\n"
2258         "precision mediump float;\n"
2259         "in float v_varying;\n"
2260         "out vec4 my_FragColor;\n"
2261         "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
2262 
2263     constexpr char kVS[] =
2264         "#version 300 es\n"
2265         "#pragma STDGL invariant(all)\n"
2266         "in vec4 a_position;\n"
2267         "out float v_varying;\n"
2268         "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
2269 
2270     GLuint program = CompileProgram(kVS, kFS);
2271     EXPECT_NE(0u, program);
2272 }
2273 
TEST_P(GLSLTest,MaxVaryingVec4)2274 TEST_P(GLSLTest, MaxVaryingVec4)
2275 {
2276     // TODO(geofflang): Find out why this doesn't compile on Apple AMD OpenGL drivers
2277     // (http://anglebug.com/42260302)
2278     ANGLE_SKIP_TEST_IF(IsMac() && IsAMD() && IsOpenGL());
2279 
2280     GLint maxVaryings = 0;
2281     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2282 
2283     VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, false, false, false, true);
2284 }
2285 
2286 // Verify we can pack registers with one builtin varying.
TEST_P(GLSLTest,MaxVaryingVec4_OneBuiltin)2287 TEST_P(GLSLTest, MaxVaryingVec4_OneBuiltin)
2288 {
2289     GLint maxVaryings = 0;
2290     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2291 
2292     // Generate shader code that uses gl_FragCoord.
2293     VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 1, 0, true, false, false, true);
2294 }
2295 
2296 // Verify we can pack registers with two builtin varyings.
TEST_P(GLSLTest,MaxVaryingVec4_TwoBuiltins)2297 TEST_P(GLSLTest, MaxVaryingVec4_TwoBuiltins)
2298 {
2299     GLint maxVaryings = 0;
2300     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2301 
2302     // Generate shader code that uses gl_FragCoord and gl_PointCoord.
2303     VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 2, 0, true, true, false, true);
2304 }
2305 
2306 // Verify we can pack registers with three builtin varyings.
TEST_P(GLSLTest,MaxVaryingVec4_ThreeBuiltins)2307 TEST_P(GLSLTest, MaxVaryingVec4_ThreeBuiltins)
2308 {
2309     GLint maxVaryings = 0;
2310     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2311 
2312     // Generate shader code that uses gl_FragCoord, gl_PointCoord and gl_PointSize.
2313     VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings - 3, 0, true, true, true, true);
2314 }
2315 
2316 // This covers a problematic case in D3D9 - we are limited by the number of available semantics,
2317 // rather than total register use.
TEST_P(GLSLTest,MaxVaryingsSpecialCases)2318 TEST_P(GLSLTest, MaxVaryingsSpecialCases)
2319 {
2320     ANGLE_SKIP_TEST_IF(!IsD3D9());
2321 
2322     GLint maxVaryings = 0;
2323     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2324 
2325     VaryingTestBase(maxVaryings, 0, 0, 0, 0, 0, 0, 0, true, false, false, false);
2326     VaryingTestBase(maxVaryings - 1, 0, 0, 0, 0, 0, 0, 0, true, true, false, false);
2327     VaryingTestBase(maxVaryings - 2, 0, 0, 0, 0, 0, 0, 0, true, true, false, true);
2328 
2329     // Special case for gl_PointSize: we get it for free on D3D9.
2330     VaryingTestBase(maxVaryings - 2, 0, 0, 0, 0, 0, 0, 0, true, true, true, true);
2331 }
2332 
2333 // This covers a problematic case in D3D9 - we are limited by the number of available semantics,
2334 // rather than total register use.
TEST_P(GLSLTest,MaxMinusTwoVaryingVec2PlusOneSpecialVariable)2335 TEST_P(GLSLTest, MaxMinusTwoVaryingVec2PlusOneSpecialVariable)
2336 {
2337     GLint maxVaryings = 0;
2338     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2339 
2340     // Generate shader code that uses gl_FragCoord.
2341     VaryingTestBase(0, 0, maxVaryings, 0, 0, 0, 0, 0, true, false, false, !IsD3D9());
2342 }
2343 
TEST_P(GLSLTest,MaxVaryingVec3)2344 TEST_P(GLSLTest, MaxVaryingVec3)
2345 {
2346     GLint maxVaryings = 0;
2347     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2348 
2349     VaryingTestBase(0, 0, 0, 0, maxVaryings, 0, 0, 0, false, false, false, true);
2350 }
2351 
TEST_P(GLSLTest,MaxVaryingVec3Array)2352 TEST_P(GLSLTest, MaxVaryingVec3Array)
2353 {
2354     GLint maxVaryings = 0;
2355     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2356 
2357     VaryingTestBase(0, 0, 0, 0, 0, maxVaryings / 2, 0, 0, false, false, false, true);
2358 }
2359 
2360 // Only fails on D3D9 because of packing limitations.
TEST_P(GLSLTest,MaxVaryingVec3AndOneFloat)2361 TEST_P(GLSLTest, MaxVaryingVec3AndOneFloat)
2362 {
2363     GLint maxVaryings = 0;
2364     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2365 
2366     VaryingTestBase(1, 0, 0, 0, maxVaryings, 0, 0, 0, false, false, false, !IsD3D9());
2367 }
2368 
2369 // Only fails on D3D9 because of packing limitations.
TEST_P(GLSLTest,MaxVaryingVec3ArrayAndOneFloatArray)2370 TEST_P(GLSLTest, MaxVaryingVec3ArrayAndOneFloatArray)
2371 {
2372     GLint maxVaryings = 0;
2373     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2374 
2375     VaryingTestBase(0, 1, 0, 0, 0, maxVaryings / 2, 0, 0, false, false, false, !IsD3D9());
2376 }
2377 
2378 // Only fails on D3D9 because of packing limitations.
TEST_P(GLSLTest,TwiceMaxVaryingVec2)2379 TEST_P(GLSLTest, TwiceMaxVaryingVec2)
2380 {
2381     // TODO(geofflang): Figure out why this fails on NVIDIA's GLES driver
2382     // (http://anglebug.com/42262492)
2383     ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGLES());
2384 
2385     // TODO(geofflang): Find out why this doesn't compile on Apple AMD OpenGL drivers
2386     // (http://anglebug.com/42260302)
2387     ANGLE_SKIP_TEST_IF(IsMac() && IsAMD() && IsOpenGL());
2388 
2389     GLint maxVaryings = 0;
2390     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2391 
2392     VaryingTestBase(0, 0, 2 * maxVaryings, 0, 0, 0, 0, 0, false, false, false, !IsD3D9());
2393 }
2394 
2395 // Disabled because of a failure in D3D9
TEST_P(GLSLTest,MaxVaryingVec2Arrays)2396 TEST_P(GLSLTest, MaxVaryingVec2Arrays)
2397 {
2398     ANGLE_SKIP_TEST_IF(IsD3D9());
2399 
2400     // TODO(geofflang): Figure out why this fails on NVIDIA's GLES driver
2401     ANGLE_SKIP_TEST_IF(IsOpenGLES());
2402 
2403     // TODO(geofflang): Find out why this doesn't compile on Apple AMD OpenGL drivers
2404     // (http://anglebug.com/42260302)
2405     ANGLE_SKIP_TEST_IF(IsMac() && IsAMD() && IsOpenGL());
2406 
2407     GLint maxVaryings = 0;
2408     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2409 
2410     // Special case: because arrays of mat2 are packed as small grids of two rows by two columns,
2411     // we should be aware that when we're packing into an odd number of varying registers the
2412     // last row will be empty and can not fit the final vec2 arrary.
2413     GLint maxVec2Arrays = (maxVaryings >> 1) << 1;
2414 
2415     VaryingTestBase(0, 0, 0, maxVec2Arrays, 0, 0, 0, 0, false, false, false, true);
2416 }
2417 
2418 // Verify max varying with feedback and gl_line enabled
TEST_P(GLSLTest_ES3,MaxVaryingWithFeedbackAndGLline)2419 TEST_P(GLSLTest_ES3, MaxVaryingWithFeedbackAndGLline)
2420 {
2421     // (http://anglebug.com/42263058)
2422     ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsVulkan());
2423 
2424     // http://anglebug.com/42263066
2425     ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
2426 
2427     GLint maxVaryings = 0;
2428     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
2429 
2430     std::stringstream vertexShaderSource;
2431     std::stringstream fragmentShaderSource;
2432 
2433     // substract 1 here for gl_PointSize
2434     const GLint vec4Count     = maxVaryings - 1;
2435     unsigned int varyingCount = 0;
2436     std::string varyingDeclaration;
2437     for (GLint i = 0; i < vec4Count; i++)
2438     {
2439         varyingDeclaration += GenerateVectorVaryingDeclaration(4, 1, varyingCount);
2440         varyingCount += 1;
2441     }
2442     // Generate the vertex shader
2443     vertexShaderSource.clear();
2444     vertexShaderSource << varyingDeclaration;
2445     vertexShaderSource << "\nattribute vec4 a_position;\n";
2446     vertexShaderSource << "\nvoid main()\n{\n";
2447     unsigned int currentVSVarying = 0;
2448     for (GLint i = 0; i < vec4Count; i++)
2449     {
2450         vertexShaderSource << GenerateVectorVaryingSettingCode(4, 1, currentVSVarying);
2451         currentVSVarying += 1;
2452     }
2453     vertexShaderSource << "\tgl_Position = vec4(a_position.rgb, 1);\n";
2454     vertexShaderSource << "\tgl_PointSize = 1.0;\n";
2455     vertexShaderSource << "}\n";
2456 
2457     // Generate the fragment shader
2458     fragmentShaderSource.clear();
2459     fragmentShaderSource << "precision highp float;\n";
2460     fragmentShaderSource << varyingDeclaration;
2461     fragmentShaderSource << "\nvoid main() \n{ \n\tvec4 retColor = vec4(0,0,0,0);\n";
2462     unsigned int currentFSVarying = 0;
2463     // Make use of the vec4 varyings
2464     fragmentShaderSource << "\tretColor += ";
2465     for (GLint i = 0; i < vec4Count; i++)
2466     {
2467         fragmentShaderSource << GenerateVectorVaryingUseCode(1, currentFSVarying);
2468         currentFSVarying += 1;
2469     }
2470     fragmentShaderSource << "vec4(0.0, 0.0, 0.0, 0.0);\n";
2471     constexpr GLuint testValue = 234;
2472     fragmentShaderSource << "\tgl_FragColor = (retColor/vec4(" << std::to_string(currentFSVarying)
2473                          << ")) /255.0*" << std::to_string(testValue) << ".0;\n";
2474     fragmentShaderSource << "}\n";
2475 
2476     std::vector<std::string> tfVaryings = {"gl_Position", "gl_PointSize"};
2477     ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(program1, vertexShaderSource.str().c_str(),
2478                                         fragmentShaderSource.str().c_str(), tfVaryings,
2479                                         GL_INTERLEAVED_ATTRIBS);
2480 
2481     GLBuffer xfbBuffer;
2482     glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfbBuffer);
2483     glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 6 * (sizeof(float[4]) + sizeof(float)), nullptr,
2484                  GL_STATIC_DRAW);
2485 
2486     GLTransformFeedback xfb;
2487     glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, xfb);
2488     glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, xfbBuffer);
2489 
2490     glUseProgram(program1);
2491 
2492     const GLint positionLocation = glGetAttribLocation(program1, essl1_shaders::PositionAttrib());
2493     GLBuffer vertexBuffer;
2494     // need to shift half pixel to make sure the line covers the center of the pixel
2495     const Vector3 vertices[2] = {
2496         {-1.0f, -1.0f + 0.5f / static_cast<float>(getWindowHeight()), 0.0f},
2497         {1.0f, -1.0f + 0.5f / static_cast<float>(getWindowHeight()), 0.0f}};
2498     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
2499     glBufferData(GL_ARRAY_BUFFER, sizeof(*vertices) * 2, vertices, GL_STATIC_DRAW);
2500     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
2501     glEnableVertexAttribArray(positionLocation);
2502 
2503     glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
2504     glClear(GL_COLOR_BUFFER_BIT);
2505 
2506     glBeginTransformFeedback(GL_LINES);
2507     glDrawArrays(GL_LINES, 0, 2);
2508     glEndTransformFeedback();
2509 
2510     ASSERT_GL_NO_ERROR();
2511 
2512     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(testValue, testValue, testValue, testValue));
2513 }
2514 
2515 // Verify shader source with a fixed length that is less than the null-terminated length will
2516 // compile.
TEST_P(GLSLTest,FixedShaderLength)2517 TEST_P(GLSLTest, FixedShaderLength)
2518 {
2519     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
2520 
2521     const std::string appendGarbage = "abcdefghijklmnopqrstuvwxyz";
2522     const std::string source   = "void main() { gl_FragColor = vec4(0, 0, 0, 0); }" + appendGarbage;
2523     const char *sourceArray[1] = {source.c_str()};
2524     GLint lengths[1]           = {static_cast<GLint>(source.length() - appendGarbage.length())};
2525     glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
2526     glCompileShader(shader);
2527 
2528     GLint compileResult;
2529     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
2530     EXPECT_NE(compileResult, 0);
2531 }
2532 
2533 // Verify that a negative shader source length is treated as a null-terminated length.
TEST_P(GLSLTest,NegativeShaderLength)2534 TEST_P(GLSLTest, NegativeShaderLength)
2535 {
2536     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
2537 
2538     const char *sourceArray[1] = {essl1_shaders::fs::Red()};
2539     GLint lengths[1]           = {-10};
2540     glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
2541     glCompileShader(shader);
2542 
2543     GLint compileResult;
2544     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
2545     EXPECT_NE(compileResult, 0);
2546 }
2547 
2548 // Check that having an invalid char after the "." doesn't cause an assert.
TEST_P(GLSLTest,InvalidFieldFirstChar)2549 TEST_P(GLSLTest, InvalidFieldFirstChar)
2550 {
2551     GLuint shader      = glCreateShader(GL_VERTEX_SHADER);
2552     const char *source = "void main() {vec4 x; x.}";
2553     glShaderSource(shader, 1, &source, 0);
2554     glCompileShader(shader);
2555 
2556     GLint compileResult;
2557     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
2558     EXPECT_EQ(0, compileResult);
2559 }
2560 
2561 // Verify that a length array with mixed positive and negative values compiles.
TEST_P(GLSLTest,MixedShaderLengths)2562 TEST_P(GLSLTest, MixedShaderLengths)
2563 {
2564     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
2565 
2566     const char *sourceArray[] = {
2567         "void main()",
2568         "{",
2569         "    gl_FragColor = vec4(0, 0, 0, 0);",
2570         "}",
2571     };
2572     GLint lengths[] = {
2573         -10,
2574         1,
2575         static_cast<GLint>(strlen(sourceArray[2])),
2576         -1,
2577     };
2578     ASSERT_EQ(ArraySize(sourceArray), ArraySize(lengths));
2579 
2580     glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
2581     glCompileShader(shader);
2582 
2583     GLint compileResult;
2584     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
2585     EXPECT_NE(compileResult, 0);
2586 }
2587 
2588 // Verify that zero-length shader source does not affect shader compilation.
TEST_P(GLSLTest,ZeroShaderLength)2589 TEST_P(GLSLTest, ZeroShaderLength)
2590 {
2591     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
2592 
2593     const char *sourceArray[] = {
2594         "abcdefg", "34534", "void main() { gl_FragColor = vec4(0, 0, 0, 0); }", "", "abcdefghijklm",
2595     };
2596     GLint lengths[] = {
2597         0, 0, -1, 0, 0,
2598     };
2599     ASSERT_EQ(ArraySize(sourceArray), ArraySize(lengths));
2600 
2601     glShaderSource(shader, static_cast<GLsizei>(ArraySize(sourceArray)), sourceArray, lengths);
2602     glCompileShader(shader);
2603 
2604     GLint compileResult;
2605     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
2606     EXPECT_NE(compileResult, 0);
2607 }
2608 
2609 // Tests that bad index expressions don't crash ANGLE's translator.
2610 // https://code.google.com/p/angleproject/issues/detail?id=857
TEST_P(GLSLTest,BadIndexBug)2611 TEST_P(GLSLTest, BadIndexBug)
2612 {
2613     constexpr char kFSSourceVec[] =
2614         "precision mediump float;\n"
2615         "uniform vec4 uniformVec;\n"
2616         "void main()\n"
2617         "{\n"
2618         "    gl_FragColor = vec4(uniformVec[int()]);\n"
2619         "}";
2620 
2621     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFSSourceVec);
2622     EXPECT_EQ(0u, shader);
2623 
2624     if (shader != 0)
2625     {
2626         glDeleteShader(shader);
2627     }
2628 
2629     constexpr char kFSSourceMat[] =
2630         "precision mediump float;\n"
2631         "uniform mat4 uniformMat;\n"
2632         "void main()\n"
2633         "{\n"
2634         "    gl_FragColor = vec4(uniformMat[int()]);\n"
2635         "}";
2636 
2637     shader = CompileShader(GL_FRAGMENT_SHADER, kFSSourceMat);
2638     EXPECT_EQ(0u, shader);
2639 
2640     if (shader != 0)
2641     {
2642         glDeleteShader(shader);
2643     }
2644 
2645     constexpr char kFSSourceArray[] =
2646         "precision mediump float;\n"
2647         "uniform vec4 uniformArray;\n"
2648         "void main()\n"
2649         "{\n"
2650         "    gl_FragColor = vec4(uniformArray[int()]);\n"
2651         "}";
2652 
2653     shader = CompileShader(GL_FRAGMENT_SHADER, kFSSourceArray);
2654     EXPECT_EQ(0u, shader);
2655 
2656     if (shader != 0)
2657     {
2658         glDeleteShader(shader);
2659     }
2660 }
2661 
2662 // Test that structs defined in uniforms are translated correctly.
TEST_P(GLSLTest,StructSpecifiersUniforms)2663 TEST_P(GLSLTest, StructSpecifiersUniforms)
2664 {
2665     constexpr char kFS[] = R"(precision mediump float;
2666 
2667 uniform struct S { float field; } s;
2668 
2669 void main()
2670 {
2671     gl_FragColor = vec4(1, 0, 0, 1);
2672     gl_FragColor.a += s.field;
2673 })";
2674 
2675     GLuint program = CompileProgram(essl1_shaders::vs::Simple(), kFS);
2676     EXPECT_NE(0u, program);
2677 }
2678 
2679 // Test that structs declaration followed directly by an initialization is translated correctly.
TEST_P(GLSLTest,StructWithInitializer)2680 TEST_P(GLSLTest, StructWithInitializer)
2681 {
2682     constexpr char kFS[] = R"(precision mediump float;
2683 
2684 struct S { float a; } s = S(1.0);
2685 
2686 void main()
2687 {
2688     gl_FragColor = vec4(0, 0, 0, 1);
2689     gl_FragColor.r += s.a;
2690 })";
2691 
2692     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
2693     glUseProgram(program);
2694 
2695     // Test drawing, should be red.
2696     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2697 
2698     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2699     EXPECT_GL_NO_ERROR();
2700 }
2701 
2702 // Test that structs without initializer, followed by a uniform usage works as expected.
TEST_P(GLSLTest,UniformStructWithoutInitializer)2703 TEST_P(GLSLTest, UniformStructWithoutInitializer)
2704 {
2705     constexpr char kFS[] = R"(precision mediump float;
2706 
2707 struct S { float a; };
2708 uniform S u_s;
2709 
2710 void main()
2711 {
2712     gl_FragColor = vec4(u_s.a);
2713 })";
2714 
2715     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
2716     glUseProgram(program);
2717 
2718     // Test drawing, should be red.
2719     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2720 
2721     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
2722     EXPECT_GL_NO_ERROR();
2723 }
2724 
2725 // Test that structs declaration followed directly by an initialization in a uniform.
TEST_P(GLSLTest,StructWithUniformInitializer)2726 TEST_P(GLSLTest, StructWithUniformInitializer)
2727 {
2728     constexpr char kFS[] = R"(precision mediump float;
2729 
2730 struct S { float a; } s = S(1.0);
2731 uniform S us;
2732 
2733 void main()
2734 {
2735     gl_FragColor = vec4(0, 0, 0, 1);
2736     gl_FragColor.r += s.a;
2737     gl_FragColor.g += us.a;
2738 })";
2739 
2740     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
2741     glUseProgram(program);
2742 
2743     // Test drawing, should be red.
2744     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2745 
2746     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2747     EXPECT_GL_NO_ERROR();
2748 }
2749 
2750 // Test that gl_DepthRange is not stored as a uniform location. Since uniforms
2751 // beginning with "gl_" are filtered out by our validation logic, we must
2752 // bypass the validation to test the behaviour of the implementation.
2753 // (note this test is still Impl-independent)
TEST_P(GLSLTestNoValidation,DepthRangeUniforms)2754 TEST_P(GLSLTestNoValidation, DepthRangeUniforms)
2755 {
2756     constexpr char kFS[] = R"(precision mediump float;
2757 
2758 void main()
2759 {
2760     gl_FragColor = vec4(gl_DepthRange.near, gl_DepthRange.far, gl_DepthRange.diff, 1);
2761 })";
2762 
2763     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
2764 
2765     // We need to bypass validation for this call.
2766     GLint nearIndex = glGetUniformLocation(program, "gl_DepthRange.near");
2767     EXPECT_EQ(-1, nearIndex);
2768 
2769     // Test drawing does not throw an exception.
2770     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2771 
2772     EXPECT_GL_NO_ERROR();
2773 }
2774 
GenerateSmallPowShader(double base,double exponent)2775 std::string GenerateSmallPowShader(double base, double exponent)
2776 {
2777     std::stringstream stream;
2778 
2779     stream.precision(8);
2780 
2781     double result = pow(base, exponent);
2782 
2783     stream << "precision highp float;\n"
2784            << "float fun(float arg)\n"
2785            << "{\n"
2786            << "    return pow(arg, " << std::fixed << exponent << ");\n"
2787            << "}\n"
2788            << "\n"
2789            << "void main()\n"
2790            << "{\n"
2791            << "    const float a = " << std::scientific << base << ";\n"
2792            << "    float b = fun(a);\n"
2793            << "    if (abs(" << result << " - b) < " << std::abs(result * 0.001) << ")\n"
2794            << "    {\n"
2795            << "        gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
2796            << "    }\n"
2797            << "    else\n"
2798            << "    {\n"
2799            << "        gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
2800            << "    }\n"
2801            << "}\n";
2802 
2803     return stream.str();
2804 }
2805 
2806 // Covers the WebGL test 'glsl/bugs/pow-of-small-constant-in-user-defined-function'
2807 // See http://anglebug.com/40096900
TEST_P(GLSLTest,PowOfSmallConstant)2808 TEST_P(GLSLTest, PowOfSmallConstant)
2809 {
2810     // Test with problematic exponents that are close to an integer.
2811     std::vector<double> testExponents;
2812     std::array<double, 5> epsilonMultipliers = {-100.0, -1.0, 0.0, 1.0, 100.0};
2813     for (double epsilonMultiplier : epsilonMultipliers)
2814     {
2815         for (int i = -4; i <= 5; ++i)
2816         {
2817             if (i >= -1 && i <= 1)
2818                 continue;
2819             const double epsilon = 1.0e-8;
2820             double bad           = static_cast<double>(i) + epsilonMultiplier * epsilon;
2821             testExponents.push_back(bad);
2822         }
2823     }
2824 
2825     // Also test with a few exponents that are not close to an integer.
2826     testExponents.push_back(3.6);
2827     testExponents.push_back(3.4);
2828 
2829     for (double testExponent : testExponents)
2830     {
2831         const std::string &fragmentShaderSource = GenerateSmallPowShader(1.0e-6, testExponent);
2832 
2833         ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), fragmentShaderSource.c_str());
2834 
2835         drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2836 
2837         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2838         EXPECT_GL_NO_ERROR();
2839     }
2840 }
2841 
2842 // Test fragment shaders which contain non-constant loop indexers
TEST_P(GLSLTest,LoopIndexingValidation)2843 TEST_P(GLSLTest, LoopIndexingValidation)
2844 {
2845     constexpr char kFS[] = R"(precision mediump float;
2846 
2847 uniform float loopMax;
2848 
2849 void main()
2850 {
2851     gl_FragColor = vec4(1, 0, 0, 1);
2852     for (float l = 0.0; l < loopMax; l++)
2853     {
2854         if (loopMax > 3.0)
2855         {
2856             gl_FragColor.a += 0.1;
2857         }
2858     }
2859 })";
2860 
2861     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
2862 
2863     const char *sourceArray[1] = {kFS};
2864     glShaderSource(shader, 1, sourceArray, nullptr);
2865     glCompileShader(shader);
2866 
2867     GLint compileResult;
2868     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
2869 
2870     // If the test is configured to run limited to Feature Level 9_3, then it is
2871     // assumed that shader compilation will fail with an expected error message containing
2872     // "Loop index cannot be compared with non-constant expression"
2873     if (GetParam() == ES2_D3D9())
2874     {
2875         if (compileResult != 0)
2876         {
2877             FAIL() << "Shader compilation succeeded, expected failure";
2878         }
2879         else
2880         {
2881             GLint infoLogLength;
2882             glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
2883 
2884             std::string infoLog;
2885             infoLog.resize(infoLogLength);
2886             glGetShaderInfoLog(shader, static_cast<GLsizei>(infoLog.size()), nullptr, &infoLog[0]);
2887 
2888             if (infoLog.find("Loop index cannot be compared with non-constant expression") ==
2889                 std::string::npos)
2890             {
2891                 FAIL() << "Shader compilation failed with unexpected error message";
2892             }
2893         }
2894     }
2895     else
2896     {
2897         EXPECT_NE(0, compileResult);
2898     }
2899 
2900     if (shader != 0)
2901     {
2902         glDeleteShader(shader);
2903     }
2904 }
2905 
2906 // Tests that the maximum uniforms count returned from querying GL_MAX_VERTEX_UNIFORM_VECTORS
2907 // can actually be used.
TEST_P(GLSLTest,VerifyMaxVertexUniformVectors)2908 TEST_P(GLSLTest, VerifyMaxVertexUniformVectors)
2909 {
2910     // crbug.com/680631
2911     ANGLE_SKIP_TEST_IF(IsOzone() && IsIntel());
2912 
2913     int maxUniforms = 10000;
2914     glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
2915     EXPECT_GL_NO_ERROR();
2916     std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS = " << maxUniforms << std::endl;
2917 
2918     CompileGLSLWithUniformsAndSamplers(maxUniforms, 0, 0, 0, true);
2919 }
2920 
2921 // Tests that the maximum uniforms count returned from querying GL_MAX_VERTEX_UNIFORM_VECTORS
2922 // can actually be used along with the maximum number of texture samplers.
TEST_P(GLSLTest,VerifyMaxVertexUniformVectorsWithSamplers)2923 TEST_P(GLSLTest, VerifyMaxVertexUniformVectorsWithSamplers)
2924 {
2925     ANGLE_SKIP_TEST_IF(IsOpenGL() || IsOpenGLES());
2926 
2927     // Times out on D3D11 on test infra. http://anglebug.com/42263645
2928     ANGLE_SKIP_TEST_IF(IsD3D11() && IsIntel());
2929 
2930     int maxUniforms = 10000;
2931     glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
2932     EXPECT_GL_NO_ERROR();
2933     std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS = " << maxUniforms << std::endl;
2934 
2935     int maxTextureImageUnits = 0;
2936     glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
2937 
2938     CompileGLSLWithUniformsAndSamplers(maxUniforms, 0, maxTextureImageUnits, 0, true);
2939 }
2940 
2941 // Tests that the maximum uniforms count + 1 from querying GL_MAX_VERTEX_UNIFORM_VECTORS
2942 // fails shader compilation.
TEST_P(GLSLTest,VerifyMaxVertexUniformVectorsExceeded)2943 TEST_P(GLSLTest, VerifyMaxVertexUniformVectorsExceeded)
2944 {
2945     int maxUniforms = 10000;
2946     glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxUniforms);
2947     EXPECT_GL_NO_ERROR();
2948     std::cout << "Validating GL_MAX_VERTEX_UNIFORM_VECTORS + 1 = " << maxUniforms + 1 << std::endl;
2949 
2950     CompileGLSLWithUniformsAndSamplers(maxUniforms + 1, 0, 0, 0, false);
2951 }
2952 
2953 // Tests that the maximum uniforms count returned from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
2954 // can actually be used.
TEST_P(GLSLTest,VerifyMaxFragmentUniformVectors)2955 TEST_P(GLSLTest, VerifyMaxFragmentUniformVectors)
2956 {
2957     // crbug.com/680631
2958     ANGLE_SKIP_TEST_IF(IsOzone() && IsIntel());
2959 
2960     int maxUniforms = 10000;
2961     glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
2962     EXPECT_GL_NO_ERROR();
2963     std::cout << "Validating GL_MAX_FRAGMENT_UNIFORM_VECTORS = " << maxUniforms << std::endl;
2964 
2965     CompileGLSLWithUniformsAndSamplers(0, maxUniforms, 0, 0, true);
2966 }
2967 
2968 // Tests that the maximum uniforms count returned from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
2969 // can actually be used along with the maximum number of texture samplers.
TEST_P(GLSLTest,VerifyMaxFragmentUniformVectorsWithSamplers)2970 TEST_P(GLSLTest, VerifyMaxFragmentUniformVectorsWithSamplers)
2971 {
2972     ANGLE_SKIP_TEST_IF(IsOpenGL() || IsOpenGLES());
2973 
2974     int maxUniforms = 10000;
2975     glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
2976     EXPECT_GL_NO_ERROR();
2977 
2978     int maxTextureImageUnits = 0;
2979     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
2980 
2981     CompileGLSLWithUniformsAndSamplers(0, maxUniforms, 0, maxTextureImageUnits, true);
2982 }
2983 
2984 // Tests that the maximum uniforms count + 1 from querying GL_MAX_FRAGMENT_UNIFORM_VECTORS
2985 // fails shader compilation.
TEST_P(GLSLTest,VerifyMaxFragmentUniformVectorsExceeded)2986 TEST_P(GLSLTest, VerifyMaxFragmentUniformVectorsExceeded)
2987 {
2988     int maxUniforms = 10000;
2989     glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxUniforms);
2990     EXPECT_GL_NO_ERROR();
2991     std::cout << "Validating GL_MAX_FRAGMENT_UNIFORM_VECTORS + 1 = " << maxUniforms + 1
2992               << std::endl;
2993 
2994     CompileGLSLWithUniformsAndSamplers(0, maxUniforms + 1, 0, 0, false);
2995 }
2996 
2997 // Test compiling shaders using the GL_EXT_shader_texture_lod extension
TEST_P(GLSLTest,TextureLOD)2998 TEST_P(GLSLTest, TextureLOD)
2999 {
3000     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_texture_lod"));
3001 
3002     constexpr char kFS[] =
3003         "#extension GL_EXT_shader_texture_lod : require\n"
3004         "uniform sampler2D u_texture;\n"
3005         "void main() {\n"
3006         "    gl_FragColor = texture2DGradEXT(u_texture, vec2(0.0, 0.0), vec2(0.0, 0.0), vec2(0.0, "
3007         "0.0));\n"
3008         "}\n";
3009 
3010     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
3011     ASSERT_NE(0u, shader);
3012     glDeleteShader(shader);
3013 }
3014 
3015 // HLSL generates extra lod0 variants of functions. There was a bug that incorrectly reworte
3016 // function calls to use them in vertex shaders.  http://anglebug.com/42262136
TEST_P(GLSLTest,TextureLODRewriteInVertexShader)3017 TEST_P(GLSLTest, TextureLODRewriteInVertexShader)
3018 {
3019     constexpr char kVS[] = R"(
3020   precision highp float;
3021   uniform int uni;
3022   uniform sampler2D texture;
3023 
3024   vec4 A();
3025 
3026   vec4 B() {
3027     vec4 a;
3028     for(int r=0; r<14; r++){
3029       if (r < uni) return vec4(0.0);
3030       a = A();
3031     }
3032     return a;
3033   }
3034 
3035   vec4 A() {
3036     return texture2D(texture, vec2(0.0, 0.0));
3037   }
3038 
3039   void main() {
3040     gl_Position = B();
3041   })";
3042 
3043     constexpr char kFS[] = R"(
3044 void main() { gl_FragColor = vec4(gl_FragCoord.x / 640.0, gl_FragCoord.y / 480.0, 0, 1); }
3045 )";
3046 
3047     ANGLE_GL_PROGRAM(program, kVS, kFS);
3048 }
3049 
3050 // Test to verify the a shader can have a sampler unused in a vertex shader
3051 // but used in the fragment shader.
TEST_P(GLSLTest,VerifySamplerInBothVertexAndFragmentShaders)3052 TEST_P(GLSLTest, VerifySamplerInBothVertexAndFragmentShaders)
3053 {
3054     constexpr char kVS[] = R"(
3055 attribute vec2 position;
3056 varying mediump vec2 texCoord;
3057 uniform sampler2D tex;
3058 void main()
3059 {
3060     gl_Position = vec4(position, 0, 1);
3061     texCoord = position * 0.5 + vec2(0.5);
3062 })";
3063 
3064     constexpr char kFS[] = R"(
3065 varying mediump vec2 texCoord;
3066 uniform sampler2D tex;
3067 void main()
3068 {
3069     gl_FragColor = texture2D(tex, texCoord);
3070 })";
3071 
3072     ANGLE_GL_PROGRAM(program, kVS, kFS);
3073 
3074     // Initialize basic red texture.
3075     const std::vector<GLColor> redColors(4, GLColor::red);
3076     GLTexture texture;
3077     glBindTexture(GL_TEXTURE_2D, texture);
3078     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, redColors.data());
3079     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3080     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3081     ASSERT_GL_NO_ERROR();
3082 
3083     drawQuad(program, "position", 0.0f);
3084 
3085     EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::red);
3086 }
3087 
3088 // Test that array of structs containing array of samplers work as expected.
TEST_P(GLSLTest,ArrayOfStructContainingArrayOfSamplers)3089 TEST_P(GLSLTest, ArrayOfStructContainingArrayOfSamplers)
3090 {
3091     constexpr char kFS[] =
3092         "precision mediump float;\n"
3093         "struct Data { mediump sampler2D data[2]; };\n"
3094         "uniform Data test[2];\n"
3095         "void main() {\n"
3096         "    gl_FragColor = vec4(texture2D(test[1].data[1], vec2(0.0, 0.0)).r,\n"
3097         "                        texture2D(test[1].data[0], vec2(0.0, 0.0)).r,\n"
3098         "                        texture2D(test[0].data[1], vec2(0.0, 0.0)).r,\n"
3099         "                        texture2D(test[0].data[0], vec2(0.0, 0.0)).r);\n"
3100         "}\n";
3101 
3102     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
3103     glUseProgram(program);
3104     GLTexture textures[4];
3105     GLColor expected = MakeGLColor(32, 64, 96, 255);
3106     GLubyte data[8]  = {};  // 4 bytes of padding, so that texture can be initialized with 4 bytes
3107     memcpy(data, expected.data(), sizeof(expected));
3108     for (int i = 0; i < 4; i++)
3109     {
3110         int outerIdx = i % 2;
3111         int innerIdx = i / 2;
3112         glActiveTexture(GL_TEXTURE0 + i);
3113         glBindTexture(GL_TEXTURE_2D, textures[i]);
3114         // Each element provides two components.
3115         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data + i);
3116         std::stringstream uniformName;
3117         uniformName << "test[" << innerIdx << "].data[" << outerIdx << "]";
3118         // Then send it as a uniform
3119         GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
3120         // The uniform should be active.
3121         EXPECT_NE(uniformLocation, -1);
3122 
3123         glUniform1i(uniformLocation, 3 - i);
3124     }
3125     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3126     EXPECT_PIXEL_COLOR_EQ(0, 0, expected);
3127 }
3128 
3129 // Test that if a non-preprocessor token is seen in a disabled if-block then it does not disallow
3130 // extension pragmas later
TEST_P(GLSLTest,NonPreprocessorTokensInIfBlocks)3131 TEST_P(GLSLTest, NonPreprocessorTokensInIfBlocks)
3132 {
3133     constexpr const char *kFS = R"(
3134 #if __VERSION__ >= 300
3135     inout mediump vec4 fragData;
3136 #else
3137     #extension GL_EXT_shader_texture_lod :enable
3138 #endif
3139 
3140 void main()
3141 {
3142 }
3143     )";
3144 
3145     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
3146     EXPECT_NE(0u, shader);
3147 }
3148 
3149 // Test that two constructors which have vec4 and mat2 parameters get disambiguated (issue in
3150 // HLSL).
TEST_P(GLSLTest_ES3,AmbiguousConstructorCall2x2)3151 TEST_P(GLSLTest_ES3, AmbiguousConstructorCall2x2)
3152 {
3153     constexpr char kVS[] =
3154         "#version 300 es\n"
3155         "precision highp float;\n"
3156         "in vec4 a_vec;\n"
3157         "in mat2 a_mat;\n"
3158         "void main()\n"
3159         "{\n"
3160         "    gl_Position = vec4(a_vec) + vec4(a_mat);\n"
3161         "}";
3162 
3163     GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
3164     EXPECT_NE(0u, program);
3165 }
3166 
3167 // Test that two constructors which have mat2x3 and mat3x2 parameters get disambiguated.
3168 // This was suspected to be an issue in HLSL, but HLSL seems to be able to natively choose between
3169 // the function signatures in this case.
TEST_P(GLSLTest_ES3,AmbiguousConstructorCall2x3)3170 TEST_P(GLSLTest_ES3, AmbiguousConstructorCall2x3)
3171 {
3172     constexpr char kVS[] =
3173         "#version 300 es\n"
3174         "precision highp float;\n"
3175         "in mat3x2 a_matA;\n"
3176         "in mat2x3 a_matB;\n"
3177         "void main()\n"
3178         "{\n"
3179         "    gl_Position = vec4(a_matA) + vec4(a_matB);\n"
3180         "}";
3181 
3182     GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
3183     EXPECT_NE(0u, program);
3184 }
3185 
3186 // Test that two functions which have vec4 and mat2 parameters get disambiguated (issue in HLSL).
TEST_P(GLSLTest_ES3,AmbiguousFunctionCall2x2)3187 TEST_P(GLSLTest_ES3, AmbiguousFunctionCall2x2)
3188 {
3189     constexpr char kVS[] =
3190         "#version 300 es\n"
3191         "precision highp float;\n"
3192         "in vec4 a_vec;\n"
3193         "in mat2 a_mat;\n"
3194         "vec4 foo(vec4 a)\n"
3195         "{\n"
3196         "    return a;\n"
3197         "}\n"
3198         "vec4 foo(mat2 a)\n"
3199         "{\n"
3200         "    return vec4(a[0][0]);\n"
3201         "}\n"
3202         "void main()\n"
3203         "{\n"
3204         "    gl_Position = foo(a_vec) + foo(a_mat);\n"
3205         "}";
3206 
3207     GLuint program = CompileProgram(kVS, essl3_shaders::fs::Red());
3208     EXPECT_NE(0u, program);
3209 }
3210 
3211 // Test that constructing matrices from non-float types works.
TEST_P(GLSLTest_ES3,ConstructMatrixFromNonFloat)3212 TEST_P(GLSLTest_ES3, ConstructMatrixFromNonFloat)
3213 {
3214     constexpr char kFS[] = R"(#version 300 es
3215 precision highp float;
3216 out vec4 color;
3217 
3218 uniform int i;
3219 uniform uint u;
3220 uniform bool b;
3221 
3222 void main()
3223 {
3224     mat3x2 mi = mat3x2(i);
3225     mat4 mu = mat4(u);
3226     mat2x4 mb = mat2x4(b);
3227 
3228     mat3x2 m = mat3x2(ivec2(i), uvec2(u), bvec2(b));
3229 
3230     color = vec4(mi[0][0] == -123.0 ? 1 : 0,
3231                  mu[2][2] == 456.0 ? 1 : 0,
3232                  mb[1][1] == 1.0 ? 1 : 0,
3233                  m[0][1] == -123.0 && m[1][0] == 456.0 && m[2][0] == 1.0 ? 1 : 0);
3234 })";
3235 
3236     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3237     glUseProgram(program);
3238 
3239     GLint iloc = glGetUniformLocation(program, "i");
3240     GLint uloc = glGetUniformLocation(program, "u");
3241     GLint bloc = glGetUniformLocation(program, "b");
3242     ASSERT_NE(iloc, -1);
3243     ASSERT_NE(uloc, -1);
3244     ASSERT_NE(bloc, -1);
3245     glUniform1i(iloc, -123);
3246     glUniform1ui(uloc, 456);
3247     glUniform1ui(bloc, 1);
3248 
3249     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3250     EXPECT_GL_NO_ERROR();
3251 
3252     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
3253 }
3254 
3255 // Test that constructing vectors from non-float types works.
TEST_P(GLSLTest_ES3,ConstructVectorFromNonFloat)3256 TEST_P(GLSLTest_ES3, ConstructVectorFromNonFloat)
3257 {
3258     constexpr char kFS[] = R"(#version 300 es
3259 precision highp float;
3260 out vec4 color;
3261 
3262 uniform ivec2 i;
3263 uniform uvec2 u;
3264 uniform bvec2 b;
3265 
3266 void main()
3267 {
3268     vec2 v2 = vec2(i.x, b);
3269     vec3 v3 = vec3(b, u);
3270     vec4 v4 = vec4(i, u);
3271 
3272     color = vec4(v2.x == -123.0 && v2.y == 1.0 ? 1 : 0,
3273                  v3.x == 1.0 && v3.y == 0.0 && v3.z == 456.0 ? 1 : 0,
3274                  v4.x == -123.0 && v4.y == -23.0 && v4.z == 456.0 && v4.w == 76.0 ? 1 : 0,
3275                  1);
3276 })";
3277 
3278     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3279     glUseProgram(program);
3280 
3281     GLint iloc = glGetUniformLocation(program, "i");
3282     GLint uloc = glGetUniformLocation(program, "u");
3283     GLint bloc = glGetUniformLocation(program, "b");
3284     ASSERT_NE(iloc, -1);
3285     ASSERT_NE(uloc, -1);
3286     ASSERT_NE(bloc, -1);
3287     glUniform2i(iloc, -123, -23);
3288     glUniform2ui(uloc, 456, 76);
3289     glUniform2ui(bloc, 1, 0);
3290 
3291     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3292     EXPECT_GL_NO_ERROR();
3293 
3294     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
3295 }
3296 
3297 // Test that constructing non-float vectors from matrix types works.
TEST_P(GLSLTest_ES3,ConstructNonFloatVectorFromMatrix)3298 TEST_P(GLSLTest_ES3, ConstructNonFloatVectorFromMatrix)
3299 {
3300     constexpr char kFS[] = R"(#version 300 es
3301 precision highp float;
3302 out vec4 color;
3303 
3304 uniform float f;
3305 
3306 void main()
3307 {
3308     mat4 m = mat4(f);
3309     ivec3 vi = ivec3(m);
3310     uvec2 vu = uvec2(m);
3311     bvec4 vb = bvec4(m);
3312     bvec2 vb2 = bvec2(vi.x, m);
3313 
3314     color = vec4(vi.x == int(f) ? 1 : 0,
3315                  vu.x == uint(f) ? 1 : 0,
3316                  vb.x == bool(f) ? 1 : 0,
3317                  vb2.x == bool(f) && vb2.y == bool(f) ? 1 : 0);
3318 })";
3319 
3320     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3321     glUseProgram(program);
3322 
3323     GLint floc = glGetUniformLocation(program, "f");
3324     ASSERT_NE(floc, -1);
3325     glUniform1f(floc, 123);
3326 
3327     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3328     EXPECT_GL_NO_ERROR();
3329 
3330     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
3331 }
3332 
3333 // Test that == and != for vector and matrix types work.
TEST_P(GLSLTest_ES3,NonScalarEqualOperator)3334 TEST_P(GLSLTest_ES3, NonScalarEqualOperator)
3335 {
3336     constexpr char kFS[] = R"(#version 300 es
3337 precision highp float;
3338 out vec4 color;
3339 
3340 uniform float f;
3341 uniform int i;
3342 uniform uint u;
3343 
3344 void main()
3345 {
3346     mat3x2 m32_1 = mat3x2(vec2(f), vec2(i), vec2(u));
3347     mat3x2 m32_2 = mat3x2(m32_1);
3348     mat3x2 m32_3 = mat3x2(vec2(i), vec2(u), vec2(f));
3349     mat2x3 m23_1 = mat2x3(vec3(f), vec3(i));
3350     mat2x3 m23_2 = mat2x3(m23_1);
3351     mat2x3 m23_3 = mat2x3(vec3(i), vec3(u));
3352     vec2 v2_1 = m32_1[0];
3353     vec2 v2_2 = m32_2[0];
3354     ivec3 v3_1 = ivec3(transpose(m32_1)[0]);
3355     ivec3 v3_2 = ivec3(transpose(m32_2)[0]);
3356     uvec4 v4_1 = uvec4(m32_1[1], m32_1[2]);
3357     uvec4 v4_2 = uvec4(m32_2[1], m32_2[2]);
3358 
3359     color = vec4((m32_1 == m32_2 ? 0.5 : 0.0) + (m23_1 == m23_2 ? 0.5 : 0.0),
3360                  v2_1 == v2_2 ? 1 : 0,
3361                  (v3_1 == v3_2 ? 0.5 : 0.0) +
3362                     (v4_1 == v4_2 ? 0.5 : 0.0),
3363                  (m32_1 != m32_3 ? 0.125 : 0.0) +
3364                     (m23_1 != m23_3 ? 0.125 : 0.0) +
3365                     (v2_1 != vec2(v3_2) ? 0.25 : 0.0) +
3366                     (v3_1 != ivec3(v4_2) ? 0.25 : 0.0) +
3367                     (v4_1 != uvec4(v2_1, v2_2) ? 0.25 : 0.0));
3368 })";
3369 
3370     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3371     glUseProgram(program);
3372 
3373     GLint floc = glGetUniformLocation(program, "f");
3374     GLint iloc = glGetUniformLocation(program, "i");
3375     GLint uloc = glGetUniformLocation(program, "u");
3376     ASSERT_NE(floc, -1);
3377     ASSERT_NE(iloc, -1);
3378     ASSERT_NE(uloc, -1);
3379     glUniform1f(floc, 1.5);
3380     glUniform1i(iloc, -123);
3381     glUniform1ui(uloc, 456);
3382 
3383     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3384     EXPECT_GL_NO_ERROR();
3385 
3386     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
3387 }
3388 
3389 // Test that == and != for structs and array types work.
TEST_P(GLSLTest_ES31,StructAndArrayEqualOperator)3390 TEST_P(GLSLTest_ES31, StructAndArrayEqualOperator)
3391 {
3392     constexpr char kFS[] = R"(#version 310 es
3393 precision highp float;
3394 out vec4 color;
3395 
3396 uniform float f;
3397 uniform int i;
3398 uniform uint u;
3399 
3400 struct S
3401 {
3402     float f;
3403     int i;
3404     uint u;
3405     vec4 v;
3406     ivec3 iv;
3407     uvec2 uv;
3408     mat3x2 m32;
3409     mat2x3 m23;
3410     float fa[3][4][5];
3411     int ia[4];
3412     uint ua[6][2];
3413 };
3414 
3415 struct T
3416 {
3417     S s1;
3418     S s2[3][2];
3419 };
3420 
3421 void main()
3422 {
3423     float fa[5] = float[5](f, f, f, f, f);
3424     int ia[4] = int[4](i, i, i, i);
3425     uint ua[2] = uint[2](u, u);
3426 
3427     S s1 = S(f, i, u, vec4(f), ivec3(i), uvec2(u),
3428              mat3x2(vec2(f), vec2(i), vec2(u)),
3429              mat2x3(vec3(f), vec3(i)),
3430              float[3][4][5](
3431                             float[4][5](fa, fa, fa, fa),
3432                             float[4][5](fa, fa, fa, fa),
3433                             float[4][5](fa, fa, fa, fa)),
3434              ia,
3435              uint[6][2](ua, ua, ua, ua, ua, ua));
3436 
3437     S s2[2] = S[2](s1, s1);
3438     s2[1].fa[0][1][2] = float(i);
3439 
3440     T t1 = T(s1, S[3][2](s2, s2, s2));
3441     T t2 = T(s2[1], S[3][2](s2, s2, s2));
3442 
3443     T ta1[2] = T[2](t1, t2);
3444     T ta2[2] = T[2](t1, t2);
3445     T ta3[2] = T[2](t2, t1);
3446 
3447     color = vec4((s1 == s2[0] ? 0.5 : 0.0) + (s1 != s2[1] ? 0.5 : 0.0),
3448                  (s1.fa[0] == s2[0].fa[0] ? 0.5 : 0.0) + (s1.fa[0] != s2[1].fa[0] ? 0.5 : 0.0),
3449                  (ta1[0] == t1 ? 0.5 : 0.0) + (ta1[1] != t1 ? 0.5 : 0.0),
3450                  (ta1 == ta2 ? 0.5 : 0.0) + (ta1 != ta3 ? 0.5 : 0.0));
3451 })";
3452 
3453     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
3454     glUseProgram(program);
3455 
3456     GLint floc = glGetUniformLocation(program, "f");
3457     GLint iloc = glGetUniformLocation(program, "i");
3458     GLint uloc = glGetUniformLocation(program, "u");
3459     ASSERT_NE(floc, -1);
3460     ASSERT_NE(iloc, -1);
3461     ASSERT_NE(uloc, -1);
3462     glUniform1f(floc, 1.5);
3463     glUniform1i(iloc, -123);
3464     glUniform1ui(uloc, 456);
3465 
3466     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3467     EXPECT_GL_NO_ERROR();
3468 
3469     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
3470 }
3471 
3472 // Test that an user-defined function with a large number of float4 parameters doesn't fail due to
3473 // the function name being too long.
TEST_P(GLSLTest_ES3,LargeNumberOfFloat4Parameters)3474 TEST_P(GLSLTest_ES3, LargeNumberOfFloat4Parameters)
3475 {
3476     std::stringstream vertexShaderStream;
3477     // Note: SPIR-V doesn't allow more than 255 parameters to a function.
3478     const unsigned int paramCount = (IsVulkan() || IsMetal()) ? 255u : 1024u;
3479 
3480     vertexShaderStream << "#version 300 es\n"
3481                           "precision highp float;\n"
3482                           "in vec4 a_vec;\n"
3483                           "vec4 lotsOfVec4Parameters(";
3484     for (unsigned int i = 0; i < paramCount - 1; ++i)
3485     {
3486         vertexShaderStream << "vec4 a" << i << ", ";
3487     }
3488     vertexShaderStream << "vec4 aLast)\n"
3489                           "{\n"
3490                           "    vec4 sum = vec4(0.0, 0.0, 0.0, 0.0);\n";
3491     for (unsigned int i = 0; i < paramCount - 1; ++i)
3492     {
3493         vertexShaderStream << "    sum += a" << i << ";\n";
3494     }
3495     vertexShaderStream << "    sum += aLast;\n"
3496                           "    return sum;\n "
3497                           "}\n"
3498                           "void main()\n"
3499                           "{\n"
3500                           "    gl_Position = lotsOfVec4Parameters(";
3501     for (unsigned int i = 0; i < paramCount - 1; ++i)
3502     {
3503         vertexShaderStream << "a_vec, ";
3504     }
3505     vertexShaderStream << "a_vec);\n"
3506                           "}";
3507 
3508     GLuint program = CompileProgram(vertexShaderStream.str().c_str(), essl3_shaders::fs::Red());
3509     EXPECT_NE(0u, program);
3510 }
3511 
3512 // This test was written specifically to stress DeferGlobalInitializers AST transformation.
3513 // Test a shader where a global constant array is initialized with an expression containing array
3514 // indexing. This initializer is tricky to constant fold, so if it's not constant folded it needs to
3515 // be handled in a way that doesn't generate statements in the global scope in HLSL output.
3516 // Also includes multiple array initializers in one declaration, where only the second one has
3517 // array indexing. This makes sure that the qualifier for the declaration is set correctly if
3518 // transformations are applied to the declaration also in the case of ESSL output.
TEST_P(GLSLTest_ES3,InitGlobalArrayWithArrayIndexing)3519 TEST_P(GLSLTest_ES3, InitGlobalArrayWithArrayIndexing)
3520 {
3521     // TODO(ynovikov): re-enable once root cause of http://anglebug.com/42260423 is fixed
3522     ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
3523 
3524     constexpr char kFS[] =
3525         "#version 300 es\n"
3526         "precision highp float;\n"
3527         "out vec4 my_FragColor;\n"
3528         "const highp float f[2] = float[2](0.1, 0.2);\n"
3529         "const highp float[2] g = float[2](0.3, 0.4), h = float[2](0.5, f[1]);\n"
3530         "void main()\n"
3531         "{\n"
3532         "    my_FragColor = vec4(h[1]);\n"
3533         "}";
3534 
3535     GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS);
3536     EXPECT_NE(0u, program);
3537 }
3538 
3539 // Test that constant global matrix array with an initializer compiles.
TEST_P(GLSLTest_ES3,InitConstantMatrixArray)3540 TEST_P(GLSLTest_ES3, InitConstantMatrixArray)
3541 {
3542     constexpr char kFS[] = R"(#version 300 es
3543         precision highp float;
3544         uniform int index;
3545 
3546         const mat4 matrix = mat4(1.0);
3547         const mat4 array[1] = mat4[1](matrix);
3548         out vec4 my_FragColor;
3549         void main() {
3550             my_FragColor = vec4(array[index][1].rgb, 1.0);
3551         })";
3552 
3553     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3554 
3555     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3556     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3557 }
3558 
3559 // Test that index-constant sampler array indexing is supported.
TEST_P(GLSLTest,IndexConstantSamplerArrayIndexing)3560 TEST_P(GLSLTest, IndexConstantSamplerArrayIndexing)
3561 {
3562     constexpr char kFS[] =
3563         "precision mediump float;\n"
3564         "uniform sampler2D uni[2];\n"
3565         "\n"
3566         "float zero(int x)\n"
3567         "{\n"
3568         "    return float(x) - float(x);\n"
3569         "}\n"
3570         "\n"
3571         "void main()\n"
3572         "{\n"
3573         "    vec4 c = vec4(0,0,0,0);\n"
3574         "    for (int ii = 1; ii < 3; ++ii) {\n"
3575         "        if (c.x > 255.0) {\n"
3576         "            c.x = 255.0 + zero(ii);\n"
3577         "            break;\n"
3578         "        }\n"
3579         // Index the sampler array with a predictable loop index (index-constant) as opposed to
3580         // a true constant. This is valid in OpenGL ES but isn't in many Desktop OpenGL versions,
3581         // without an extension.
3582         "        c += texture2D(uni[ii - 1], vec2(0.5, 0.5));\n"
3583         "    }\n"
3584         "    gl_FragColor = c;\n"
3585         "}";
3586 
3587     GLuint program = CompileProgram(essl1_shaders::vs::Simple(), kFS);
3588     EXPECT_NE(0u, program);
3589 }
3590 
3591 // Test that the #pragma directive is supported and doesn't trigger a compilation failure on the
3592 // native driver. The only pragma that gets passed to the OpenGL driver is "invariant" but we don't
3593 // want to test its behavior, so don't use any varyings.
TEST_P(GLSLTest,PragmaDirective)3594 TEST_P(GLSLTest, PragmaDirective)
3595 {
3596     constexpr char kVS[] =
3597         "#pragma STDGL invariant(all)\n"
3598         "void main()\n"
3599         "{\n"
3600         "    gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
3601         "}\n";
3602 
3603     GLuint program = CompileProgram(kVS, essl1_shaders::fs::Red());
3604     EXPECT_NE(0u, program);
3605 }
3606 
3607 // Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
3608 // The function call that returns the array needs to be evaluated after ++j for the expression to
3609 // return the correct value (true).
TEST_P(GLSLTest_ES3,SequenceOperatorEvaluationOrderArray)3610 TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderArray)
3611 {
3612     constexpr char kFS[] =
3613         "#version 300 es\n"
3614         "precision mediump float;\n"
3615         "out vec4 my_FragColor; \n"
3616         "int[2] func(int param) {\n"
3617         "    return int[2](param, param);\n"
3618         "}\n"
3619         "void main() {\n"
3620         "    int a[2]; \n"
3621         "    for (int i = 0; i < 2; ++i) {\n"
3622         "        a[i] = 1;\n"
3623         "    }\n"
3624         "    int j = 0; \n"
3625         "    bool result = ((++j), (a == func(j)));\n"
3626         "    my_FragColor = vec4(0.0, (result ? 1.0 : 0.0), 0.0, 1.0);\n"
3627         "}\n";
3628 
3629     GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS);
3630     ASSERT_NE(0u, program);
3631 
3632     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3633 
3634     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3635 }
3636 
3637 // Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
3638 // The short-circuiting expression needs to be evaluated after ++j for the expression to return the
3639 // correct value (true).
TEST_P(GLSLTest_ES3,SequenceOperatorEvaluationOrderShortCircuit)3640 TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderShortCircuit)
3641 {
3642     constexpr char kFS[] =
3643         "#version 300 es\n"
3644         "precision mediump float;\n"
3645         "out vec4 my_FragColor; \n"
3646         "void main() {\n"
3647         "    int j = 0; \n"
3648         "    bool result = ((++j), (j == 1 ? true : (++j == 3)));\n"
3649         "    my_FragColor = vec4(0.0, ((result && j == 1) ? 1.0 : 0.0), 0.0, 1.0);\n"
3650         "}\n";
3651 
3652     GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS);
3653     ASSERT_NE(0u, program);
3654 
3655     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3656 
3657     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3658 }
3659 
3660 // Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
3661 // Indexing the vector needs to be evaluated after func() for the right result.
TEST_P(GLSLTest_ES3,SequenceOperatorEvaluationOrderDynamicVectorIndexingInLValue)3662 TEST_P(GLSLTest_ES3, SequenceOperatorEvaluationOrderDynamicVectorIndexingInLValue)
3663 {
3664     constexpr char kFS[] =
3665         "#version 300 es\n"
3666         "precision mediump float;\n"
3667         "out vec4 my_FragColor;\n"
3668         "uniform int u_zero;\n"
3669         "int sideEffectCount = 0;\n"
3670         "float func() {\n"
3671         "    ++sideEffectCount;\n"
3672         "    return -1.0;\n"
3673         "}\n"
3674         "void main() {\n"
3675         "    vec4 v = vec4(0.0, 2.0, 4.0, 6.0); \n"
3676         "    float f = (func(), (++v[u_zero + sideEffectCount]));\n"
3677         "    bool green = abs(f - 3.0) < 0.01 && abs(v[1] - 3.0) < 0.01 && sideEffectCount == 1;\n"
3678         "    my_FragColor = vec4(0.0, (green ? 1.0 : 0.0), 0.0, 1.0);\n"
3679         "}\n";
3680 
3681     GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS);
3682     ASSERT_NE(0u, program);
3683 
3684     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3685 
3686     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3687 }
3688 
3689 // Test that using gl_PointCoord with GL_TRIANGLES doesn't produce a link error.
3690 // From WebGL test conformance/rendering/point-specific-shader-variables.html
3691 // See http://anglebug.com/42260376
TEST_P(GLSLTest,RenderTrisWithPointCoord)3692 TEST_P(GLSLTest, RenderTrisWithPointCoord)
3693 {
3694     constexpr char kVS[] =
3695         "attribute vec2 aPosition;\n"
3696         "void main()\n"
3697         "{\n"
3698         "    gl_Position = vec4(aPosition, 0, 1);\n"
3699         "    gl_PointSize = 1.0;\n"
3700         "}";
3701     constexpr char kFS[] =
3702         "void main()\n"
3703         "{\n"
3704         "    gl_FragColor = vec4(gl_PointCoord.xy, 0, 1);\n"
3705         "    gl_FragColor = vec4(0, 1, 0, 1);\n"
3706         "}";
3707 
3708     ANGLE_GL_PROGRAM(prog, kVS, kFS);
3709     drawQuad(prog, "aPosition", 0.5f);
3710     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3711 }
3712 
3713 // Convers a bug with the integer pow statement workaround.
TEST_P(GLSLTest,NestedPowStatements)3714 TEST_P(GLSLTest, NestedPowStatements)
3715 {
3716     // https://crbug.com/1127866 - possible NVIDIA driver issue
3717     ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsVulkan() && IsWindows());
3718 
3719     constexpr char kFS[] =
3720         "precision mediump float;\n"
3721         "float func(float v)\n"
3722         "{\n"
3723         "   float f1 = pow(v, 2.0);\n"
3724         "   return pow(f1 + v, 2.0);\n"
3725         "}\n"
3726         "void main()\n"
3727         "{\n"
3728         "    float v = func(2.0);\n"
3729         "    gl_FragColor = abs(v - 36.0) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
3730         "}";
3731 
3732     ANGLE_GL_PROGRAM(prog, essl1_shaders::vs::Simple(), kFS);
3733     drawQuad(prog, essl1_shaders::PositionAttrib(), 0.5f);
3734     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3735 }
3736 
3737 // This test covers a crash seen in an application during SPIR-V compilation
TEST_P(GLSLTest_ES3,NestedPowFromUniform)3738 TEST_P(GLSLTest_ES3, NestedPowFromUniform)
3739 {
3740     constexpr char kVS[] = R"(#version 300 es
3741 in vec2 position;
3742 void main()
3743 {
3744     gl_Position = vec4(position, 0, 1);
3745 })";
3746 
3747     constexpr char kFS[] = R"(#version 300 es
3748 precision mediump float;
3749 precision mediump int;
3750 
3751 uniform highp vec4 scale;
3752 out mediump vec4 out_FragColor;
3753 void main()
3754 {
3755     highp vec4 v0;
3756     v0 = scale;
3757     highp vec3 v1;
3758     v1.xyz = v0.xyz;
3759     if ((v0.y!=1.0))
3760     {
3761         vec3 v3;
3762         v3.xyz = pow(v0.xyz,v0.xxx);
3763         float h0;
3764         if ((v3.x < 3.13))
3765         {
3766             h0 = (v3.x * 1.29);
3767         }
3768         else
3769         {
3770             h0 = ((pow(v3.x,4.16)*1.055)+-5.5);
3771         }
3772         float h1;
3773         if ((v3.y<3.13))
3774         {
3775             h1 = (v3.y*1.29);
3776         }
3777         else
3778         {
3779             h1 = ((pow(v3.y,4.16)*1.055)+-5.5);
3780         }
3781         float h2;
3782         if ((v3.z<3.13))
3783         {
3784             h2 = (v3.z*1.29);
3785         }
3786         else
3787         {
3788             h2 = ((pow(v3.z,4.16)*1.055)+-5.5);
3789         }
3790         v1.xyz = vec3(h0, h1, h2);
3791     }
3792     out_FragColor = vec4(v1, v0.w);
3793 }
3794 )";
3795 
3796     ANGLE_GL_PROGRAM(prog, kVS, kFS);
3797 
3798     GLint scaleIndex = glGetUniformLocation(prog, "scale");
3799     ASSERT_NE(-1, scaleIndex);
3800 
3801     glUseProgram(prog);
3802     glUniform4f(scaleIndex, 0.5, 0.5, 0.5, 0.5);
3803 
3804     // Don't crash
3805     drawQuad(prog, "position", 0.5f);
3806 }
3807 
3808 // Test that -float calculation is correct.
TEST_P(GLSLTest_ES3,UnaryMinusOperatorFloat)3809 TEST_P(GLSLTest_ES3, UnaryMinusOperatorFloat)
3810 {
3811     constexpr char kFS[] =
3812         "#version 300 es\n"
3813         "out highp vec4 o_color;\n"
3814         "void main() {\n"
3815         "    highp float f = -1.0;\n"
3816         "    // atan(tan(0.5), -f) should be 0.5.\n"
3817         "    highp float v = atan(tan(0.5), -f);\n"
3818         "    o_color = abs(v - 0.5) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
3819         "}\n";
3820 
3821     ANGLE_GL_PROGRAM(prog, essl3_shaders::vs::Simple(), kFS);
3822     drawQuad(prog, essl3_shaders::PositionAttrib(), 0.5f);
3823     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3824 }
3825 
3826 // Test that atan(vec2, vec2) calculation is correct.
TEST_P(GLSLTest_ES3,AtanVec2)3827 TEST_P(GLSLTest_ES3, AtanVec2)
3828 {
3829     constexpr char kFS[] =
3830         "#version 300 es\n"
3831         "out highp vec4 o_color;\n"
3832         "void main() {\n"
3833         "    highp float f = 1.0;\n"
3834         "    // atan(tan(0.5), f) should be 0.5.\n"
3835         "    highp vec2 v = atan(vec2(tan(0.5)), vec2(f));\n"
3836         "    o_color = (abs(v[0] - 0.5) < 0.001 && abs(v[1] - 0.5) < 0.001) ? vec4(0, 1, 0, 1) : "
3837         "vec4(1, 0, 0, 1);\n"
3838         "}\n";
3839 
3840     ANGLE_GL_PROGRAM(prog, essl3_shaders::vs::Simple(), kFS);
3841     drawQuad(prog, essl3_shaders::PositionAttrib(), 0.5f);
3842     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3843 }
3844 
3845 // Convers a bug with the unary minus operator on signed integer workaround.
TEST_P(GLSLTest_ES3,UnaryMinusOperatorSignedInt)3846 TEST_P(GLSLTest_ES3, UnaryMinusOperatorSignedInt)
3847 {
3848     constexpr char kVS[] =
3849         "#version 300 es\n"
3850         "in highp vec4 position;\n"
3851         "out mediump vec4 v_color;\n"
3852         "uniform int ui_one;\n"
3853         "uniform int ui_two;\n"
3854         "uniform int ui_three;\n"
3855         "void main() {\n"
3856         "    int s[3];\n"
3857         "    s[0] = ui_one;\n"
3858         "    s[1] = -(-(-ui_two + 1) + 1);\n"  // s[1] = -ui_two
3859         "    s[2] = ui_three;\n"
3860         "    int result = 0;\n"
3861         "    for (int i = 0; i < ui_three; i++) {\n"
3862         "        result += s[i];\n"
3863         "    }\n"
3864         "    v_color = (result == 2) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
3865         "    gl_Position = position;\n"
3866         "}\n";
3867     constexpr char kFS[] =
3868         "#version 300 es\n"
3869         "in mediump vec4 v_color;\n"
3870         "layout(location=0) out mediump vec4 o_color;\n"
3871         "void main() {\n"
3872         "    o_color = v_color;\n"
3873         "}\n";
3874 
3875     ANGLE_GL_PROGRAM(prog, kVS, kFS);
3876 
3877     GLint oneIndex = glGetUniformLocation(prog, "ui_one");
3878     ASSERT_NE(-1, oneIndex);
3879     GLint twoIndex = glGetUniformLocation(prog, "ui_two");
3880     ASSERT_NE(-1, twoIndex);
3881     GLint threeIndex = glGetUniformLocation(prog, "ui_three");
3882     ASSERT_NE(-1, threeIndex);
3883     glUseProgram(prog);
3884     glUniform1i(oneIndex, 1);
3885     glUniform1i(twoIndex, 2);
3886     glUniform1i(threeIndex, 3);
3887 
3888     drawQuad(prog, "position", 0.5f);
3889     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3890 }
3891 
3892 // Convers a bug with the unary minus operator on unsigned integer workaround.
TEST_P(GLSLTest_ES3,UnaryMinusOperatorUnsignedInt)3893 TEST_P(GLSLTest_ES3, UnaryMinusOperatorUnsignedInt)
3894 {
3895     constexpr char kVS[] =
3896         "#version 300 es\n"
3897         "in highp vec4 position;\n"
3898         "out mediump vec4 v_color;\n"
3899         "uniform uint ui_one;\n"
3900         "uniform uint ui_two;\n"
3901         "uniform uint ui_three;\n"
3902         "void main() {\n"
3903         "    uint s[3];\n"
3904         "    s[0] = ui_one;\n"
3905         "    s[1] = -(-(-ui_two + 1u) + 1u);\n"  // s[1] = -ui_two
3906         "    s[2] = ui_three;\n"
3907         "    uint result = 0u;\n"
3908         "    for (uint i = 0u; i < ui_three; i++) {\n"
3909         "        result += s[i];\n"
3910         "    }\n"
3911         "    v_color = (result == 2u) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
3912         "    gl_Position = position;\n"
3913         "}\n";
3914     constexpr char kFS[] =
3915         "#version 300 es\n"
3916         "in mediump vec4 v_color;\n"
3917         "layout(location=0) out mediump vec4 o_color;\n"
3918         "void main() {\n"
3919         "    o_color = v_color;\n"
3920         "}\n";
3921 
3922     ANGLE_GL_PROGRAM(prog, kVS, kFS);
3923 
3924     GLint oneIndex = glGetUniformLocation(prog, "ui_one");
3925     ASSERT_NE(-1, oneIndex);
3926     GLint twoIndex = glGetUniformLocation(prog, "ui_two");
3927     ASSERT_NE(-1, twoIndex);
3928     GLint threeIndex = glGetUniformLocation(prog, "ui_three");
3929     ASSERT_NE(-1, threeIndex);
3930     glUseProgram(prog);
3931     glUniform1ui(oneIndex, 1u);
3932     glUniform1ui(twoIndex, 2u);
3933     glUniform1ui(threeIndex, 3u);
3934 
3935     drawQuad(prog, "position", 0.5f);
3936     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3937 }
3938 
3939 // Test a nested sequence operator with a ternary operator inside. The ternary operator is
3940 // intended to be such that it gets converted to an if statement on the HLSL backend.
TEST_P(GLSLTest,NestedSequenceOperatorWithTernaryInside)3941 TEST_P(GLSLTest, NestedSequenceOperatorWithTernaryInside)
3942 {
3943     // Note that the uniform keep_flop_positive doesn't need to be set - the test expects it to have
3944     // its default value false.
3945     constexpr char kFS[] =
3946         "precision mediump float;\n"
3947         "uniform bool keep_flop_positive;\n"
3948         "float flop;\n"
3949         "void main() {\n"
3950         "    flop = -1.0,\n"
3951         "    (flop *= -1.0,\n"
3952         "    keep_flop_positive ? 0.0 : flop *= -1.0),\n"
3953         "    gl_FragColor = vec4(0, -flop, 0, 1);\n"
3954         "}";
3955 
3956     ANGLE_GL_PROGRAM(prog, essl1_shaders::vs::Simple(), kFS);
3957     drawQuad(prog, essl1_shaders::PositionAttrib(), 0.5f);
3958     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3959 }
3960 
3961 // Test that nesting ternary and short-circuitting operators work.
TEST_P(GLSLTest,NestedTernaryAndShortCircuit)3962 TEST_P(GLSLTest, NestedTernaryAndShortCircuit)
3963 {
3964     // Note that the uniform doesn't need to be set, and will contain the default value of false.
3965     constexpr char kFS[] = R"(
3966 precision mediump float;
3967 uniform bool u;
3968 void main()
3969 {
3970     int a = u ? 12345 : 2;      // will be 2
3971     int b = u ? 12345 : 4;      // will be 4
3972     int c = u ? 12345 : 0;      // will be 0
3973 
3974     if (a == 2                  // true path is taken
3975         ? (b == 3               // false path is taken
3976             ? (a=0) != 0
3977             : b != 0            // true
3978           ) && (                // short-circuit evaluates RHS
3979             (a=7) == 7          // true, modifies a
3980             ||                  // short-circuit doesn't evaluate RHS
3981             (b=8) == 8
3982           )
3983         : (a == 0 && b == 0
3984             ? (c += int((a=0) == 0 && (b=0) == 0)) != 0
3985             : (c += int((a=0) != 0 && (b=0) != 0)) != 0))
3986     {
3987         c += 15;                // will execute
3988     }
3989 
3990     // Verify that a is 7, b is 4 and c is 15.
3991     gl_FragColor = vec4(a == 7, b == 4, c == 15, 1);
3992 })";
3993 
3994     ANGLE_GL_PROGRAM(prog, essl1_shaders::vs::Simple(), kFS);
3995     drawQuad(prog, essl1_shaders::PositionAttrib(), 0.5f);
3996     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
3997 }
3998 
3999 // Test that uniform bvecN passed to functions work.
TEST_P(GLSLTest_ES3,UniformBoolVectorPassedToFunctions)4000 TEST_P(GLSLTest_ES3, UniformBoolVectorPassedToFunctions)
4001 {
4002     constexpr char kFS[] = R"(#version 300 es
4003 precision mediump float;
4004 uniform bvec4 u;
4005 out vec4 color;
4006 
4007 bool f(bvec4 bv)
4008 {
4009     return all(bv.xz) && !any(bv.yw);
4010 }
4011 
4012 void main() {
4013     color = f(u) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
4014 })";
4015 
4016     ANGLE_GL_PROGRAM(prog, essl3_shaders::vs::Simple(), kFS);
4017     glUseProgram(prog);
4018 
4019     GLint uloc = glGetUniformLocation(prog, "u");
4020     ASSERT_NE(uloc, -1);
4021     glUniform4ui(uloc, true, false, true, false);
4022 
4023     drawQuad(prog, essl3_shaders::PositionAttrib(), 0.5f);
4024     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4025 }
4026 
4027 // Test that bvecN in storage buffer passed to functions work.
TEST_P(GLSLTest_ES31,StorageBufferBoolVectorPassedToFunctions)4028 TEST_P(GLSLTest_ES31, StorageBufferBoolVectorPassedToFunctions)
4029 {
4030     constexpr char kCS[] = R"(#version 310 es
4031 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
4032 layout(binding = 0, std430) buffer Output {
4033     bvec4 b;
4034     bool valid;
4035 } outbuf;
4036 
4037 bool f_in(bvec4 bv)
4038 {
4039     return all(bv.xz) && !any(bv.yw);
4040 }
4041 
4042 bool f_inout(inout bvec4 bv)
4043 {
4044     bool ok = all(bv.xz) && !any(bv.yw);
4045     bv.xw = bvec2(false, true);
4046     return ok;
4047 }
4048 
4049 void f_out(out bvec4 bv)
4050 {
4051     bv = bvec4(false, true, false, true);
4052 }
4053 
4054 void main() {
4055     bool valid = f_in(outbuf.b);
4056     valid = f_inout(outbuf.b) && valid;
4057     f_out(outbuf.b);
4058     outbuf.valid = valid;
4059 })";
4060 
4061     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
4062     glUseProgram(program);
4063 
4064     constexpr std::array<GLuint, 5> kOutputInitData = {true, false, true, false, false};
4065     GLBuffer outputBuffer;
4066     glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
4067     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kOutputInitData), kOutputInitData.data(),
4068                  GL_STATIC_DRAW);
4069     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, outputBuffer);
4070     EXPECT_GL_NO_ERROR();
4071 
4072     glDispatchCompute(1, 1, 1);
4073     EXPECT_GL_NO_ERROR();
4074 
4075     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4076 
4077     const GLuint *ptr = reinterpret_cast<const GLuint *>(
4078         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kOutputInitData), GL_MAP_READ_BIT));
4079     fprintf(stderr, "%d %d %d %d %d\n", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4]);
4080     EXPECT_FALSE(ptr[0]);
4081     EXPECT_TRUE(ptr[1]);
4082     EXPECT_FALSE(ptr[2]);
4083     EXPECT_TRUE(ptr[3]);
4084     EXPECT_TRUE(ptr[4]);
4085     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4086 }
4087 
4088 // Test that using a sampler2D and samplerExternalOES in the same shader works
4089 // (anglebug.com/42260512)
TEST_P(GLSLTest,ExternalAnd2DSampler)4090 TEST_P(GLSLTest, ExternalAnd2DSampler)
4091 {
4092     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_EGL_image_external"));
4093 
4094     constexpr char kFS[] = R"(#extension GL_OES_EGL_image_external : enable
4095 precision mediump float;
4096 uniform samplerExternalOES tex0;
4097 uniform sampler2D tex1;
4098 void main(void)
4099 {
4100     vec2 uv = vec2(0.0, 0.0);
4101     gl_FragColor = texture2D(tex0, uv) + texture2D(tex1, uv);
4102 })";
4103 
4104     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
4105 }
4106 
4107 // Tests that monomorphizing functions does not crash if there is a main prototype.
TEST_P(GLSLTest,MonomorphizeMainPrototypeNoCrash)4108 TEST_P(GLSLTest, MonomorphizeMainPrototypeNoCrash)
4109 {
4110     constexpr char kFS[] = R"(precision mediump float;
4111 struct S { sampler2D source; };
4112 vec4 f(S s)
4113 {
4114     return texture2D(s.source, vec2(5));
4115 }
4116 uniform S green;
4117 void main();
4118 void main() {
4119     f(green);
4120 })";
4121     CompileShader(GL_FRAGMENT_SHADER, kFS);
4122     ASSERT_GL_NO_ERROR();
4123 }
4124 
4125 // Test that using a varying matrix array is supported.
TEST_P(GLSLTest,VaryingMatrixArray)4126 TEST_P(GLSLTest, VaryingMatrixArray)
4127 {
4128     constexpr char kVS[] =
4129         "uniform vec2 u_a1;\n"
4130         "uniform vec2 u_a2;\n"
4131         "attribute vec4 a_position;\n"
4132         "varying mat2 v_mat[2];\n"
4133         "void main() {\n"
4134         "    v_mat[0] = mat2(u_a1, u_a2);\n"
4135         "    v_mat[1] = mat2(1.0 - u_a2, 1.0 - u_a1);\n"
4136         "    gl_Position = a_position;\n"
4137         "}";
4138 
4139     constexpr char kFS[] =
4140         "precision mediump float;\n"
4141         "varying mat2 v_mat[2];\n"
4142         "void main(void)\n"
4143         "{\n"
4144         "    gl_FragColor = vec4(v_mat[0][0].x, v_mat[0][0].y, v_mat[1][0].x, 1.0);\n"
4145         "}";
4146 
4147     ANGLE_GL_PROGRAM(program, kVS, kFS);
4148 
4149     GLint oneIndex = glGetUniformLocation(program, "u_a1");
4150     ASSERT_NE(-1, oneIndex);
4151     GLint twoIndex = glGetUniformLocation(program, "u_a2");
4152     ASSERT_NE(-1, twoIndex);
4153     glUseProgram(program);
4154     glUniform2f(oneIndex, 1, 0.5f);
4155     glUniform2f(twoIndex, 0.25f, 0.125f);
4156 
4157     drawQuad(program, "a_position", 0.5f);
4158     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 127, 255 - 63, 255), 1.0);
4159 }
4160 
4161 // Test that using a centroid varying matrix array is supported.
TEST_P(GLSLTest_ES3,CentroidVaryingMatrixArray)4162 TEST_P(GLSLTest_ES3, CentroidVaryingMatrixArray)
4163 {
4164     constexpr char kVS[] =
4165         "#version 300 es\n"
4166         "uniform vec2 u_a1;\n"
4167         "uniform vec2 u_a2;\n"
4168         "in vec4 a_position;\n"
4169         "centroid out mat3x2 v_mat[2];\n"
4170         "void main() {\n"
4171         "    v_mat[0] = mat3x2(u_a1, u_a2, vec2(0.0));\n"
4172         "    v_mat[1] = mat3x2(vec2(0.0), 1.0 - u_a2, 1.0 - u_a1);\n"
4173         "    gl_Position = a_position;\n"
4174         "}";
4175 
4176     constexpr char kFS[] =
4177         "#version 300 es\n"
4178         "precision mediump float;\n"
4179         "centroid in mat3x2 v_mat[2];\n"
4180         "layout(location = 0) out vec4 out_color;\n"
4181         "void main(void)\n"
4182         "{\n"
4183         "    out_color = vec4(v_mat[0][0].x, v_mat[0][0].y, v_mat[1][1].x, 1.0);\n"
4184         "}";
4185 
4186     ANGLE_GL_PROGRAM(program, kVS, kFS);
4187 
4188     GLint oneIndex = glGetUniformLocation(program, "u_a1");
4189     ASSERT_NE(-1, oneIndex);
4190     GLint twoIndex = glGetUniformLocation(program, "u_a2");
4191     ASSERT_NE(-1, twoIndex);
4192     glUseProgram(program);
4193     glUniform2f(oneIndex, 1, 0.5f);
4194     glUniform2f(twoIndex, 0.25f, 0.125f);
4195 
4196     drawQuad(program, "a_position", 0.5f);
4197     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 127, 255 - 63, 255), 1.0);
4198 }
4199 
4200 // Test that using a flat varying matrix array is supported.
TEST_P(GLSLTest_ES3,FlatVaryingMatrixArray)4201 TEST_P(GLSLTest_ES3, FlatVaryingMatrixArray)
4202 {
4203     constexpr char kVS[] =
4204         "#version 300 es\n"
4205         "uniform vec2 u_a1;\n"
4206         "uniform vec2 u_a2;\n"
4207         "in vec4 a_position;\n"
4208         "flat out mat2 v_mat[2];\n"
4209         "void main() {\n"
4210         "    v_mat[0] = mat2(u_a1, u_a2);\n"
4211         "    v_mat[1] = mat2(u_a2, u_a1);\n"
4212         "    gl_Position = a_position;\n"
4213         "}";
4214 
4215     constexpr char kFS[] =
4216         "#version 300 es\n"
4217         "precision mediump float;\n"
4218         "flat in mat2 v_mat[2];\n"
4219         "layout(location = 0) out vec4 out_color;\n"
4220         "void main(void)\n"
4221         "{\n"
4222         "    out_color = vec4(v_mat[0][0].x, v_mat[0][0].y, v_mat[1][0].x, 1.0);\n"
4223         "}";
4224 
4225     ANGLE_GL_PROGRAM(program, kVS, kFS);
4226 
4227     GLint oneIndex = glGetUniformLocation(program, "u_a1");
4228     ASSERT_NE(-1, oneIndex);
4229     GLint twoIndex = glGetUniformLocation(program, "u_a2");
4230     ASSERT_NE(-1, twoIndex);
4231     glUseProgram(program);
4232     glUniform2f(oneIndex, 1, 0.5f);
4233     glUniform2f(twoIndex, 0.25f, 0.125f);
4234 
4235     drawQuad(program, "a_position", 0.5f);
4236     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 127, 63, 255), 1.0);
4237 }
4238 
4239 // Test that using a varying matrix array works with a particular input names scheme.
4240 // Test that having "mat3 a[*]" and "mat2 a_0" does not cause internal shader compile failures.
4241 // For a buggy naming scheme both would expand into a_0_0 and cause problems.
TEST_P(GLSLTest_ES3,VaryingMatrixArrayNaming2)4242 TEST_P(GLSLTest_ES3, VaryingMatrixArrayNaming2)
4243 {
4244     constexpr char kVS[] = R"(#version 300 es
4245 precision mediump float;
4246 uniform mat3 r0;
4247 uniform mat2 r1;
4248 in vec4 a_position;
4249 out mat2 a_0;
4250 out mat3 a[2];
4251 void main() {
4252     a[0] = r0;
4253     a[1] = r0 + mat3(1, 1, 1, 1, 1, 1, 1, 1, 1);
4254     a_0 = r1;
4255     gl_Position = a_position;
4256 })";
4257     constexpr char kFS[] = R"(#version 300 es
4258 precision mediump float;
4259 in mat2 a_0;
4260 in mat3 a[2];
4261 layout(location = 0) out vec4 o;
4262 void main(void) {
4263     mat3 diff0 = a[0] - mat3(0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8);
4264     mat3 diff1 = a[1] - mat3(1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8);
4265     mat2 diff2 = a_0 - mat2(3.0, 3.1, 3.2, 3.3);
4266     o.r = all(lessThan(abs(diff0[0]) + abs(diff0[1]) + abs(diff0[2]), vec3(0.01))) ? 1.0 : 0.0;
4267     o.g = all(lessThan(abs(diff1[0]) + abs(diff1[1]) + abs(diff1[2]), vec3(0.01))) ? 1.0 : 0.0;
4268     o.b = all(lessThan(abs(diff2[0]) + abs(diff2[1]), vec2(0.01))) ? 1.0 : 0.0;
4269     o.a = 1.0;
4270 })";
4271     ANGLE_GL_PROGRAM(program, kVS, kFS);
4272 
4273     GLint r0 = glGetUniformLocation(program, "r0");
4274     ASSERT_NE(-1, r0);
4275     GLint r1 = glGetUniformLocation(program, "r1");
4276     ASSERT_NE(-1, r1);
4277     glUseProgram(program);
4278     float r0v[] = {0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f};
4279     glUniformMatrix3fv(r0, 1, false, r0v);
4280     float r1v[] = {3.0f, 3.1f, 3.2f, 3.3f};
4281     glUniformMatrix2fv(r1, 1, false, r1v);
4282     drawQuad(program, "a_position", 0.5f);
4283     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 255, 255, 255), 1.0);
4284 }
4285 
4286 // Test that literal infinity can be written out from the shader translator.
4287 // 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)4288 TEST_P(GLSLTest_ES3, LiteralInfinityOutput)
4289 {
4290     constexpr char kFS[] =
4291         "#version 300 es\n"
4292         "precision highp float;\n"
4293         "out vec4 out_color;\n"
4294         "uniform float u;\n"
4295         "void main()\n"
4296         "{\n"
4297         "   float infVar = 1.0e40 - u;\n"
4298         "   bool correct = isinf(infVar) && infVar > 0.0;\n"
4299         "   out_color = correct ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4300         "}\n";
4301 
4302     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4303     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
4304     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4305 }
4306 
4307 // Test that literal negative infinity can be written out from the shader translator.
4308 // 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)4309 TEST_P(GLSLTest_ES3, LiteralNegativeInfinityOutput)
4310 {
4311     constexpr char kFS[] =
4312         "#version 300 es\n"
4313         "precision highp float;\n"
4314         "out vec4 out_color;\n"
4315         "uniform float u;\n"
4316         "void main()\n"
4317         "{\n"
4318         "   float infVar = -1.0e40 + u;\n"
4319         "   bool correct = isinf(infVar) && infVar < 0.0;\n"
4320         "   out_color = correct ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4321         "}\n";
4322 
4323     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4324     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
4325     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4326 }
4327 
4328 // The following MultipleDeclaration* tests are testing TranslatorHLSL specific simplification
4329 // passes. Because the interaction of multiple passes must be tested, it is difficult to write
4330 // a unittest for them. Instead we add the tests as end2end so will in particular test
4331 // TranslatorHLSL when run on Windows.
4332 
4333 // Test that passes splitting multiple declarations and comma operators are correctly ordered.
TEST_P(GLSLTest_ES3,MultipleDeclarationWithCommaOperator)4334 TEST_P(GLSLTest_ES3, MultipleDeclarationWithCommaOperator)
4335 {
4336     constexpr char kFS[] = R"(#version 300 es
4337 precision mediump float;
4338 out vec4 color;
4339 
4340 uniform float u;
4341 float c = 0.0;
4342 float sideEffect()
4343 {
4344     c = u;
4345     return c;
4346 }
4347 
4348 void main(void)
4349 {
4350     float a = 0.0, b = ((gl_FragCoord.x < 0.5 ? a : sideEffect()), a);
4351     color = vec4(b + c);
4352 })";
4353 
4354     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4355 }
4356 
4357 // Test that passes splitting multiple declarations and comma operators and for loops are
4358 // correctly ordered.
TEST_P(GLSLTest_ES3,MultipleDeclarationWithCommaOperatorInForLoop)4359 TEST_P(GLSLTest_ES3, MultipleDeclarationWithCommaOperatorInForLoop)
4360 {
4361     constexpr char kFS[] = R"(#version 300 es
4362 precision mediump float;
4363 out vec4 color;
4364 
4365 uniform float u;
4366 float c = 0.0;
4367 float sideEffect()
4368 {
4369     c = u;
4370     return c;
4371 }
4372 
4373 void main(void)
4374 {
4375     for(float a = 0.0, b = ((gl_FragCoord.x < 0.5 ? a : sideEffect()), a); a < 10.0; a++)
4376     {
4377         b += 1.0;
4378         color = vec4(b);
4379     }
4380 })";
4381 
4382     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4383 }
4384 
4385 // Test that splitting multiple declaration in for loops works with no loop condition
TEST_P(GLSLTest_ES3,MultipleDeclarationInForLoopEmptyCondition)4386 TEST_P(GLSLTest_ES3, MultipleDeclarationInForLoopEmptyCondition)
4387 {
4388     constexpr char kFS[] =
4389         "#version 300 es\n"
4390         "precision mediump float;\n"
4391         "out vec4 color;\n"
4392         "void main(void)\n"
4393         "{\n"
4394         " for(float a = 0.0, b = 1.0;; a++)\n"
4395         " {\n"
4396         "  b += 1.0;\n"
4397         "  if (a > 10.0) {break;}\n"
4398         "  color = vec4(b);\n"
4399         " }\n"
4400         "}\n";
4401 
4402     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4403 }
4404 
4405 // Test that splitting multiple declaration in for loops works with no loop expression
TEST_P(GLSLTest_ES3,MultipleDeclarationInForLoopEmptyExpression)4406 TEST_P(GLSLTest_ES3, MultipleDeclarationInForLoopEmptyExpression)
4407 {
4408     constexpr char kFS[] =
4409         "#version 300 es\n"
4410         "precision mediump float;\n"
4411         "out vec4 color;\n"
4412         "void main(void)\n"
4413         "{\n"
4414         " for(float a = 0.0, b = 1.0; a < 10.0;)\n"
4415         " {\n"
4416         "  b += 1.0;\n"
4417         "  a += 1.0;\n"
4418         "  color = vec4(b);\n"
4419         " }\n"
4420         "}\n";
4421 
4422     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4423 }
4424 
4425 // Test that dynamic indexing of a matrix inside a dynamic indexing of a vector in an l-value works
4426 // correctly.
TEST_P(GLSLTest_ES3,NestedDynamicIndexingInLValue)4427 TEST_P(GLSLTest_ES3, NestedDynamicIndexingInLValue)
4428 {
4429     constexpr char kFS[] =
4430         "#version 300 es\n"
4431         "precision mediump float;\n"
4432         "out vec4 my_FragColor;\n"
4433         "uniform int u_zero;\n"
4434         "void main() {\n"
4435         "    mat2 m = mat2(0.0, 0.0, 0.0, 0.0);\n"
4436         "    m[u_zero + 1][u_zero + 1] = float(u_zero + 1);\n"
4437         "    float f = m[1][1];\n"
4438         "    my_FragColor = vec4(1.0 - f, f, 0.0, 1.0);\n"
4439         "}\n";
4440 
4441     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4442     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
4443     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4444 }
4445 
4446 class WebGLGLSLTest : public GLSLTest
4447 {
4448   protected:
WebGLGLSLTest()4449     WebGLGLSLTest() { setWebGLCompatibilityEnabled(true); }
4450 };
4451 
4452 class WebGL2GLSLTest : public GLSLTest
4453 {
4454   protected:
WebGL2GLSLTest()4455     WebGL2GLSLTest() { setWebGLCompatibilityEnabled(true); }
4456 };
4457 
TEST_P(WebGLGLSLTest,MaxVaryingVec4PlusFragCoord)4458 TEST_P(WebGLGLSLTest, MaxVaryingVec4PlusFragCoord)
4459 {
4460     GLint maxVaryings = 0;
4461     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4462 
4463     // Generate shader code that uses gl_FragCoord, a special fragment shader variables.
4464     // This test should fail, since we are really using (maxVaryings + 1) varyings.
4465     VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, true, false, false, false);
4466 }
4467 
TEST_P(WebGLGLSLTest,MaxVaryingVec4PlusPointCoord)4468 TEST_P(WebGLGLSLTest, MaxVaryingVec4PlusPointCoord)
4469 {
4470     GLint maxVaryings = 0;
4471     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4472 
4473     // Generate shader code that uses gl_FragCoord, a special fragment shader variables.
4474     // This test should fail, since we are really using (maxVaryings + 1) varyings.
4475     VaryingTestBase(0, 0, 0, 0, 0, 0, maxVaryings, 0, false, true, false, false);
4476 }
4477 
TEST_P(WebGLGLSLTest,MaxPlusOneVaryingVec3)4478 TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec3)
4479 {
4480     GLint maxVaryings = 0;
4481     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4482 
4483     VaryingTestBase(0, 0, 0, 0, maxVaryings + 1, 0, 0, 0, false, false, false, false);
4484 }
4485 
TEST_P(WebGLGLSLTest,MaxPlusOneVaryingVec3Array)4486 TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec3Array)
4487 {
4488     GLint maxVaryings = 0;
4489     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4490 
4491     VaryingTestBase(0, 0, 0, 0, 0, maxVaryings / 2 + 1, 0, 0, false, false, false, false);
4492 }
4493 
TEST_P(WebGLGLSLTest,MaxVaryingVec3AndOneVec2)4494 TEST_P(WebGLGLSLTest, MaxVaryingVec3AndOneVec2)
4495 {
4496     GLint maxVaryings = 0;
4497     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4498 
4499     VaryingTestBase(0, 0, 1, 0, maxVaryings, 0, 0, 0, false, false, false, false);
4500 }
4501 
TEST_P(WebGLGLSLTest,MaxPlusOneVaryingVec2)4502 TEST_P(WebGLGLSLTest, MaxPlusOneVaryingVec2)
4503 {
4504     GLint maxVaryings = 0;
4505     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4506 
4507     VaryingTestBase(0, 0, 2 * maxVaryings + 1, 0, 0, 0, 0, 0, false, false, false, false);
4508 }
4509 
TEST_P(WebGLGLSLTest,MaxVaryingVec3ArrayAndMaxPlusOneFloatArray)4510 TEST_P(WebGLGLSLTest, MaxVaryingVec3ArrayAndMaxPlusOneFloatArray)
4511 {
4512     GLint maxVaryings = 0;
4513     glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
4514 
4515     VaryingTestBase(0, maxVaryings / 2 + 1, 0, 0, 0, 0, 0, maxVaryings / 2, false, false, false,
4516                     false);
4517 }
4518 
4519 // Test that FindLSB and FindMSB return correct values in their corner cases.
TEST_P(GLSLTest_ES31,FindMSBAndFindLSBCornerCases)4520 TEST_P(GLSLTest_ES31, FindMSBAndFindLSBCornerCases)
4521 {
4522     // Suspecting AMD driver bug - failure seen on bots running on AMD R5 230.
4523     ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL() && IsLinux());
4524 
4525     // Failing on N5X Oreo http://anglebug.com/42261013
4526     ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
4527 
4528     constexpr char kFS[] =
4529         "#version 310 es\n"
4530         "precision mediump float;\n"
4531         "out vec4 my_FragColor;\n"
4532         "uniform int u_zero;\n"
4533         "void main() {\n"
4534         "    if (findLSB(u_zero) == -1 && findMSB(u_zero) == -1 && findMSB(u_zero - 1) == -1)\n"
4535         "    {\n"
4536         "        my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
4537         "    }\n"
4538         "    else\n"
4539         "    {\n"
4540         "        my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
4541         "    }\n"
4542         "}\n";
4543 
4544     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4545     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
4546     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4547 }
4548 
4549 // Test that reading from a swizzled vector that is dynamically indexed succeeds.
TEST_P(GLSLTest_ES3,ReadFromDynamicIndexingOfSwizzledVector)4550 TEST_P(GLSLTest_ES3, ReadFromDynamicIndexingOfSwizzledVector)
4551 {
4552     constexpr char kFS[] = R"(#version 300 es
4553 precision highp float;
4554 
4555 uniform int index;
4556 uniform vec4 data;
4557 
4558 out vec4 color;
4559 void main() {
4560     color = vec4(vec4(data.x, data.y, data.z, data.w).zyxw[index], 0, 0, 1);
4561 })";
4562 
4563     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4564     glUseProgram(program);
4565 
4566     GLint dataLoc = glGetUniformLocation(program, "data");
4567     glUniform4f(dataLoc, 0.2, 0.4, 0.6, 0.8);
4568     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
4569 
4570     EXPECT_PIXEL_NEAR(0, 0, 153, 0, 0, 255, 1);
4571 }
4572 
4573 // Test that writing into a swizzled vector that is dynamically indexed succeeds.
TEST_P(GLSLTest_ES3,WriteIntoDynamicIndexingOfSwizzledVector)4574 TEST_P(GLSLTest_ES3, WriteIntoDynamicIndexingOfSwizzledVector)
4575 {
4576     // http://anglebug.com/40644616
4577     ANGLE_SKIP_TEST_IF(IsOpenGL());
4578 
4579     // The shader first assigns v.x to v.z (1.0)
4580     // Then v.y to v.y (2.0)
4581     // Then v.z to v.x (1.0)
4582     constexpr char kFS[] =
4583         "#version 300 es\n"
4584         "precision highp float;\n"
4585         "out vec4 my_FragColor;\n"
4586         "void main() {\n"
4587         "    vec3 v = vec3(1.0, 2.0, 3.0);\n"
4588         "    for (int i = 0; i < 3; i++) {\n"
4589         "        v.zyx[i] = v[i];\n"
4590         "    }\n"
4591         "    my_FragColor = distance(v, vec3(1.0, 2.0, 1.0)) < 0.01 ? vec4(0, 1, 0, 1) : vec4(1, "
4592         "0, 0, 1);\n"
4593         "}\n";
4594 
4595     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4596     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
4597     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4598 }
4599 
4600 // Test including Ternary using a uniform block is correctly
4601 // expanded.
TEST_P(GLSLTest_ES3,NamelessUniformBlockTernary)4602 TEST_P(GLSLTest_ES3, NamelessUniformBlockTernary)
4603 {
4604     const char kVS[] = R"(#version 300 es
4605     precision highp float;
4606     out vec4 color_interp;
4607     void  main()
4608     {
4609         color_interp = vec4(0.0);
4610     }
4611 )";
4612     const char kFS[] = R"(#version 300 es
4613     precision highp float;
4614     out vec4 fragColor;
4615     in vec4 color_interp;
4616 layout(std140) uniform TestData {
4617     int a;
4618     int b;
4619 };
4620 void main()
4621 {
4622     int c, a1;
4623     a1 += c > 0 ? a : b;
4624     fragColor = vec4(a1,a1,a1,1.0);
4625 }
4626 )";
4627     ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
4628 }
4629 
4630 // Test that uniform block variables work as comma expression results.
TEST_P(GLSLTest_ES3,UniformBlockCommaExpressionResult)4631 TEST_P(GLSLTest_ES3, UniformBlockCommaExpressionResult)
4632 {
4633     constexpr char kFS[] = R"(#version 300 es
4634 precision highp float;
4635 layout (std140) uniform C {
4636     float u;
4637     float v;
4638 };
4639 out vec4 o;
4640 void main() {
4641     vec2 z = vec2(1.0 - u, v);
4642     vec2 b = vec2((z=z, u)); // Being tested.
4643     o = vec4(b.x, z.x, b.x, 1.0);
4644 })";
4645     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
4646     glUseProgram(program);
4647 
4648     constexpr GLfloat kInput1Data[2] = {1.f, 0.f};
4649     GLBuffer input1;
4650     glBindBuffer(GL_UNIFORM_BUFFER, input1);
4651     glBufferData(GL_UNIFORM_BUFFER, sizeof(GLfloat) * 2, &kInput1Data, GL_STATIC_COPY);
4652     const GLuint kInput1Index = glGetUniformBlockIndex(program, "C");
4653     glUniformBlockBinding(program, kInput1Index, 1);
4654     glBindBufferBase(GL_UNIFORM_BUFFER, 1, input1);
4655     glBindBuffer(GL_UNIFORM_BUFFER, 0);
4656     ASSERT_GL_NO_ERROR();
4657 
4658     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
4659     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::magenta);
4660     ASSERT_GL_NO_ERROR();
4661 }
4662 
4663 // Test that the length() method is correctly translated in Vulkan atomic counter buffer emulation.
TEST_P(GLSLTest_ES31,AtomicCounterArrayLength)4664 TEST_P(GLSLTest_ES31, AtomicCounterArrayLength)
4665 {
4666     // Crashes on an assertion.  The driver reports no atomic counter buffers when queried from the
4667     // program, but ANGLE believes there to be one.
4668     //
4669     // This is likely due to the fact that ANGLE generates the following code, as a side effect of
4670     // the code on which .length() is being called:
4671     //
4672     //     _uac1[(_uvalue = _utestSideEffectValue)];
4673     //
4674     // The driver is optimizing the subscription out, and calling the atomic counter inactive.  This
4675     // was observed on nvidia, mesa and amd/windows.
4676     //
4677     // The fix would be for ANGLE to skip uniforms it believes should exist, but when queried, the
4678     // driver says don't.
4679     //
4680     // http://anglebug.com/42262426
4681     ANGLE_SKIP_TEST_IF(IsOpenGL());
4682 
4683     constexpr char kCS[] = R"(#version 310 es
4684 precision mediump float;
4685 layout(local_size_x=1) in;
4686 
4687 layout(binding = 0) uniform atomic_uint ac1[2][3][4];
4688 uniform uint testSideEffectValue;
4689 
4690 layout(binding = 1, std140) buffer Result
4691 {
4692     uint value;
4693 } result;
4694 
4695 void main() {
4696     bool passed = true;
4697     if (ac1.length() != 2)
4698     {
4699         passed = false;
4700     }
4701     uint value = 0u;
4702     if (ac1[value = testSideEffectValue].length() != 3)
4703     {
4704         passed = false;
4705     }
4706     if (value != testSideEffectValue)
4707     {
4708         passed = false;
4709     }
4710     if (ac1[1][value = testSideEffectValue + 1u].length() != 4)
4711     {
4712         passed = false;
4713     }
4714     if (value != testSideEffectValue + 1u)
4715     {
4716         passed = false;
4717     }
4718     result.value = passed ? 255u : 127u;
4719 })";
4720 
4721     constexpr unsigned int kUniformTestValue     = 17;
4722     constexpr unsigned int kExpectedSuccessValue = 255;
4723     constexpr unsigned int kAtomicCounterRows    = 2;
4724     constexpr unsigned int kAtomicCounterCols    = 3;
4725 
4726     GLint maxAtomicCounters = 0;
4727     glGetIntegerv(GL_MAX_COMPUTE_ATOMIC_COUNTERS, &maxAtomicCounters);
4728     EXPECT_GL_NO_ERROR();
4729 
4730     // Required minimum is 8 by the spec
4731     EXPECT_GE(maxAtomicCounters, 8);
4732     ANGLE_SKIP_TEST_IF(static_cast<uint32_t>(maxAtomicCounters) <
4733                        kAtomicCounterRows * kAtomicCounterCols);
4734 
4735     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
4736     glUseProgram(program);
4737 
4738     constexpr unsigned int kBufferData[kAtomicCounterRows * kAtomicCounterCols] = {};
4739     GLBuffer atomicCounterBuffer;
4740     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
4741     glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(kBufferData), kBufferData, GL_STATIC_DRAW);
4742     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
4743 
4744     constexpr unsigned int kOutputInitValue = 0;
4745     GLBuffer shaderStorageBuffer;
4746     glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer);
4747     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kOutputInitValue), &kOutputInitValue,
4748                  GL_STATIC_DRAW);
4749     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, shaderStorageBuffer);
4750 
4751     GLint uniformLocation = glGetUniformLocation(program, "testSideEffectValue");
4752     EXPECT_NE(uniformLocation, -1);
4753     glUniform1ui(uniformLocation, kUniformTestValue);
4754     EXPECT_GL_NO_ERROR();
4755 
4756     glDispatchCompute(1, 1, 1);
4757 
4758     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4759 
4760     const GLuint *ptr = reinterpret_cast<const GLuint *>(
4761         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(GLuint), GL_MAP_READ_BIT));
4762     EXPECT_EQ(*ptr, kExpectedSuccessValue);
4763     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4764 }
4765 
4766 // Test that inactive images don't cause any errors.
TEST_P(GLSLTest_ES31,InactiveImages)4767 TEST_P(GLSLTest_ES31, InactiveImages)
4768 {
4769     ANGLE_SKIP_TEST_IF(IsD3D11());
4770 
4771     constexpr char kCS[] = R"(#version 310 es
4772 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
4773 layout(rgba32ui) uniform highp readonly uimage2D image1;
4774 layout(rgba32ui) uniform highp readonly uimage2D image2[4];
4775 void main()
4776 {
4777 })";
4778 
4779     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
4780 
4781     glUseProgram(program);
4782     glDispatchCompute(1, 1, 1);
4783     EXPECT_GL_NO_ERROR();
4784 
4785     // Verify that the images are indeed inactive.
4786     GLuint index = glGetProgramResourceIndex(program, GL_UNIFORM, "image1");
4787     EXPECT_GL_NO_ERROR();
4788     EXPECT_EQ(GL_INVALID_INDEX, index);
4789 
4790     index = glGetProgramResourceIndex(program, GL_UNIFORM, "image2");
4791     EXPECT_GL_NO_ERROR();
4792     EXPECT_EQ(GL_INVALID_INDEX, index);
4793 }
4794 
4795 // Test that inactive atomic counters don't cause any errors.
TEST_P(GLSLTest_ES31,InactiveAtomicCounters)4796 TEST_P(GLSLTest_ES31, InactiveAtomicCounters)
4797 {
4798     constexpr char kCS[] = R"(#version 310 es
4799 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
4800 layout(binding = 0, offset = 0) uniform atomic_uint ac1;
4801 layout(binding = 0, offset = 4) uniform atomic_uint ac2[5];
4802 void main()
4803 {
4804 })";
4805 
4806     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
4807 
4808     glUseProgram(program);
4809     glDispatchCompute(1, 1, 1);
4810     EXPECT_GL_NO_ERROR();
4811 
4812     // Verify that the atomic counters are indeed inactive.
4813     GLuint index = glGetProgramResourceIndex(program, GL_UNIFORM, "ac1");
4814     EXPECT_GL_NO_ERROR();
4815     EXPECT_EQ(GL_INVALID_INDEX, index);
4816 
4817     index = glGetProgramResourceIndex(program, GL_UNIFORM, "ac2");
4818     EXPECT_GL_NO_ERROR();
4819     EXPECT_EQ(GL_INVALID_INDEX, index);
4820 }
4821 
4822 // Test that inactive samplers in structs don't cause any errors.
TEST_P(GLSLTest_ES31,InactiveSamplersInStructCS)4823 TEST_P(GLSLTest_ES31, InactiveSamplersInStructCS)
4824 {
4825     constexpr char kCS[] = R"(#version 310 es
4826 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
4827 struct S
4828 {
4829     vec4 v;
4830     sampler2D t[10];
4831 };
4832 uniform S s;
4833 void main()
4834 {
4835 })";
4836 
4837     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
4838 
4839     glUseProgram(program);
4840     glDispatchCompute(1, 1, 1);
4841     EXPECT_GL_NO_ERROR();
4842 }
4843 
4844 // Test that array indices for arrays of arrays of basic types work as expected.
TEST_P(GLSLTest_ES31,ArraysOfArraysBasicType)4845 TEST_P(GLSLTest_ES31, ArraysOfArraysBasicType)
4846 {
4847     constexpr char kFS[] =
4848         "#version 310 es\n"
4849         "precision mediump float;\n"
4850         "out vec4 my_FragColor;\n"
4851         "uniform ivec2 test[2][2];\n"
4852         "void main() {\n"
4853         "    bool passed = true;\n"
4854         "    for (int i = 0; i < 2; i++) {\n"
4855         "        for (int j = 0; j < 2; j++) {\n"
4856         "            if (test[i][j] != ivec2(i + 1, j + 1)) {\n"
4857         "                passed = false;\n"
4858         "            }\n"
4859         "        }\n"
4860         "    }\n"
4861         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4862         "}\n";
4863 
4864     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4865     glUseProgram(program);
4866     for (int i = 0; i < 2; i++)
4867     {
4868         for (int j = 0; j < 2; j++)
4869         {
4870             std::stringstream uniformName;
4871             uniformName << "test[" << i << "][" << j << "]";
4872             GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
4873             // All array indices should be used.
4874             EXPECT_NE(uniformLocation, -1);
4875             glUniform2i(uniformLocation, i + 1, j + 1);
4876         }
4877     }
4878     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
4879     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4880 }
4881 
4882 // Test that array indices for arrays of arrays of basic types work as expected
4883 // inside blocks.
TEST_P(GLSLTest_ES31,ArraysOfArraysBlockBasicType)4884 TEST_P(GLSLTest_ES31, ArraysOfArraysBlockBasicType)
4885 {
4886     // anglebug.com/42262465 - fails on AMD Windows
4887     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL());
4888     constexpr char kFS[] =
4889         "#version 310 es\n"
4890         "precision mediump float;\n"
4891         "out vec4 my_FragColor;\n"
4892         "layout(packed) uniform UBO { ivec2 test[2][2]; } ubo_data;\n"
4893         "void main() {\n"
4894         "    bool passed = true;\n"
4895         "    for (int i = 0; i < 2; i++) {\n"
4896         "        for (int j = 0; j < 2; j++) {\n"
4897         "            if (ubo_data.test[i][j] != ivec2(i + 1, j + 1)) {\n"
4898         "                passed = false;\n"
4899         "            }\n"
4900         "        }\n"
4901         "    }\n"
4902         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4903         "}\n";
4904 
4905     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4906     glUseProgram(program);
4907     // Use interface queries to determine buffer size and offset
4908     GLuint uboBlockIndex   = glGetProgramResourceIndex(program, GL_UNIFORM_BLOCK, "UBO");
4909     GLenum uboDataSizeProp = GL_BUFFER_DATA_SIZE;
4910     GLint uboDataSize;
4911     glGetProgramResourceiv(program, GL_UNIFORM_BLOCK, uboBlockIndex, 1, &uboDataSizeProp, 1,
4912                            nullptr, &uboDataSize);
4913     std::unique_ptr<char[]> uboData(new char[uboDataSize]);
4914     for (int i = 0; i < 2; i++)
4915     {
4916         std::stringstream resourceName;
4917         resourceName << "UBO.test[" << i << "][0]";
4918         GLenum resourceProps[] = {GL_ARRAY_STRIDE, GL_OFFSET};
4919         struct
4920         {
4921             GLint stride;
4922             GLint offset;
4923         } values;
4924         GLuint resourceIndex =
4925             glGetProgramResourceIndex(program, GL_UNIFORM, resourceName.str().c_str());
4926         ASSERT_NE(resourceIndex, GL_INVALID_INDEX);
4927         glGetProgramResourceiv(program, GL_UNIFORM, resourceIndex, 2, &resourceProps[0], 2, nullptr,
4928                                &values.stride);
4929         for (int j = 0; j < 2; j++)
4930         {
4931             GLint(&dataPtr)[2] =
4932                 *reinterpret_cast<GLint(*)[2]>(&uboData[values.offset + j * values.stride]);
4933             dataPtr[0] = i + 1;
4934             dataPtr[1] = j + 1;
4935         }
4936     }
4937     GLBuffer ubo;
4938     glBindBuffer(GL_UNIFORM_BUFFER, ubo);
4939     glBufferData(GL_UNIFORM_BUFFER, uboDataSize, &uboData[0], GL_STATIC_DRAW);
4940     GLuint ubo_index = glGetUniformBlockIndex(program, "UBO");
4941     ASSERT_NE(ubo_index, GL_INVALID_INDEX);
4942     glUniformBlockBinding(program, ubo_index, 5);
4943     glBindBufferBase(GL_UNIFORM_BUFFER, 5, ubo);
4944     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
4945     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4946 }
4947 
4948 // Test that arrays of arrays of samplers work as expected.
TEST_P(GLSLTest_ES31,ArraysOfArraysSampler)4949 TEST_P(GLSLTest_ES31, ArraysOfArraysSampler)
4950 {
4951     constexpr char kFS[] =
4952         "#version 310 es\n"
4953         "precision mediump float;\n"
4954         "out vec4 my_FragColor;\n"
4955         "uniform mediump isampler2D test[2][2];\n"
4956         "void main() {\n"
4957         "    bool passed = true;\n"
4958         "#define DO_CHECK(i,j) \\\n"
4959         "    if (texture(test[i][j], vec2(0.0, 0.0)) != ivec4(i + 1, j + 1, 0, 1)) { \\\n"
4960         "        passed = false; \\\n"
4961         "    }\n"
4962         "    DO_CHECK(0, 0)\n"
4963         "    DO_CHECK(0, 1)\n"
4964         "    DO_CHECK(1, 0)\n"
4965         "    DO_CHECK(1, 1)\n"
4966         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
4967         "}\n";
4968 
4969     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4970     glUseProgram(program);
4971     GLTexture textures[2][2];
4972     for (int i = 0; i < 2; i++)
4973     {
4974         for (int j = 0; j < 2; j++)
4975         {
4976             // First generate the texture
4977             int textureUnit = i * 2 + j;
4978             glActiveTexture(GL_TEXTURE0 + textureUnit);
4979             glBindTexture(GL_TEXTURE_2D, textures[i][j]);
4980             GLint texData[2] = {i + 1, j + 1};
4981             glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32I, 1, 1, 0, GL_RG_INTEGER, GL_INT, &texData[0]);
4982             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4983             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4984             // Then send it as a uniform
4985             std::stringstream uniformName;
4986             uniformName << "test[" << i << "][" << j << "]";
4987             GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
4988             // All array indices should be used.
4989             EXPECT_NE(uniformLocation, -1);
4990             glUniform1i(uniformLocation, textureUnit);
4991         }
4992     }
4993     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
4994     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4995 }
4996 
4997 // Test that arrays of arrays of images work as expected.
TEST_P(GLSLTest_ES31,ArraysOfArraysImage)4998 TEST_P(GLSLTest_ES31, ArraysOfArraysImage)
4999 {
5000     // http://anglebug.com/42263641
5001     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
5002 
5003     // Fails on D3D due to mistranslation.
5004     ANGLE_SKIP_TEST_IF(IsD3D());
5005 
5006     // Fails on Android on GLES.
5007     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
5008 
5009     GLint maxTextures, maxComputeImageUniforms;
5010     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextures);
5011     glGetIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &maxComputeImageUniforms);
5012     ANGLE_SKIP_TEST_IF(maxTextures < 1 * 2 * 3);
5013     ANGLE_SKIP_TEST_IF(maxComputeImageUniforms < 1 * 2 * 3);
5014 
5015     constexpr char kComputeShader[] = R"(#version 310 es
5016         layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
5017         layout(binding = 0, r32ui) uniform highp readonly uimage2D image[1][2][3];
5018         layout(binding = 1, std430) buffer Output {
5019             uint image_value;
5020         } outbuf;
5021 
5022         void main(void)
5023         {
5024             outbuf.image_value = uint(0.0);
5025             outbuf.image_value += imageLoad(image[0][0][0], ivec2(0, 0)).x;
5026             outbuf.image_value += imageLoad(image[0][0][1], ivec2(0, 0)).x;
5027             outbuf.image_value += imageLoad(image[0][0][2], ivec2(0, 0)).x;
5028             outbuf.image_value += imageLoad(image[0][1][0], ivec2(0, 0)).x;
5029             outbuf.image_value += imageLoad(image[0][1][1], ivec2(0, 0)).x;
5030             outbuf.image_value += imageLoad(image[0][1][2], ivec2(0, 0)).x;
5031         })";
5032     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
5033     EXPECT_GL_NO_ERROR();
5034 
5035     glUseProgram(program);
5036 
5037     GLuint outputInitData[1] = {10};
5038     GLBuffer outputBuffer;
5039     glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
5040     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), outputInitData, GL_STATIC_DRAW);
5041     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
5042     EXPECT_GL_NO_ERROR();
5043 
5044     GLuint imageData = 200u;
5045     GLTexture images[1][2][3];
5046     for (int i = 0; i < 1; i++)
5047     {
5048         for (int j = 0; j < 2; j++)
5049         {
5050             for (int k = 0; k < 3; k++)
5051             {
5052                 glBindTexture(GL_TEXTURE_2D, images[i][j][k]);
5053                 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
5054                 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT,
5055                                 &imageData);
5056                 glBindImageTexture(i * 6 + j * 3 + k, images[i][j][k], 0, GL_FALSE, 0, GL_READ_ONLY,
5057                                    GL_R32UI);
5058                 EXPECT_GL_NO_ERROR();
5059             }
5060         }
5061     }
5062 
5063     glDispatchCompute(1, 1, 1);
5064     EXPECT_GL_NO_ERROR();
5065 
5066     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5067 
5068     // read back
5069     const GLuint *ptr = reinterpret_cast<const GLuint *>(
5070         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
5071     memcpy(outputInitData, ptr, sizeof(outputInitData));
5072     EXPECT_EQ(outputInitData[0], imageData * 1 * 2 * 3);
5073     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
5074 }
5075 
5076 // Test that multiple arrays of arrays of images work as expected.
TEST_P(GLSLTest_ES31,ConsecutiveArraysOfArraysImage)5077 TEST_P(GLSLTest_ES31, ConsecutiveArraysOfArraysImage)
5078 {
5079     // http://anglebug.com/42263641
5080     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
5081 
5082     // Fails on D3D due to mistranslation.
5083     ANGLE_SKIP_TEST_IF(IsD3D());
5084 
5085     constexpr GLsizei kImage1Layers = 3;
5086     constexpr GLsizei kImage1Rows   = 2;
5087     constexpr GLsizei kImage1Cols   = 1;
5088     constexpr GLsizei kImage2Rows   = 2;
5089     constexpr GLsizei kImage2Cols   = 4;
5090 
5091     constexpr GLsizei kImage1Units = kImage1Layers * kImage1Rows * kImage1Cols;
5092     constexpr GLsizei kImage2Units = kImage2Rows * kImage2Cols;
5093     constexpr GLsizei kImage3Units = 1;
5094 
5095     constexpr GLsizei kTotalImageCount = kImage1Units + kImage2Units + kImage3Units;
5096 
5097     GLint maxTextures, maxComputeImageUniforms;
5098     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextures);
5099     glGetIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &maxComputeImageUniforms);
5100     ANGLE_SKIP_TEST_IF(maxTextures < kTotalImageCount);
5101     ANGLE_SKIP_TEST_IF(maxComputeImageUniforms < kTotalImageCount);
5102 
5103     constexpr char kComputeShader[] = R"(#version 310 es
5104         layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
5105         layout(binding = 0, r32ui) uniform highp readonly uimage2D image1[3][2][1];
5106         layout(binding = 6, r32ui) uniform highp readonly uimage2D image2[2][4];
5107         layout(binding = 14, r32ui) uniform highp readonly uimage2D image3;
5108         layout(binding = 0, std430) buffer Output {
5109             uint image_value;
5110         } outbuf;
5111 
5112         void main(void)
5113         {
5114             outbuf.image_value = uint(0.0);
5115 
5116             outbuf.image_value += imageLoad(image1[0][0][0], ivec2(0, 0)).x;
5117             outbuf.image_value += imageLoad(image1[0][1][0], ivec2(0, 0)).x;
5118             outbuf.image_value += imageLoad(image1[1][0][0], ivec2(0, 0)).x;
5119             outbuf.image_value += imageLoad(image1[1][1][0], ivec2(0, 0)).x;
5120             outbuf.image_value += imageLoad(image1[2][0][0], ivec2(0, 0)).x;
5121             outbuf.image_value += imageLoad(image1[2][1][0], ivec2(0, 0)).x;
5122 
5123             outbuf.image_value += imageLoad(image2[0][0], ivec2(0, 0)).x;
5124             outbuf.image_value += imageLoad(image2[0][1], ivec2(0, 0)).x;
5125             outbuf.image_value += imageLoad(image2[0][2], ivec2(0, 0)).x;
5126             outbuf.image_value += imageLoad(image2[0][3], ivec2(0, 0)).x;
5127             outbuf.image_value += imageLoad(image2[1][0], ivec2(0, 0)).x;
5128             outbuf.image_value += imageLoad(image2[1][1], ivec2(0, 0)).x;
5129             outbuf.image_value += imageLoad(image2[1][2], ivec2(0, 0)).x;
5130             outbuf.image_value += imageLoad(image2[1][3], ivec2(0, 0)).x;
5131 
5132             outbuf.image_value += imageLoad(image3, ivec2(0, 0)).x;
5133         })";
5134     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
5135     EXPECT_GL_NO_ERROR();
5136 
5137     glUseProgram(program);
5138 
5139     constexpr GLuint kOutputInitData = 10;
5140     GLBuffer outputBuffer;
5141     glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
5142     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kOutputInitData), &kOutputInitData,
5143                  GL_STATIC_DRAW);
5144     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, outputBuffer);
5145     EXPECT_GL_NO_ERROR();
5146 
5147     constexpr GLsizei kImage1Binding = 0;
5148     constexpr GLsizei kImage2Binding = kImage1Binding + kImage1Units;
5149     constexpr GLsizei kImage3Binding = kImage2Binding + kImage2Units;
5150 
5151     constexpr GLuint kImage1Data = 13;
5152     GLTexture images1[kImage1Layers][kImage1Rows][kImage1Cols];
5153     for (int layer = 0; layer < kImage1Layers; layer++)
5154     {
5155         for (int row = 0; row < kImage1Rows; row++)
5156         {
5157             for (int col = 0; col < kImage1Cols; col++)
5158             {
5159                 glBindTexture(GL_TEXTURE_2D, images1[layer][row][col]);
5160                 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
5161                 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT,
5162                                 &kImage1Data);
5163                 glBindImageTexture(kImage1Binding + (layer * kImage1Rows + row) * kImage1Cols + col,
5164                                    images1[layer][row][col], 0, GL_FALSE, 0, GL_READ_ONLY,
5165                                    GL_R32UI);
5166                 EXPECT_GL_NO_ERROR();
5167             }
5168         }
5169     }
5170 
5171     constexpr GLuint kImage2Data = 17;
5172     GLTexture images2[kImage2Rows][kImage2Cols];
5173     for (int row = 0; row < kImage2Rows; row++)
5174     {
5175         for (int col = 0; col < kImage2Cols; col++)
5176         {
5177             glBindTexture(GL_TEXTURE_2D, images2[row][col]);
5178             glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
5179             glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT,
5180                             &kImage2Data);
5181             glBindImageTexture(kImage2Binding + row * kImage2Cols + col, images2[row][col], 0,
5182                                GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
5183             EXPECT_GL_NO_ERROR();
5184         }
5185     }
5186 
5187     constexpr GLuint kImage3Data = 19;
5188     GLTexture image3;
5189     glBindTexture(GL_TEXTURE_2D, image3);
5190     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
5191     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &kImage3Data);
5192     glBindImageTexture(kImage3Binding, image3, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
5193     EXPECT_GL_NO_ERROR();
5194 
5195     glDispatchCompute(1, 1, 1);
5196     EXPECT_GL_NO_ERROR();
5197 
5198     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5199 
5200     // read back
5201     const GLuint *ptr = reinterpret_cast<const GLuint *>(
5202         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kOutputInitData), GL_MAP_READ_BIT));
5203     EXPECT_EQ(*ptr,
5204               kImage1Data * kImage1Units + kImage2Data * kImage2Units + kImage3Data * kImage3Units);
5205     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
5206 }
5207 
5208 // Test that arrays of arrays of images of r32f format work when passed to functions.
TEST_P(GLSLTest_ES31,ArraysOfArraysOfR32fImages)5209 TEST_P(GLSLTest_ES31, ArraysOfArraysOfR32fImages)
5210 {
5211     // Skip if GL_OES_shader_image_atomic is not enabled.
5212     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_image_atomic"));
5213 
5214     // http://anglebug.com/42263641
5215     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
5216 
5217     // Fails on D3D due to mistranslation.
5218     ANGLE_SKIP_TEST_IF(IsD3D());
5219 
5220     // Fails on Android on GLES.
5221     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
5222 
5223     // http://anglebug.com/42263895
5224     ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGL());
5225 
5226     GLint maxComputeImageUniforms;
5227     glGetIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &maxComputeImageUniforms);
5228     ANGLE_SKIP_TEST_IF(maxComputeImageUniforms < 7);
5229 
5230     constexpr char kComputeShader[] = R"(#version 310 es
5231 #extension GL_OES_shader_image_atomic : require
5232 
5233 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
5234 layout(binding = 0, r32f) uniform highp image2D image1[2][3];
5235 layout(binding = 6, r32f) uniform highp image2D image2;
5236 
5237 void testFunction(highp image2D imageOut[2][3])
5238 {
5239     // image1 is an array of 1x1 images.
5240     // image2 is a 1x4 image with the following data:
5241     //
5242     // (0, 0): 234.5
5243     // (0, 1): 4.0
5244     // (0, 2): 456.0
5245     // (0, 3): 987.0
5246 
5247 
5248     // Write to [0][0]
5249     imageStore(imageOut[0][0], ivec2(0, 0), vec4(1234.5));
5250 
5251     // Write to [0][1]
5252     imageStore(imageOut[0][1], ivec2(0, 0), imageLoad(image2, ivec2(0, 0)));
5253 
5254     // Write to [0][2]
5255     imageStore(imageOut[0][2], ivec2(0, 0), vec4(imageSize(image2).y));
5256 
5257     // Write to [1][0]
5258     imageStore(imageOut[1][0], ivec2(0,
5259                  imageSize(image2).y - int(imageLoad(image2, ivec2(0, 1)).x)
5260                 ), vec4(678.0));
5261 
5262     // Write to [1][1]
5263     imageStore(imageOut[1][1], ivec2(0, 0),
5264                 vec4(imageAtomicExchange(image2, ivec2(0, 2), 135.0)));
5265 
5266     // Write to [1][2]
5267     imageStore(imageOut[1][2], ivec2(0, 0),
5268                     imageLoad(image2, ivec2(imageSize(image2).x - 1, 3)));
5269 }
5270 
5271 void main(void)
5272 {
5273     testFunction(image1);
5274 })";
5275     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
5276     EXPECT_GL_NO_ERROR();
5277 
5278     glUseProgram(program);
5279 
5280     constexpr GLsizei kImageRows = 2;
5281     constexpr GLsizei kImageCols = 3;
5282     constexpr GLfloat kImageData = 0;
5283     GLTexture images[kImageRows][kImageCols];
5284     for (size_t row = 0; row < kImageRows; row++)
5285     {
5286         for (size_t col = 0; col < kImageCols; col++)
5287         {
5288             glBindTexture(GL_TEXTURE_2D, images[row][col]);
5289             glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, 1, 1);
5290             glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED, GL_FLOAT, &kImageData);
5291             glBindImageTexture(row * kImageCols + col, images[row][col], 0, GL_FALSE, 0,
5292                                GL_READ_WRITE, GL_R32F);
5293             EXPECT_GL_NO_ERROR();
5294         }
5295     }
5296 
5297     constexpr GLsizei kImage2Size                          = 4;
5298     constexpr std::array<GLfloat, kImage2Size> kImage2Data = {
5299         234.5f,
5300         4.0f,
5301         456.0f,
5302         987.0f,
5303     };
5304     GLTexture image2;
5305     glBindTexture(GL_TEXTURE_2D, image2);
5306     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, 1, kImage2Size);
5307     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, kImage2Size, GL_RED, GL_FLOAT, kImage2Data.data());
5308     glBindImageTexture(6, image2, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
5309     EXPECT_GL_NO_ERROR();
5310 
5311     glDispatchCompute(1, 1, 1);
5312     EXPECT_GL_NO_ERROR();
5313 
5314     glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5315 
5316     // Verify the previous dispatch with another dispatch
5317     constexpr char kVerifyShader[] = R"(#version 310 es
5318 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
5319 layout(binding = 0, r32f) uniform highp readonly image2D image1[2][3];
5320 layout(binding = 6, r32f) uniform highp readonly image2D image2;
5321 layout(binding = 0, std430) buffer Output {
5322     float image2Data[4];
5323     float image1Data[6];
5324 } outbuf;
5325 
5326 void main(void)
5327 {
5328     for (int i = 0; i < 4; ++i)
5329     {
5330         outbuf.image2Data[i] = imageLoad(image2, ivec2(0, i)).x;
5331     }
5332     outbuf.image1Data[0] = imageLoad(image1[0][0], ivec2(0, 0)).x;
5333     outbuf.image1Data[1] = imageLoad(image1[0][1], ivec2(0, 0)).x;
5334     outbuf.image1Data[2] = imageLoad(image1[0][2], ivec2(0, 0)).x;
5335     outbuf.image1Data[3] = imageLoad(image1[1][0], ivec2(0, 0)).x;
5336     outbuf.image1Data[4] = imageLoad(image1[1][1], ivec2(0, 0)).x;
5337     outbuf.image1Data[5] = imageLoad(image1[1][2], ivec2(0, 0)).x;
5338 })";
5339     ANGLE_GL_COMPUTE_PROGRAM(verifyProgram, kVerifyShader);
5340     EXPECT_GL_NO_ERROR();
5341 
5342     glUseProgram(verifyProgram);
5343 
5344     constexpr std::array<GLfloat, kImage2Size + kImageRows * kImageCols> kOutputInitData = {};
5345     GLBuffer outputBuffer;
5346     glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
5347     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kOutputInitData), kOutputInitData.data(),
5348                  GL_STATIC_DRAW);
5349     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, outputBuffer);
5350     EXPECT_GL_NO_ERROR();
5351 
5352     glDispatchCompute(1, 1, 1);
5353     EXPECT_GL_NO_ERROR();
5354 
5355     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5356 
5357     // Verify
5358     const GLfloat *ptr = reinterpret_cast<const GLfloat *>(
5359         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kOutputInitData), GL_MAP_READ_BIT));
5360 
5361     EXPECT_EQ(ptr[0], kImage2Data[0]);
5362     EXPECT_EQ(ptr[1], kImage2Data[1]);
5363     EXPECT_NEAR(ptr[2], 135.0f, 0.0001f);
5364     EXPECT_EQ(ptr[3], kImage2Data[3]);
5365 
5366     EXPECT_NEAR(ptr[4], 1234.5f, 0.0001f);
5367     EXPECT_NEAR(ptr[5], kImage2Data[0], 0.0001f);
5368     EXPECT_NEAR(ptr[6], kImage2Size, 0.0001f);
5369     EXPECT_NEAR(ptr[7], 678.0f, 0.0001f);
5370     EXPECT_NEAR(ptr[8], kImage2Data[2], 0.0001f);
5371     EXPECT_NEAR(ptr[9], kImage2Data[3], 0.0001f);
5372 
5373     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
5374 }
5375 
5376 // Check that imageLoad gives the correct color after clearing the texture -- anglebug.com/42265826
TEST_P(GLSLTest_ES31,ImageLoadAfterClear)5377 TEST_P(GLSLTest_ES31, ImageLoadAfterClear)
5378 {
5379     ANGLE_GL_PROGRAM(program,
5380                      R"(#version 310 es
5381 precision highp float;
5382 void main()
5383 {
5384     gl_Position.x = ((gl_VertexID & 1) == 0 ? -1.0 : 1.0);
5385     gl_Position.y = ((gl_VertexID & 2) == 0 ? -1.0 : 1.0);
5386     gl_Position.zw = vec2(0, 1);
5387 })",
5388 
5389                      R"(#version 310 es
5390 precision highp float;
5391 layout(binding=0, rgba8) readonly highp uniform image2D img;
5392 out vec4 fragColor;
5393 void main()
5394 {
5395     ivec2 imgcoord = ivec2(floor(gl_FragCoord.xy));
5396     fragColor = vec4(1, 0, 0, 0) + imageLoad(img, imgcoord);
5397 })");
5398     ASSERT_TRUE(program.valid());
5399     glUseProgram(program);
5400 
5401     GLTexture tex;
5402     glBindTexture(GL_TEXTURE_2D, tex);
5403     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, getWindowWidth(), getWindowHeight());
5404     glBindImageTexture(0, tex, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
5405 
5406     // Clear the texture to green.
5407     GLFramebuffer fbo;
5408     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5409     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
5410     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5411     glClearColor(0, 1, 0, 1);
5412     glClear(GL_COLOR_BUFFER_BIT);
5413     glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_FRAMEBUFFER_BARRIER_BIT);
5414 
5415     // Draw the texture via imageLoad, plus red, into the main framebuffer. Make sure the texture
5416     // was still green. (green + red == yellow.)
5417     glBindFramebuffer(GL_FRAMEBUFFER, 0);
5418     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5419     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5420 
5421     EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::yellow);
5422     ASSERT_GL_NO_ERROR();
5423 }
5424 
5425 // Check that writeonly image2D handles can be passed as function args.
TEST_P(GLSLTest_ES31,WriteOnlyImage2DAsFunctionArg)5426 TEST_P(GLSLTest_ES31, WriteOnlyImage2DAsFunctionArg)
5427 {
5428     // Create an image.
5429     GLTexture tex;
5430     glBindTexture(GL_TEXTURE_2D, tex);
5431     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, getWindowWidth(), getWindowHeight());
5432 
5433     // Clear the image to red.
5434     GLFramebuffer fbo;
5435     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5436     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
5437     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5438 
5439     glClearColor(1, 0, 0, 1);
5440     glClear(GL_COLOR_BUFFER_BIT);
5441     glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5442 
5443     const char kVS[] = R"(#version 310 es
5444 precision highp float;
5445 void main()
5446 {
5447     gl_Position.x = ((gl_VertexID & 1) == 0 ? -1.0 : 1.0);
5448     gl_Position.y = ((gl_VertexID & 2) == 0 ? -1.0 : 1.0);
5449     gl_Position.zw = vec2(0, 1);
5450 })";
5451 
5452     const char kFS[] = R"(#version 310 es
5453 precision highp float;
5454 layout(binding=0, rgba8) writeonly highp uniform image2D uniformImage;
5455 void store(writeonly highp image2D img, vec4 color)
5456 {
5457     ivec2 imgcoord = ivec2(floor(gl_FragCoord.xy));
5458     imageStore(img, imgcoord, color);
5459 }
5460 void main()
5461 {
5462     store(uniformImage, vec4(1, 1, 0, 1));
5463 })";
5464 
5465     // Store yellow to the image.
5466     ANGLE_GL_PROGRAM(program, kVS, kFS);
5467     glUseProgram(program);
5468 
5469     glBindFramebuffer(GL_FRAMEBUFFER, 0);
5470     glBindImageTexture(0, tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
5471     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5472     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
5473 
5474     // Check that the image is yellow.
5475     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5476     EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::yellow);
5477     ASSERT_GL_NO_ERROR();
5478 }
5479 
5480 // Check that readonly image2D handles can be passed as function args.
TEST_P(GLSLTest_ES31,ReadOnlyImage2DAsFunctionArg)5481 TEST_P(GLSLTest_ES31, ReadOnlyImage2DAsFunctionArg)
5482 {
5483     const int w = getWindowWidth();
5484     const int h = getWindowHeight();
5485 
5486     // Create an image.
5487     GLTexture tex;
5488     glBindTexture(GL_TEXTURE_2D, tex);
5489     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, w, h);
5490 
5491     const std::vector<GLColor> kInitData(w * h, GLColor::red);
5492     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, kInitData.data());
5493 
5494     // Create a framebuffer.
5495     GLTexture color;
5496     glBindTexture(GL_TEXTURE_2D, color);
5497     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, w, h);
5498 
5499     GLFramebuffer fbo;
5500     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5501     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
5502     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5503 
5504     // Initialize the framebuffer with the contents of the texture.
5505     glClearColor(0, 0, 0, 0);
5506     glClear(GL_COLOR_BUFFER_BIT);
5507 
5508     const char kVS[] = R"(#version 310 es
5509 precision highp float;
5510 void main()
5511 {
5512     gl_Position.x = ((gl_VertexID & 1) == 0 ? -1.0 : 1.0);
5513     gl_Position.y = ((gl_VertexID & 2) == 0 ? -1.0 : 1.0);
5514     gl_Position.zw = vec2(0, 1);
5515 })";
5516 
5517     const char kFS[] = R"(#version 310 es
5518 precision highp float;
5519 layout(binding=0, rgba8) readonly highp uniform image2D uniformImage;
5520 out vec4 color;
5521 vec4 load(readonly highp image2D img)
5522 {
5523     ivec2 imgcoord = ivec2(floor(gl_FragCoord.xy));
5524     return imageLoad(img, imgcoord);
5525 }
5526 void main()
5527 {
5528     color = load(uniformImage);
5529 })";
5530 
5531     ANGLE_GL_PROGRAM(program, kVS, kFS);
5532     glUseProgram(program);
5533 
5534     glBindImageTexture(0, tex, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
5535     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5536 
5537     // Check that the framebuffer is red.
5538     EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::red);
5539     ASSERT_GL_NO_ERROR();
5540 }
5541 
5542 // Check that the volatile keyword combined with memoryBarrierImage() allow load/store from
5543 // different aliases of the same image -- anglebug.com/42265813
5544 //
5545 // ES 3.1 requires most image formats to be either readonly or writeonly. (It appears that this
5546 // limitation exists due to atomics, since we still have the volatile keyword and the built-in
5547 // memoryBarrierImage(), which ought to allow us to load and store different aliases of the same
5548 // image.) To test this, we create two aliases of the same image -- one for reading and one for
5549 // writing.
TEST_P(GLSLTest_ES31,AliasedLoadStore)5550 TEST_P(GLSLTest_ES31, AliasedLoadStore)
5551 {
5552 
5553     GLTexture tex;
5554     glBindTexture(GL_TEXTURE_2D, tex);
5555     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, getWindowWidth(), getWindowHeight());
5556 
5557     GLFramebuffer fbo;
5558     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5559     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
5560     glClearColor(1, 0, 0, 1);
5561     glClear(GL_COLOR_BUFFER_BIT);
5562     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5563 
5564     ANGLE_GL_PROGRAM(program,
5565 
5566                      R"(#version 310 es
5567 precision highp float;
5568 void main()
5569 {
5570     gl_Position.x = ((gl_VertexID & 1) == 0 ? -1.0 : 1.0);
5571     gl_Position.y = ((gl_VertexID & 2) == 0 ? -1.0 : 1.0);
5572     gl_Position.zw = vec2(0, 1);
5573 })",
5574 
5575                      R"(#version 310 es
5576 precision highp float;
5577 layout(binding=0, rgba8) volatile readonly highp uniform image2D img_r;
5578 layout(binding=0, rgba8) volatile writeonly highp uniform image2D img_w;
5579 uniform vec4 drawColor;
5580 void main()
5581 {
5582     ivec2 coord = ivec2(floor(gl_FragCoord.xy));
5583     vec4 oldval = imageLoad(img_r, coord);
5584     memoryBarrierImage();
5585     imageStore(img_w, coord, oldval + drawColor);
5586 })");
5587 
5588     ASSERT_TRUE(program.valid());
5589     glUseProgram(program);
5590     GLint drawColorLocation = glGetUniformLocation(program, "drawColor");
5591 
5592     // Tell the driver the binding is GL_READ_WRITE, since it will be referenced by two image2Ds:
5593     // one readeonly and one writeonly.
5594     glBindImageTexture(0, tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8);
5595 
5596     glBindFramebuffer(GL_FRAMEBUFFER, 0);
5597     glUniform4f(drawColorLocation, 0, 1, 0, 0);
5598     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5599     glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5600 
5601     // Ensure the cleared color was loaded before we stored.
5602     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5603     EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::yellow);
5604 
5605     ASSERT_GL_NO_ERROR();
5606 
5607     // Now make two draws to ensure the imageStore is coherent.
5608     glClear(GL_COLOR_BUFFER_BIT);
5609     glBindFramebuffer(GL_FRAMEBUFFER, 0);
5610     glUniform4f(drawColorLocation, 0, 1, 0, 0);
5611     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5612     glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5613     glUniform4f(drawColorLocation, 0, 0, 1, 0);
5614     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5615     glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5616 
5617     // Ensure the first imageStore was loaded by the second imageLoad.
5618     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5619     EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::white);
5620 
5621     ASSERT_GL_NO_ERROR();
5622 }
5623 
5624 // Test that structs containing arrays of samplers work as expected.
TEST_P(GLSLTest_ES31,StructArraySampler)5625 TEST_P(GLSLTest_ES31, StructArraySampler)
5626 {
5627     constexpr char kFS[] =
5628         "#version 310 es\n"
5629         "precision mediump float;\n"
5630         "out vec4 my_FragColor;\n"
5631         "struct Data { mediump sampler2D data[2]; };\n"
5632         "uniform Data test;\n"
5633         "void main() {\n"
5634         "    my_FragColor = vec4(texture(test.data[0], vec2(0.0, 0.0)).rg,\n"
5635         "                        texture(test.data[1], vec2(0.0, 0.0)).rg);\n"
5636         "}\n";
5637 
5638     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5639     glUseProgram(program);
5640     GLTexture textures[2];
5641     GLColor expected = MakeGLColor(32, 64, 96, 255);
5642     GLubyte data[6]  = {};  // Two bytes of padding, so that texture can be initialized with 4 bytes
5643     memcpy(data, expected.data(), sizeof(expected));
5644     for (int i = 0; i < 2; i++)
5645     {
5646         glActiveTexture(GL_TEXTURE0 + i);
5647         glBindTexture(GL_TEXTURE_2D, textures[i]);
5648         // Each element provides two components.
5649         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data + 2 * i);
5650         std::stringstream uniformName;
5651         uniformName << "test.data[" << i << "]";
5652         // Then send it as a uniform
5653         GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
5654         // The uniform should be active.
5655         EXPECT_NE(uniformLocation, -1);
5656         glUniform1i(uniformLocation, i);
5657     }
5658     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
5659     EXPECT_PIXEL_COLOR_EQ(0, 0, expected);
5660 }
5661 
5662 // Test that arrays of arrays of samplers inside structs work as expected.
TEST_P(GLSLTest_ES31,StructArrayArraySampler)5663 TEST_P(GLSLTest_ES31, StructArrayArraySampler)
5664 {
5665     constexpr char kFS[] =
5666         "#version 310 es\n"
5667         "precision mediump float;\n"
5668         "out vec4 my_FragColor;\n"
5669         "struct Data { mediump isampler2D data[2][2]; };\n"
5670         "uniform Data test;\n"
5671         "void main() {\n"
5672         "    bool passed = true;\n"
5673         "#define DO_CHECK(i,j) \\\n"
5674         "    if (texture(test.data[i][j], vec2(0.0, 0.0)) != ivec4(i + 1, j + 1, 0, 1)) { \\\n"
5675         "        passed = false; \\\n"
5676         "    }\n"
5677         "    DO_CHECK(0, 0)\n"
5678         "    DO_CHECK(0, 1)\n"
5679         "    DO_CHECK(1, 0)\n"
5680         "    DO_CHECK(1, 1)\n"
5681         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
5682         "}\n";
5683 
5684     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5685     glUseProgram(program);
5686     GLTexture textures[2][2];
5687     for (int i = 0; i < 2; i++)
5688     {
5689         for (int j = 0; j < 2; j++)
5690         {
5691             // First generate the texture
5692             int textureUnit = i * 2 + j;
5693             glActiveTexture(GL_TEXTURE0 + textureUnit);
5694             glBindTexture(GL_TEXTURE_2D, textures[i][j]);
5695             GLint texData[2] = {i + 1, j + 1};
5696             glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32I, 1, 1, 0, GL_RG_INTEGER, GL_INT, &texData[0]);
5697             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5698             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5699             // Then send it as a uniform
5700             std::stringstream uniformName;
5701             uniformName << "test.data[" << i << "][" << j << "]";
5702             GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
5703             // All array indices should be used.
5704             EXPECT_NE(uniformLocation, -1);
5705             glUniform1i(uniformLocation, textureUnit);
5706         }
5707     }
5708     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
5709     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5710 }
5711 
5712 // Test that an array of structs with arrays of arrays of samplers works.
TEST_P(GLSLTest_ES31,ArrayStructArrayArraySampler)5713 TEST_P(GLSLTest_ES31, ArrayStructArrayArraySampler)
5714 {
5715     GLint numTextures;
5716     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
5717     ANGLE_SKIP_TEST_IF(numTextures < 2 * (2 * 2 + 2 * 2));
5718     constexpr char kFS[] =
5719         "#version 310 es\n"
5720         "precision mediump float;\n"
5721         "out vec4 my_FragColor;\n"
5722         "struct Data { mediump isampler2D data0[2][2]; mediump isampler2D data1[2][2]; };\n"
5723         "uniform Data test[2];\n"
5724         "void main() {\n"
5725         "    bool passed = true;\n"
5726         "#define DO_CHECK_ikl(i,k,l) \\\n"
5727         "    if (texture(test[i].data0[k][l], vec2(0.0, 0.0)) != ivec4(i, 0, k, l)+1) { \\\n"
5728         "        passed = false; \\\n"
5729         "    } \\\n"
5730         "    if (texture(test[i].data1[k][l], vec2(0.0, 0.0)) != ivec4(i, 1, k, l)+1) { \\\n"
5731         "        passed = false; \\\n"
5732         "    }\n"
5733         "#define DO_CHECK_ik(i,k) \\\n"
5734         "    DO_CHECK_ikl(i, k, 0) \\\n"
5735         "    DO_CHECK_ikl(i, k, 1)\n"
5736         "#define DO_CHECK_i(i) \\\n"
5737         "    DO_CHECK_ik(i, 0) \\\n"
5738         "    DO_CHECK_ik(i, 1)\n"
5739         "    DO_CHECK_i(0)\n"
5740         "    DO_CHECK_i(1)\n"
5741         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
5742         "}\n";
5743 
5744     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5745     glUseProgram(program);
5746     GLTexture textures[2][2][2][2];
5747     for (int i = 0; i < 2; i++)
5748     {
5749         for (int j = 0; j < 2; j++)
5750         {
5751             for (int k = 0; k < 2; k++)
5752             {
5753                 for (int l = 0; l < 2; l++)
5754                 {
5755                     // First generate the texture
5756                     int textureUnit = l + 2 * (k + 2 * (j + 2 * i));
5757                     glActiveTexture(GL_TEXTURE0 + textureUnit);
5758                     glBindTexture(GL_TEXTURE_2D, textures[i][j][k][l]);
5759                     GLint texData[4] = {i + 1, j + 1, k + 1, l + 1};
5760                     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT,
5761                                  &texData[0]);
5762                     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5763                     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5764                     // Then send it as a uniform
5765                     std::stringstream uniformName;
5766                     uniformName << "test[" << i << "].data" << j << "[" << k << "][" << l << "]";
5767                     GLint uniformLocation =
5768                         glGetUniformLocation(program, uniformName.str().c_str());
5769                     // All array indices should be used.
5770                     EXPECT_NE(uniformLocation, -1);
5771                     glUniform1i(uniformLocation, textureUnit);
5772                 }
5773             }
5774         }
5775     }
5776     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
5777     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5778 }
5779 
5780 // Test that a complex chain of structs and arrays of samplers works as expected.
TEST_P(GLSLTest_ES31,ComplexStructArraySampler)5781 TEST_P(GLSLTest_ES31, ComplexStructArraySampler)
5782 {
5783     GLint numTextures;
5784     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
5785     ANGLE_SKIP_TEST_IF(numTextures < 2 * 3 * (2 + 3));
5786     constexpr char kFS[] =
5787         "#version 310 es\n"
5788         "precision mediump float;\n"
5789         "out vec4 my_FragColor;\n"
5790         "struct Data { mediump isampler2D data0[2]; mediump isampler2D data1[3]; };\n"
5791         "uniform Data test[2][3];\n"
5792         "const vec2 ZERO = vec2(0.0, 0.0);\n"
5793         "void main() {\n"
5794         "    bool passed = true;\n"
5795         "#define DO_CHECK_INNER0(i,j,l) \\\n"
5796         "    if (texture(test[i][j].data0[l], ZERO) != ivec4(i, j, 0, l) + 1) { \\\n"
5797         "        passed = false; \\\n"
5798         "    }\n"
5799         "#define DO_CHECK_INNER1(i,j,l) \\\n"
5800         "    if (texture(test[i][j].data1[l], ZERO) != ivec4(i, j, 1, l) + 1) { \\\n"
5801         "        passed = false; \\\n"
5802         "    }\n"
5803         "#define DO_CHECK(i,j) \\\n"
5804         "    DO_CHECK_INNER0(i, j, 0) \\\n"
5805         "    DO_CHECK_INNER0(i, j, 1) \\\n"
5806         "    DO_CHECK_INNER1(i, j, 0) \\\n"
5807         "    DO_CHECK_INNER1(i, j, 1) \\\n"
5808         "    DO_CHECK_INNER1(i, j, 2)\n"
5809         "    DO_CHECK(0, 0)\n"
5810         "    DO_CHECK(0, 1)\n"
5811         "    DO_CHECK(0, 2)\n"
5812         "    DO_CHECK(1, 0)\n"
5813         "    DO_CHECK(1, 1)\n"
5814         "    DO_CHECK(1, 2)\n"
5815         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
5816         "}\n";
5817 
5818     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5819     glUseProgram(program);
5820     struct Data
5821     {
5822         GLTexture data1[2];
5823         GLTexture data2[3];
5824     };
5825     Data textures[2][3];
5826     for (int i = 0; i < 2; i++)
5827     {
5828         for (int j = 0; j < 3; j++)
5829         {
5830             GLTexture *arrays[]     = {&textures[i][j].data1[0], &textures[i][j].data2[0]};
5831             size_t arrayLengths[]   = {2, 3};
5832             size_t arrayOffsets[]   = {0, 2};
5833             size_t totalArrayLength = 5;
5834             for (int k = 0; k < 2; k++)
5835             {
5836                 GLTexture *array   = arrays[k];
5837                 size_t arrayLength = arrayLengths[k];
5838                 size_t arrayOffset = arrayOffsets[k];
5839                 for (int l = 0; l < static_cast<int>(arrayLength); l++)
5840                 {
5841                     // First generate the texture
5842                     int textureUnit = arrayOffset + l + totalArrayLength * (j + 3 * i);
5843                     glActiveTexture(GL_TEXTURE0 + textureUnit);
5844                     glBindTexture(GL_TEXTURE_2D, array[l]);
5845                     GLint texData[4] = {i + 1, j + 1, k + 1, l + 1};
5846                     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT,
5847                                  &texData[0]);
5848                     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5849                     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5850                     // Then send it as a uniform
5851                     std::stringstream uniformName;
5852                     uniformName << "test[" << i << "][" << j << "].data" << k << "[" << l << "]";
5853                     GLint uniformLocation =
5854                         glGetUniformLocation(program, uniformName.str().c_str());
5855                     // All array indices should be used.
5856                     EXPECT_NE(uniformLocation, -1);
5857                     glUniform1i(uniformLocation, textureUnit);
5858                 }
5859             }
5860         }
5861     }
5862     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
5863     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5864 }
5865 
TEST_P(GLSLTest_ES31,ArraysOfArraysStructDifferentTypesSampler)5866 TEST_P(GLSLTest_ES31, ArraysOfArraysStructDifferentTypesSampler)
5867 {
5868     GLint numTextures;
5869     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
5870     ANGLE_SKIP_TEST_IF(numTextures < 3 * (2 + 2));
5871     constexpr char kFS[] =
5872         "#version 310 es\n"
5873         "precision mediump float;\n"
5874         "out vec4 my_FragColor;\n"
5875         "struct Data { mediump isampler2D data0[2]; mediump sampler2D data1[2]; };\n"
5876         "uniform Data test[3];\n"
5877         "ivec4 f2i(vec4 x) { return ivec4(x * 4.0 + 0.5); }"
5878         "void main() {\n"
5879         "    bool passed = true;\n"
5880         "#define DO_CHECK_ik(i,k) \\\n"
5881         "    if (texture(test[i].data0[k], vec2(0.0, 0.0)) != ivec4(i, 0, k, 0)+1) { \\\n"
5882         "        passed = false; \\\n"
5883         "    } \\\n"
5884         "    if (f2i(texture(test[i].data1[k], vec2(0.0, 0.0))) != ivec4(i, 1, k, 0)+1) { \\\n"
5885         "        passed = false; \\\n"
5886         "    }\n"
5887         "#define DO_CHECK_i(i) \\\n"
5888         "    DO_CHECK_ik(i, 0) \\\n"
5889         "    DO_CHECK_ik(i, 1)\n"
5890         "    DO_CHECK_i(0)\n"
5891         "    DO_CHECK_i(1)\n"
5892         "    DO_CHECK_i(2)\n"
5893         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
5894         "}\n";
5895 
5896     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5897     glUseProgram(program);
5898     GLTexture textures[3][2][2];
5899     for (int i = 0; i < 3; i++)
5900     {
5901         for (int j = 0; j < 2; j++)
5902         {
5903             for (int k = 0; k < 2; k++)
5904             {
5905                 // First generate the texture
5906                 int textureUnit = k + 2 * (j + 2 * i);
5907                 glActiveTexture(GL_TEXTURE0 + textureUnit);
5908                 glBindTexture(GL_TEXTURE_2D, textures[i][j][k]);
5909                 GLint texData[4]        = {i + 1, j + 1, k + 1, 1};
5910                 GLubyte texDataFloat[4] = {static_cast<GLubyte>((i + 1) * 64 - 1),
5911                                            static_cast<GLubyte>((j + 1) * 64 - 1),
5912                                            static_cast<GLubyte>((k + 1) * 64 - 1), 64};
5913                 if (j == 0)
5914                 {
5915                     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT,
5916                                  &texData[0]);
5917                 }
5918                 else
5919                 {
5920                     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5921                                  &texDataFloat[0]);
5922                 }
5923                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5924                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5925                 // Then send it as a uniform
5926                 std::stringstream uniformName;
5927                 uniformName << "test[" << i << "].data" << j << "[" << k << "]";
5928                 GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
5929                 // All array indices should be used.
5930                 EXPECT_NE(uniformLocation, -1);
5931                 glUniform1i(uniformLocation, textureUnit);
5932             }
5933         }
5934     }
5935     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
5936     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5937 }
5938 
5939 // Test that arrays of arrays of samplers as parameters works as expected.
TEST_P(GLSLTest_ES31,ParameterArraysOfArraysSampler)5940 TEST_P(GLSLTest_ES31, ParameterArraysOfArraysSampler)
5941 {
5942     // anglebug.com/42262476 - no sampler array params on Android
5943     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
5944 
5945     constexpr char kFS[] =
5946         "#version 310 es\n"
5947         "precision mediump float;\n"
5948         "out vec4 my_FragColor;\n"
5949         "uniform mediump isampler2D test[2][3];\n"
5950         "const vec2 ZERO = vec2(0.0, 0.0);\n"
5951         "\n"
5952         "bool check(mediump isampler2D data[2][3]);\n"
5953         "bool check(mediump isampler2D data[2][3]) {\n"
5954         "#define DO_CHECK(i,j) \\\n"
5955         "    if (texture(data[i][j], ZERO) != ivec4(i+1, j+1, 0, 1)) { \\\n"
5956         "        return false; \\\n"
5957         "    }\n"
5958         "    DO_CHECK(0, 0)\n"
5959         "    DO_CHECK(0, 1)\n"
5960         "    DO_CHECK(0, 2)\n"
5961         "    DO_CHECK(1, 0)\n"
5962         "    DO_CHECK(1, 1)\n"
5963         "    DO_CHECK(1, 2)\n"
5964         "    return true;\n"
5965         "}\n"
5966         "void main() {\n"
5967         "    bool passed = check(test);\n"
5968         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
5969         "}\n";
5970 
5971     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
5972     glUseProgram(program);
5973     GLTexture textures[2][3];
5974     for (int i = 0; i < 2; i++)
5975     {
5976         for (int j = 0; j < 3; j++)
5977         {
5978             // First generate the texture
5979             int textureUnit = i * 3 + j;
5980             glActiveTexture(GL_TEXTURE0 + textureUnit);
5981             glBindTexture(GL_TEXTURE_2D, textures[i][j]);
5982             GLint texData[2] = {i + 1, j + 1};
5983             glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32I, 1, 1, 0, GL_RG_INTEGER, GL_INT, &texData[0]);
5984             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5985             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5986             // Then send it as a uniform
5987             std::stringstream uniformName;
5988             uniformName << "test[" << i << "][" << j << "]";
5989             GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
5990             // All array indices should be used.
5991             EXPECT_NE(uniformLocation, -1);
5992             glUniform1i(uniformLocation, textureUnit);
5993         }
5994     }
5995     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
5996     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5997 }
5998 
5999 // Test that structs with arrays of arrays of samplers as parameters works as expected.
TEST_P(GLSLTest_ES31,ParameterStructArrayArraySampler)6000 TEST_P(GLSLTest_ES31, ParameterStructArrayArraySampler)
6001 {
6002     // anglebug.com/42262476 - no sampler array params on Android
6003     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
6004 
6005     constexpr char kFS[] =
6006         "#version 310 es\n"
6007         "precision mediump float;\n"
6008         "out vec4 my_FragColor;\n"
6009         "struct Data { mediump isampler2D data[2][3]; };\n"
6010         "uniform Data test;\n"
6011         "const vec2 ZERO = vec2(0.0, 0.0);\n"
6012         "\n"
6013         "bool check(Data data) {\n"
6014         "#define DO_CHECK(i,j) \\\n"
6015         "    if (texture(data.data[i][j], ZERO) != ivec4(i+1, j+1, 0, 1)) { \\\n"
6016         "        return false; \\\n"
6017         "    }\n"
6018         "    DO_CHECK(0, 0)\n"
6019         "    DO_CHECK(0, 1)\n"
6020         "    DO_CHECK(0, 2)\n"
6021         "    DO_CHECK(1, 0)\n"
6022         "    DO_CHECK(1, 1)\n"
6023         "    DO_CHECK(1, 2)\n"
6024         "    return true;\n"
6025         "}\n"
6026         "void main() {\n"
6027         "    bool passed = check(test);\n"
6028         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
6029         "}\n";
6030 
6031     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
6032     glUseProgram(program);
6033     GLTexture textures[2][3];
6034     for (int i = 0; i < 2; i++)
6035     {
6036         for (int j = 0; j < 3; j++)
6037         {
6038             // First generate the texture
6039             int textureUnit = i * 3 + j;
6040             glActiveTexture(GL_TEXTURE0 + textureUnit);
6041             glBindTexture(GL_TEXTURE_2D, textures[i][j]);
6042             GLint texData[2] = {i + 1, j + 1};
6043             glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32I, 1, 1, 0, GL_RG_INTEGER, GL_INT, &texData[0]);
6044             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6045             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6046             // Then send it as a uniform
6047             std::stringstream uniformName;
6048             uniformName << "test.data[" << i << "][" << j << "]";
6049             GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
6050             // All array indices should be used.
6051             EXPECT_NE(uniformLocation, -1);
6052             glUniform1i(uniformLocation, textureUnit);
6053         }
6054     }
6055     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
6056     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6057 }
6058 
6059 // Test that arrays of arrays of structs with arrays of arrays of samplers
6060 // as parameters works as expected.
TEST_P(GLSLTest_ES31,ParameterArrayArrayStructArrayArraySampler)6061 TEST_P(GLSLTest_ES31, ParameterArrayArrayStructArrayArraySampler)
6062 {
6063     // anglebug.com/42262476 - no sampler array params on Android
6064     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
6065 
6066     GLint numTextures;
6067     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
6068     ANGLE_SKIP_TEST_IF(numTextures < 3 * 2 * 2 * 2);
6069     constexpr char kFS[] =
6070         "#version 310 es\n"
6071         "precision mediump float;\n"
6072         "out vec4 my_FragColor;\n"
6073         "struct Data { mediump isampler2D data[2][2]; };\n"
6074         "uniform Data test[3][2];\n"
6075         "const vec2 ZERO = vec2(0.0, 0.0);\n"
6076         "\n"
6077         "bool check(Data data[3][2]) {\n"
6078         "#define DO_CHECK_ijkl(i,j,k,l) \\\n"
6079         "    if (texture(data[i][j].data[k][l], ZERO) != ivec4(i, j, k, l) + 1) { \\\n"
6080         "        return false; \\\n"
6081         "    }\n"
6082         "#define DO_CHECK_ij(i,j) \\\n"
6083         "    DO_CHECK_ijkl(i, j, 0, 0) \\\n"
6084         "    DO_CHECK_ijkl(i, j, 0, 1) \\\n"
6085         "    DO_CHECK_ijkl(i, j, 1, 0) \\\n"
6086         "    DO_CHECK_ijkl(i, j, 1, 1)\n"
6087         "    DO_CHECK_ij(0, 0)\n"
6088         "    DO_CHECK_ij(1, 0)\n"
6089         "    DO_CHECK_ij(2, 0)\n"
6090         "    DO_CHECK_ij(0, 1)\n"
6091         "    DO_CHECK_ij(1, 1)\n"
6092         "    DO_CHECK_ij(2, 1)\n"
6093         "    return true;\n"
6094         "}\n"
6095         "void main() {\n"
6096         "    bool passed = check(test);\n"
6097         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
6098         "}\n";
6099 
6100     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
6101     glUseProgram(program);
6102     GLTexture textures[3][2][2][2];
6103     for (int i = 0; i < 3; i++)
6104     {
6105         for (int j = 0; j < 2; j++)
6106         {
6107             for (int k = 0; k < 2; k++)
6108             {
6109                 for (int l = 0; l < 2; l++)
6110                 {
6111                     // First generate the texture
6112                     int textureUnit = l + 2 * (k + 2 * (j + 2 * i));
6113                     glActiveTexture(GL_TEXTURE0 + textureUnit);
6114                     glBindTexture(GL_TEXTURE_2D, textures[i][j][k][l]);
6115                     GLint texData[4] = {i + 1, j + 1, k + 1, l + 1};
6116                     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 1, 0, GL_RGBA_INTEGER, GL_INT,
6117                                  &texData[0]);
6118                     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6119                     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6120                     // Then send it as a uniform
6121                     std::stringstream uniformName;
6122                     uniformName << "test[" << i << "][" << j << "].data[" << k << "][" << l << "]";
6123                     GLint uniformLocation =
6124                         glGetUniformLocation(program, uniformName.str().c_str());
6125                     // All array indices should be used.
6126                     EXPECT_NE(uniformLocation, -1);
6127                     glUniform1i(uniformLocation, textureUnit);
6128                 }
6129             }
6130         }
6131     }
6132     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
6133     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6134 }
6135 
6136 // Test that 3D arrays with sub-arrays passed as parameters works as expected.
TEST_P(GLSLTest_ES31,ParameterArrayArrayArraySampler)6137 TEST_P(GLSLTest_ES31, ParameterArrayArrayArraySampler)
6138 {
6139     GLint numTextures;
6140     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
6141     ANGLE_SKIP_TEST_IF(numTextures < 2 * 3 * 4 + 4);
6142 
6143     // anglebug.com/42262476 - no sampler array params on Android
6144     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
6145 
6146     // http://anglebug.com/42264082
6147     ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
6148 
6149     constexpr char kFS[] =
6150         "#version 310 es\n"
6151         "precision mediump float;\n"
6152         "out vec4 my_FragColor;\n"
6153         "uniform mediump isampler2D test[2][3][4];\n"
6154         "uniform mediump isampler2D test2[4];\n"
6155         "const vec2 ZERO = vec2(0.0, 0.0);\n"
6156         "\n"
6157         "bool check1D(mediump isampler2D arr[4], int x, int y) {\n"
6158         "    if (texture(arr[0], ZERO) != ivec4(x, y, 0, 0)+1) return false;\n"
6159         "    if (texture(arr[1], ZERO) != ivec4(x, y, 1, 0)+1) return false;\n"
6160         "    if (texture(arr[2], ZERO) != ivec4(x, y, 2, 0)+1) return false;\n"
6161         "    if (texture(arr[3], ZERO) != ivec4(x, y, 3, 0)+1) return false;\n"
6162         "    return true;\n"
6163         "}\n"
6164         "bool check2D(mediump isampler2D arr[3][4], int x) {\n"
6165         "    if (!check1D(arr[0], x, 0)) return false;\n"
6166         "    if (!check1D(arr[1], x, 1)) return false;\n"
6167         "    if (!check1D(arr[2], x, 2)) return false;\n"
6168         "    return true;\n"
6169         "}\n"
6170         "bool check3D(mediump isampler2D arr[2][3][4]) {\n"
6171         "    if (!check2D(arr[0], 0)) return false;\n"
6172         "    if (!check2D(arr[1], 1)) return false;\n"
6173         "    return true;\n"
6174         "}\n"
6175         "void main() {\n"
6176         "    bool passed = check3D(test) && check1D(test2, 7, 8);\n"
6177         "    my_FragColor = passed ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);\n"
6178         "}\n";
6179 
6180     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
6181     glUseProgram(program);
6182     GLTexture textures1[2][3][4];
6183     GLTexture textures2[4];
6184     for (int i = 0; i < 2; i++)
6185     {
6186         for (int j = 0; j < 3; j++)
6187         {
6188             for (int k = 0; k < 4; k++)
6189             {
6190                 // First generate the texture
6191                 int textureUnit = k + 4 * (j + 3 * i);
6192                 glActiveTexture(GL_TEXTURE0 + textureUnit);
6193                 glBindTexture(GL_TEXTURE_2D, textures1[i][j][k]);
6194                 GLint texData[3] = {i + 1, j + 1, k + 1};
6195                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32I, 1, 1, 0, GL_RGB_INTEGER, GL_INT,
6196                              &texData[0]);
6197                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6198                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6199                 // Then send it as a uniform
6200                 std::stringstream uniformName;
6201                 uniformName << "test[" << i << "][" << j << "][" << k << "]";
6202                 GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
6203                 // All array indices should be used.
6204                 EXPECT_NE(uniformLocation, -1);
6205                 glUniform1i(uniformLocation, textureUnit);
6206             }
6207         }
6208     }
6209     for (int k = 0; k < 4; k++)
6210     {
6211         // First generate the texture
6212         int textureUnit = 2 * 3 * 4 + k;
6213         glActiveTexture(GL_TEXTURE0 + textureUnit);
6214         glBindTexture(GL_TEXTURE_2D, textures2[k]);
6215         GLint texData[3] = {7 + 1, 8 + 1, k + 1};
6216         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32I, 1, 1, 0, GL_RGB_INTEGER, GL_INT, &texData[0]);
6217         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6218         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6219         // Then send it as a uniform
6220         std::stringstream uniformName;
6221         uniformName << "test2[" << k << "]";
6222         GLint uniformLocation = glGetUniformLocation(program, uniformName.str().c_str());
6223         // All array indices should be used.
6224         EXPECT_NE(uniformLocation, -1);
6225         glUniform1i(uniformLocation, textureUnit);
6226     }
6227     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
6228     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6229 }
6230 
6231 // Test that names do not collide when translating arrays of arrays of samplers.
TEST_P(GLSLTest_ES31,ArraysOfArraysNameCollisionSampler)6232 TEST_P(GLSLTest_ES31, ArraysOfArraysNameCollisionSampler)
6233 {
6234     ANGLE_SKIP_TEST_IF(IsVulkan());  // anglebug.com/42262269 - rewriter can create name collisions
6235     GLint numTextures;
6236     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numTextures);
6237     ANGLE_SKIP_TEST_IF(numTextures < 2 * 2 + 3 * 3 + 4 * 4);
6238     // anglebug.com/42262476 - no sampler array params on Android
6239     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
6240     constexpr char kFS[] =
6241         "#version 310 es\n"
6242         "precision mediump sampler2D;\n"
6243         "precision mediump float;\n"
6244         "uniform sampler2D test_field1_field2[2][2];\n"
6245         "struct S1 { sampler2D field2[3][3]; }; uniform S1 test_field1;\n"
6246         "struct S2 { sampler2D field1_field2[4][4]; }; uniform S2 test;\n"
6247         "vec4 func1(sampler2D param_field1_field2[2][2],\n"
6248         "           int param_field1_field2_offset,\n"
6249         "           S1 param_field1,\n"
6250         "           S2 param) {\n"
6251         "    return vec4(0.0, 1.0, 0.0, 0.0);\n"
6252         "}\n"
6253         "out vec4 my_FragColor;\n"
6254         "void main() {\n"
6255         "    my_FragColor = vec4(0.0, 0.0, 0.0, 1.0);\n"
6256         "    my_FragColor += func1(test_field1_field2, 0, test_field1, test);\n"
6257         "    vec2 uv = vec2(0.0);\n"
6258         "    my_FragColor += texture(test_field1_field2[0][0], uv) +\n"
6259         "                    texture(test_field1.field2[0][0], uv) +\n"
6260         "                    texture(test.field1_field2[0][0], uv);\n"
6261         "}\n";
6262     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
6263     glActiveTexture(GL_TEXTURE0);
6264     GLTexture tex;
6265     glBindTexture(GL_TEXTURE_2D, tex);
6266     GLint zero = 0;
6267     glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 1, 1, 0, GL_RED, GL_UNSIGNED_BYTE, &zero);
6268     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
6269     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6270 }
6271 
6272 // Test that regular arrays are unmodified.
TEST_P(GLSLTest_ES31,BasicTypeArrayAndArrayOfSampler)6273 TEST_P(GLSLTest_ES31, BasicTypeArrayAndArrayOfSampler)
6274 {
6275     constexpr char kFS[] =
6276         "#version 310 es\n"
6277         "precision mediump sampler2D;\n"
6278         "precision mediump float;\n"
6279         "uniform sampler2D sampler_array[2][2];\n"
6280         "uniform int array[3][2];\n"
6281         "vec4 func1(int param[2],\n"
6282         "           int param2[3]) {\n"
6283         "    return vec4(0.0, 1.0, 0.0, 0.0);\n"
6284         "}\n"
6285         "out vec4 my_FragColor;\n"
6286         "void main() {\n"
6287         "    my_FragColor = texture(sampler_array[0][0], vec2(0.0));\n"
6288         "    my_FragColor += func1(array[1], int[](1, 2, 3));\n"
6289         "}\n";
6290     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
6291     glActiveTexture(GL_TEXTURE0);
6292     GLTexture tex;
6293     glBindTexture(GL_TEXTURE_2D, tex);
6294     GLint zero = 0;
6295     glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 1, 1, 0, GL_RED, GL_UNSIGNED_BYTE, &zero);
6296     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
6297     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6298 }
6299 
6300 // This test covers a bug (and associated workaround) with nested sampling operations in the HLSL
6301 // compiler DLL.
TEST_P(GLSLTest_ES3,NestedSamplingOperation)6302 TEST_P(GLSLTest_ES3, NestedSamplingOperation)
6303 {
6304     // This seems to be bugged on some version of Android. Might not affect the newest versions.
6305     // TODO(jmadill): Lift suppression when Chromium bots are upgraded.
6306     // Test skipped on Android because of bug with Nexus 5X.
6307     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
6308 
6309     constexpr char kVS[] =
6310         "#version 300 es\n"
6311         "out vec2 texCoord;\n"
6312         "in vec2 position;\n"
6313         "void main()\n"
6314         "{\n"
6315         "    gl_Position = vec4(position, 0, 1);\n"
6316         "    texCoord = position * 0.5 + vec2(0.5);\n"
6317         "}\n";
6318 
6319     constexpr char kSimpleFS[] =
6320         "#version 300 es\n"
6321         "in mediump vec2 texCoord;\n"
6322         "out mediump vec4 fragColor;\n"
6323         "void main()\n"
6324         "{\n"
6325         "    fragColor = vec4(texCoord, 0, 1);\n"
6326         "}\n";
6327 
6328     constexpr char kNestedFS[] =
6329         "#version 300 es\n"
6330         "uniform mediump sampler2D samplerA;\n"
6331         "uniform mediump sampler2D samplerB;\n"
6332         "in mediump vec2 texCoord;\n"
6333         "out mediump vec4 fragColor;\n"
6334         "void main ()\n"
6335         "{\n"
6336         "    fragColor = texture(samplerB, texture(samplerA, texCoord).xy);\n"
6337         "}\n";
6338 
6339     ANGLE_GL_PROGRAM(initProg, kVS, kSimpleFS);
6340     ANGLE_GL_PROGRAM(nestedProg, kVS, kNestedFS);
6341 
6342     // Initialize a first texture with default texCoord data.
6343     GLTexture texA;
6344     glActiveTexture(GL_TEXTURE0);
6345     glBindTexture(GL_TEXTURE_2D, texA);
6346     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
6347                  GL_UNSIGNED_BYTE, nullptr);
6348     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6349     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6350 
6351     GLFramebuffer fbo;
6352     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6353     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texA, 0);
6354 
6355     drawQuad(initProg, "position", 0.5f);
6356     ASSERT_GL_NO_ERROR();
6357 
6358     // Initialize a second texture with a simple color pattern.
6359     GLTexture texB;
6360     glActiveTexture(GL_TEXTURE1);
6361     glBindTexture(GL_TEXTURE_2D, texB);
6362 
6363     std::array<GLColor, 4> simpleColors = {
6364         {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
6365     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6366                  simpleColors.data());
6367     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6368     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6369 
6370     // Draw with the nested program, using the first texture to index the second.
6371     glBindFramebuffer(GL_FRAMEBUFFER, 0);
6372     glUseProgram(nestedProg);
6373     GLint samplerALoc = glGetUniformLocation(nestedProg, "samplerA");
6374     ASSERT_NE(-1, samplerALoc);
6375     glUniform1i(samplerALoc, 0);
6376     GLint samplerBLoc = glGetUniformLocation(nestedProg, "samplerB");
6377     ASSERT_NE(-1, samplerBLoc);
6378     glUniform1i(samplerBLoc, 1);
6379 
6380     drawQuad(nestedProg, "position", 0.5f);
6381     ASSERT_GL_NO_ERROR();
6382 
6383     // Compute four texel centers.
6384     Vector2 windowSize(getWindowWidth(), getWindowHeight());
6385     Vector2 quarterWindowSize = windowSize / 4;
6386     Vector2 ul                = quarterWindowSize;
6387     Vector2 ur(windowSize.x() - quarterWindowSize.x(), quarterWindowSize.y());
6388     Vector2 ll(quarterWindowSize.x(), windowSize.y() - quarterWindowSize.y());
6389     Vector2 lr = windowSize - quarterWindowSize;
6390 
6391     EXPECT_PIXEL_COLOR_EQ_VEC2(ul, simpleColors[0]);
6392     EXPECT_PIXEL_COLOR_EQ_VEC2(ur, simpleColors[1]);
6393     EXPECT_PIXEL_COLOR_EQ_VEC2(ll, simpleColors[2]);
6394     EXPECT_PIXEL_COLOR_EQ_VEC2(lr, simpleColors[3]);
6395 }
6396 
6397 // Tests that using a constant declaration as the only statement in a for loop without curly braces
6398 // doesn't crash.
TEST_P(GLSLTest,ConstantStatementInForLoop)6399 TEST_P(GLSLTest, ConstantStatementInForLoop)
6400 {
6401     constexpr char kVS[] =
6402         "void main()\n"
6403         "{\n"
6404         "    for (int i = 0; i < 10; ++i)\n"
6405         "        const int b = 0;\n"
6406         "}\n";
6407 
6408     GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
6409     EXPECT_NE(0u, shader);
6410     glDeleteShader(shader);
6411 }
6412 
6413 // Tests that using a constant declaration as a loop init expression doesn't crash. Note that this
6414 // test doesn't work on D3D9 due to looping limitations, so it is only run on ES3.
TEST_P(GLSLTest_ES3,ConstantStatementAsLoopInit)6415 TEST_P(GLSLTest_ES3, ConstantStatementAsLoopInit)
6416 {
6417     constexpr char kVS[] =
6418         "void main()\n"
6419         "{\n"
6420         "    for (const int i = 0; i < 0;) {}\n"
6421         "}\n";
6422 
6423     GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
6424     EXPECT_NE(0u, shader);
6425     glDeleteShader(shader);
6426 }
6427 
6428 // Tests that using a constant condition guarding a discard works
6429 // Covers a failing case in the Vulkan backend: http://anglebug.com/42265506
TEST_P(GLSLTest_ES3,ConstantConditionGuardingDiscard)6430 TEST_P(GLSLTest_ES3, ConstantConditionGuardingDiscard)
6431 {
6432     constexpr char kFS[] = R"(#version 300 es
6433 void main()
6434 {
6435     if (true)
6436     {
6437         discard;
6438     }
6439 })";
6440 
6441     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
6442     EXPECT_NE(0u, shader);
6443     glDeleteShader(shader);
6444 }
6445 
6446 // Tests that nesting a discard in unconditional blocks works
6447 // Covers a failing case in the Vulkan backend: http://anglebug.com/42265506
TEST_P(GLSLTest_ES3,NestedUnconditionalDiscards)6448 TEST_P(GLSLTest_ES3, NestedUnconditionalDiscards)
6449 {
6450     constexpr char kFS[] = R"(#version 300 es
6451 out mediump vec4 c;
6452 void main()
6453 {
6454     {
6455         c = vec4(0);
6456         {
6457             discard;
6458         }
6459     }
6460 })";
6461 
6462     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
6463     EXPECT_NE(0u, shader);
6464     glDeleteShader(shader);
6465 }
6466 
6467 // Test that uninitialized local variables are initialized to 0.
TEST_P(WebGL2GLSLTest,InitUninitializedLocals)6468 TEST_P(WebGL2GLSLTest, InitUninitializedLocals)
6469 {
6470     // Test skipped on Android GLES because local variable initialization is disabled.
6471     // http://anglebug.com/40096454
6472     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
6473 
6474     constexpr char kFS[] =
6475         "#version 300 es\n"
6476         "precision mediump float;\n"
6477         "out vec4 my_FragColor;\n"
6478         "int result = 0;\n"
6479         "void main()\n"
6480         "{\n"
6481         "    int u;\n"
6482         "    result += u;\n"
6483         "    int k = 0;\n"
6484         "    for (int i[2], j = i[0] + 1; k < 2; ++k)\n"
6485         "    {\n"
6486         "        result += j;\n"
6487         "    }\n"
6488         "    if (result == 2)\n"
6489         "    {\n"
6490         "        my_FragColor = vec4(0, 1, 0, 1);\n"
6491         "    }\n"
6492         "    else\n"
6493         "    {\n"
6494         "        my_FragColor = vec4(1, 0, 0, 1);\n"
6495         "    }\n"
6496         "}\n";
6497 
6498     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6499 
6500     // [WebGL 1.0]
6501     // DrawArrays or drawElements will generate an INVALID_OPERATION error
6502     // if a vertex attribute is enabled as an array via enableVertexAttribArray
6503     // but no buffer is bound to that attribute.
6504     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6505     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6506 }
6507 
6508 // Test that uninitialized structs containing arrays of structs are initialized to 0. This
6509 // specifically tests with two different struct variables declared in the same block.
TEST_P(WebGL2GLSLTest,InitUninitializedStructContainingArrays)6510 TEST_P(WebGL2GLSLTest, InitUninitializedStructContainingArrays)
6511 {
6512     // Test skipped on Android GLES because local variable initialization is disabled.
6513     // http://anglebug.com/40096454
6514     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
6515 
6516     constexpr char kFS[] =
6517         "precision mediump float;\n"
6518         "struct T\n"
6519         "{\n"
6520         "    int a[2];\n"
6521         "};\n"
6522         "struct S\n"
6523         "{\n"
6524         "    T t[2];\n"
6525         "};\n"
6526         "void main()\n"
6527         "{\n"
6528         "    S s;\n"
6529         "    S s2;\n"
6530         "    if (s.t[1].a[1] == 0 && s2.t[1].a[1] == 0)\n"
6531         "    {\n"
6532         "        gl_FragColor = vec4(0, 1, 0, 1);\n"
6533         "    }\n"
6534         "    else\n"
6535         "    {\n"
6536         "        gl_FragColor = vec4(1, 0, 0, 1);\n"
6537         "    }\n"
6538         "}\n";
6539 
6540     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
6541     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6542     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6543 }
6544 
6545 // Verify that two shaders with the same uniform name and members but different structure names will
6546 // not link.
TEST_P(GLSLTest,StructureNameMatchingTest)6547 TEST_P(GLSLTest, StructureNameMatchingTest)
6548 {
6549     const char *vsSource =
6550         "// Structures must have the same name, sequence of type names, and\n"
6551         "// type definitions, and field names to be considered the same type.\n"
6552         "// GLSL 1.017 4.2.4\n"
6553         "precision mediump float;\n"
6554         "struct info {\n"
6555         "  vec4 pos;\n"
6556         "  vec4 color;\n"
6557         "};\n"
6558         "\n"
6559         "uniform info uni;\n"
6560         "void main()\n"
6561         "{\n"
6562         "    gl_Position = uni.pos;\n"
6563         "}\n";
6564 
6565     GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
6566     ASSERT_NE(0u, vs);
6567     glDeleteShader(vs);
6568 
6569     const char *fsSource =
6570         "// Structures must have the same name, sequence of type names, and\n"
6571         "// type definitions, and field names to be considered the same type.\n"
6572         "// GLSL 1.017 4.2.4\n"
6573         "precision mediump float;\n"
6574         "struct info1 {\n"
6575         "  vec4 pos;\n"
6576         "  vec4 color;\n"
6577         "};\n"
6578         "\n"
6579         "uniform info1 uni;\n"
6580         "void main()\n"
6581         "{\n"
6582         "    gl_FragColor = uni.color;\n"
6583         "}\n";
6584 
6585     GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
6586     ASSERT_NE(0u, fs);
6587     glDeleteShader(fs);
6588 
6589     GLuint program = CompileProgram(vsSource, fsSource);
6590     EXPECT_EQ(0u, program);
6591 }
6592 
6593 // Test that an uninitialized nameless struct inside a for loop init statement works.
TEST_P(WebGL2GLSLTest,UninitializedNamelessStructInForInitStatement)6594 TEST_P(WebGL2GLSLTest, UninitializedNamelessStructInForInitStatement)
6595 {
6596     // Test skipped on Android GLES because local variable initialization is disabled.
6597     // http://anglebug.com/40096454
6598     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
6599 
6600     constexpr char kFS[] =
6601         "#version 300 es\n"
6602         "precision highp float;\n"
6603         "out vec4 my_FragColor;\n"
6604         "void main()\n"
6605         "{\n"
6606         "    my_FragColor = vec4(1, 0, 0, 1);\n"
6607         "    for (struct { float q; } b; b.q < 2.0; b.q++) {\n"
6608         "        my_FragColor = vec4(0, 1, 0, 1);\n"
6609         "    }\n"
6610         "}\n";
6611 
6612     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6613     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6614     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6615 }
6616 
6617 // Test that uninitialized global variables are initialized to 0.
TEST_P(WebGLGLSLTest,InitUninitializedGlobals)6618 TEST_P(WebGLGLSLTest, InitUninitializedGlobals)
6619 {
6620     // http://anglebug.com/42261561
6621     ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
6622 
6623     constexpr char kFS[] =
6624         "precision mediump float;\n"
6625         "int result;\n"
6626         "int i[2], j = i[0] + 1;\n"
6627         "void main()\n"
6628         "{\n"
6629         "    result += j;\n"
6630         "    if (result == 1)\n"
6631         "    {\n"
6632         "        gl_FragColor = vec4(0, 1, 0, 1);\n"
6633         "    }\n"
6634         "    else\n"
6635         "    {\n"
6636         "        gl_FragColor = vec4(1, 0, 0, 1);\n"
6637         "    }\n"
6638         "}\n";
6639 
6640     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
6641     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6642     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6643 }
6644 
6645 // Test that an uninitialized nameless struct in the global scope works.
TEST_P(WebGLGLSLTest,UninitializedNamelessStructInGlobalScope)6646 TEST_P(WebGLGLSLTest, UninitializedNamelessStructInGlobalScope)
6647 {
6648     constexpr char kFS[] =
6649         "precision mediump float;\n"
6650         "struct { float q; } b;\n"
6651         "void main()\n"
6652         "{\n"
6653         "    gl_FragColor = vec4(1, 0, 0, 1);\n"
6654         "    if (b.q == 0.0)\n"
6655         "    {\n"
6656         "        gl_FragColor = vec4(0, 1, 0, 1);\n"
6657         "    }\n"
6658         "}\n";
6659 
6660     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
6661     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6662     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6663 }
6664 
6665 // Test that uninitialized output arguments are initialized to 0.
TEST_P(WebGL2GLSLTest,InitOutputParams)6666 TEST_P(WebGL2GLSLTest, InitOutputParams)
6667 {
6668     constexpr char kFS[] = R"(#version 300 es
6669 precision mediump float;
6670 
6671 struct S { float a; };
6672 
6673 out vec4 color;
6674 
6675 float f(out float, out vec2 o1, out S o2[2], out float o3[3])
6676 {
6677     float uninitialized_local;
6678 
6679     // leave o1 uninitialized
6680     // leave o2 partially uninitialized
6681     o2[0].a = 1.0;
6682 
6683     // leave o3 partially uninitialized
6684     o3[1] = 0.5;
6685 
6686     return uninitialized_local;
6687 }
6688 
6689 void main()
6690 {
6691     float v0 = 345.;
6692     vec2 v1 = vec2(123., 234.);
6693     S v2[2] = S[2](S(-1111.), S(55.));
6694     float v3[3] = float[3](20., 30., 40.);
6695     float v4 = f(v0, v1, v2, v3);
6696 
6697     // Everything should be 0 now except for v2[0].a and v3[1] which should be 1.0 and 0.5
6698     // respectively.
6699     color = vec4(v0 + v1.x + v2[0].a + v3[0],  // 1.0
6700                  v1.y + v2[1].a + v3[1],  // 0.5
6701                  v3[2] + v4,              // 0
6702                  1.0);
6703 })";
6704 
6705     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6706     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6707     EXPECT_PIXEL_NEAR(0, 0, 255, 127, 0, 255, 1);
6708 }
6709 
6710 // Tests nameless struct uniforms.
TEST_P(GLSLTest,EmbeddedStructUniform)6711 TEST_P(GLSLTest, EmbeddedStructUniform)
6712 {
6713     const char kFragmentShader[] = R"(precision mediump float;
6714 uniform struct { float q; } b;
6715 void main()
6716 {
6717     gl_FragColor = vec4(1, 0, 0, 1);
6718     if (b.q == 0.5)
6719     {
6720         gl_FragColor = vec4(0, 1, 0, 1);
6721     }
6722 })";
6723 
6724     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
6725     glUseProgram(program);
6726     GLint uniLoc = glGetUniformLocation(program, "b.q");
6727     ASSERT_NE(-1, uniLoc);
6728     glUniform1f(uniLoc, 0.5f);
6729 
6730     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6731     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6732 }
6733 
6734 // Tests nameless struct uniform arrays.
TEST_P(GLSLTest,EmbeddedStructUniformArray)6735 TEST_P(GLSLTest, EmbeddedStructUniformArray)
6736 {
6737     const char kFragmentShader[] = R"(precision mediump float;
6738 uniform struct { float q; } b[2];
6739 void main()
6740 {
6741     gl_FragColor = vec4(1, 0, 0, 1);
6742     if (b[0].q == 0.5)
6743     {
6744         gl_FragColor = vec4(0, 1, 0, 1);
6745     }
6746 })";
6747 
6748     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
6749     glUseProgram(program);
6750     GLint uniLoc = glGetUniformLocation(program, "b[0].q");
6751     ASSERT_NE(-1, uniLoc);
6752     glUniform1f(uniLoc, 0.5f);
6753 
6754     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6755     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6756 }
6757 
6758 // Test that samplers in structs can be extracted if the first reference to the struct does not
6759 // select an attribute.
TEST_P(GLSLTest,SamplerInStructNoMemberIndexing)6760 TEST_P(GLSLTest, SamplerInStructNoMemberIndexing)
6761 {
6762     constexpr char kVS[] = R"(
6763 uniform struct {
6764     sampler2D n;
6765     vec2 c;
6766 } s;
6767 void main()
6768 {
6769     s;
6770 })";
6771 
6772     constexpr char kFS[] = R"(void main()
6773 {
6774     gl_FragColor = vec4(1);
6775 })";
6776 
6777     ANGLE_GL_PROGRAM(program, kVS, kFS);
6778 }
6779 
6780 // Similar test to SamplerInStructNoMemberIndexing, but the struct variable is an array.
TEST_P(GLSLTest,SamplerInStructArrayNoMemberIndexing)6781 TEST_P(GLSLTest, SamplerInStructArrayNoMemberIndexing)
6782 {
6783     constexpr char kVS[] = R"(
6784 uniform struct
6785 {
6786     sampler2D K;
6787     vec4 c;
6788 } s[6];
6789 void main()
6790 {
6791     s[0];
6792 })";
6793 
6794     constexpr char kFS[] = R"(void main()
6795 {
6796     gl_FragColor = vec4(1);
6797 })";
6798 
6799     ANGLE_GL_PROGRAM(program, kVS, kFS);
6800 }
6801 
6802 // Tests that rewriting samplers in structs doesn't mess up indexing.
TEST_P(GLSLTest,SamplerInStructMemberIndexing)6803 TEST_P(GLSLTest, SamplerInStructMemberIndexing)
6804 {
6805     const char kVertexShader[] = R"(attribute vec2 position;
6806 varying vec2 texCoord;
6807 void main()
6808 {
6809     gl_Position = vec4(position, 0, 1);
6810     texCoord = position * 0.5 + vec2(0.5);
6811 })";
6812 
6813     const char kFragmentShader[] = R"(precision mediump float;
6814 struct S { sampler2D samp; bool b; };
6815 uniform S uni;
6816 varying vec2 texCoord;
6817 void main()
6818 {
6819     uni;
6820     if (uni.b)
6821     {
6822         gl_FragColor = texture2D(uni.samp, texCoord);
6823     }
6824     else
6825     {
6826         gl_FragColor = vec4(1, 0, 0, 1);
6827     }
6828 })";
6829 
6830     ANGLE_GL_PROGRAM(program, kVertexShader, kFragmentShader);
6831     glUseProgram(program);
6832 
6833     GLint bLoc = glGetUniformLocation(program, "uni.b");
6834     ASSERT_NE(-1, bLoc);
6835     GLint sampLoc = glGetUniformLocation(program, "uni.samp");
6836     ASSERT_NE(-1, sampLoc);
6837 
6838     glUniform1i(bLoc, 1);
6839 
6840     std::array<GLColor, 4> kGreenPixels = {
6841         {GLColor::green, GLColor::green, GLColor::green, GLColor::green}};
6842 
6843     GLTexture tex;
6844     glBindTexture(GL_TEXTURE_2D, tex);
6845     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6846                  kGreenPixels.data());
6847     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6848     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6849     ASSERT_GL_NO_ERROR();
6850 
6851     drawQuad(program, "position", 0.5f);
6852     ASSERT_GL_NO_ERROR();
6853 
6854     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6855 }
6856 
6857 // Tests that rewriting samplers in structs works when passed as function argument.  In this test,
6858 // the function references another struct, which is not being modified.  Regression test for AST
6859 // validation applied to a multipass transformation, where references to declarations were attempted
6860 // to be validated without having the entire shader.  In this case, the reference to S2 was flagged
6861 // as invalid because S2's declaration was not visible.
TEST_P(GLSLTest,SamplerInStructAsFunctionArg)6862 TEST_P(GLSLTest, SamplerInStructAsFunctionArg)
6863 {
6864     const char kFS[] = R"(precision mediump float;
6865 struct S { sampler2D samp; bool b; };
6866 struct S2 { float f; };
6867 
6868 uniform S us;
6869 
6870 float f(S s)
6871 {
6872     S2 s2;
6873     s2.f = float(s.b);
6874     return s2.f;
6875 }
6876 
6877 void main()
6878 {
6879     gl_FragColor = vec4(f(us), 0, 0, 1);
6880 })";
6881 
6882     GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
6883     EXPECT_NE(fs, 0u);
6884     ASSERT_GL_NO_ERROR();
6885 }
6886 
6887 // Test that structs with samplers are not allowed in interface blocks.  This is forbidden per
6888 // GLES3:
6889 //
6890 // > Types and declarators are the same as for other uniform variable declarations outside blocks,
6891 // > with these exceptions:
6892 // > * opaque types are not allowed
TEST_P(GLSLTest_ES3,StructWithSamplersDisallowedInInterfaceBlock)6893 TEST_P(GLSLTest_ES3, StructWithSamplersDisallowedInInterfaceBlock)
6894 {
6895     const char kFS[] = R"(#version 300 es
6896 precision mediump float;
6897 struct S { sampler2D samp; bool b; };
6898 
6899 layout(std140) uniform Buffer { S s; } buffer;
6900 
6901 out vec4 color;
6902 
6903 void main()
6904 {
6905     color = texture(buffer.s.samp, vec2(0));
6906 })";
6907 
6908     GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
6909     EXPECT_EQ(fs, 0u);
6910     ASSERT_GL_NO_ERROR();
6911 }
6912 
6913 // Tests two nameless struct uniforms.
TEST_P(GLSLTest,TwoEmbeddedStructUniforms)6914 TEST_P(GLSLTest, TwoEmbeddedStructUniforms)
6915 {
6916     const char kFragmentShader[] = R"(precision mediump float;
6917 uniform struct { float q; } b, c;
6918 void main()
6919 {
6920     gl_FragColor = vec4(1, 0, 0, 1);
6921     if (b.q == 0.5 && c.q == 1.0)
6922     {
6923         gl_FragColor = vec4(0, 1, 0, 1);
6924     }
6925 })";
6926 
6927     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
6928     glUseProgram(program);
6929 
6930     GLint uniLocB = glGetUniformLocation(program, "b.q");
6931     ASSERT_NE(-1, uniLocB);
6932     glUniform1f(uniLocB, 0.5f);
6933 
6934     GLint uniLocC = glGetUniformLocation(program, "c.q");
6935     ASSERT_NE(-1, uniLocC);
6936     glUniform1f(uniLocC, 1.0f);
6937 
6938     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6939     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6940 }
6941 
6942 // Test that a loop condition that has an initializer declares a variable.
TEST_P(GLSLTest_ES3,ConditionInitializerDeclaresVariable)6943 TEST_P(GLSLTest_ES3, ConditionInitializerDeclaresVariable)
6944 {
6945     constexpr char kFS[] =
6946         "#version 300 es\n"
6947         "precision highp float;\n"
6948         "out vec4 my_FragColor;\n"
6949         "void main()\n"
6950         "{\n"
6951         "    float i = 0.0;\n"
6952         "    while (bool foo = (i < 1.5))\n"
6953         "    {\n"
6954         "        if (!foo)\n"
6955         "        {\n"
6956         "            ++i;\n"
6957         "        }\n"
6958         "        if (i > 3.5)\n"
6959         "        {\n"
6960         "            break;\n"
6961         "        }\n"
6962         "        ++i;\n"
6963         "    }\n"
6964         "    my_FragColor = vec4(i * 0.5 - 1.0, i * 0.5, 0.0, 1.0);\n"
6965         "}\n";
6966 
6967     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6968     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
6969     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6970 }
6971 
6972 // Test that a variable hides a user-defined function with the same name after its initializer.
6973 // GLSL ES 1.00.17 section 4.2.2: "A variable declaration is visible immediately following the
6974 // initializer if present, otherwise immediately following the identifier"
TEST_P(GLSLTest,VariableHidesUserDefinedFunctionAfterInitializer)6975 TEST_P(GLSLTest, VariableHidesUserDefinedFunctionAfterInitializer)
6976 {
6977     constexpr char kFS[] =
6978         "precision mediump float;\n"
6979         "uniform vec4 u;\n"
6980         "vec4 foo()\n"
6981         "{\n"
6982         "    return u;\n"
6983         "}\n"
6984         "void main()\n"
6985         "{\n"
6986         "    vec4 foo = foo();\n"
6987         "    gl_FragColor = foo + vec4(0, 1, 0, 1);\n"
6988         "}\n";
6989 
6990     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
6991     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
6992     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6993 }
6994 
6995 // Test that structs with identical members are not ambiguous as function arguments.
TEST_P(GLSLTest,StructsWithSameMembersDisambiguatedByName)6996 TEST_P(GLSLTest, StructsWithSameMembersDisambiguatedByName)
6997 {
6998     constexpr char kFS[] =
6999         "precision mediump float;\n"
7000         "uniform float u_zero;\n"
7001         "struct S { float foo; };\n"
7002         "struct S2 { float foo; };\n"
7003         "float get(S s) { return s.foo + u_zero; }\n"
7004         "float get(S2 s2) { return 0.25 + s2.foo + u_zero; }\n"
7005         "void main()\n"
7006         "{\n"
7007         "    S s;\n"
7008         "    s.foo = 0.5;\n"
7009         "    S2 s2;\n"
7010         "    s2.foo = 0.25;\n"
7011         "    gl_FragColor = vec4(0.0, get(s) + get(s2), 0.0, 1.0);\n"
7012         "}\n";
7013 
7014     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
7015     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
7016     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7017 }
7018 
7019 // Test that an inactive varying in vertex shader but used in fragment shader can be linked
7020 // successfully.
TEST_P(GLSLTest,InactiveVaryingInVertexActiveInFragment)7021 TEST_P(GLSLTest, InactiveVaryingInVertexActiveInFragment)
7022 {
7023     // http://anglebug.com/42263408
7024     ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
7025 
7026     constexpr char kVS[] =
7027         "attribute vec4 inputAttribute;\n"
7028         "varying vec4 varColor;\n"
7029         "void main()\n"
7030         "{\n"
7031         "    gl_Position = inputAttribute;\n"
7032         "}\n";
7033 
7034     constexpr char kFS[] =
7035         "precision mediump float;\n"
7036         "varying vec4 varColor;\n"
7037         "void main()\n"
7038         "{\n"
7039         "    gl_FragColor = varColor;\n"
7040         "}\n";
7041 
7042     ANGLE_GL_PROGRAM(program, kVS, kFS);
7043     drawQuad(program, "inputAttribute", 0.5f);
7044     ASSERT_GL_NO_ERROR();
7045 }
7046 
7047 // Test that a varying struct that's not statically used in the fragment shader works.
7048 // GLSL ES 3.00.6 section 4.3.10.
TEST_P(GLSLTest_ES3,VaryingStructNotStaticallyUsedInFragmentShader)7049 TEST_P(GLSLTest_ES3, VaryingStructNotStaticallyUsedInFragmentShader)
7050 {
7051     constexpr char kVS[] =
7052         "#version 300 es\n"
7053         "struct S {\n"
7054         "    vec4 field;\n"
7055         "};\n"
7056         "out S varStruct;\n"
7057         "void main()\n"
7058         "{\n"
7059         "    gl_Position = vec4(1.0);\n"
7060         "    varStruct.field = vec4(0.0, 0.5, 0.0, 0.0);\n"
7061         "}\n";
7062 
7063     constexpr char kFS[] =
7064         "#version 300 es\n"
7065         "precision mediump float;\n"
7066         "struct S {\n"
7067         "    vec4 field;\n"
7068         "};\n"
7069         "in S varStruct;\n"
7070         "out vec4 col;\n"
7071         "void main()\n"
7072         "{\n"
7073         "    col = vec4(1.0);\n"
7074         "}\n";
7075 
7076     ANGLE_GL_PROGRAM(program, kVS, kFS);
7077 }
7078 
7079 // Test that inactive shader IO block varying are ok.
TEST_P(GLSLTest_ES31,InactiveVaryingIOBlock)7080 TEST_P(GLSLTest_ES31, InactiveVaryingIOBlock)
7081 {
7082     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
7083 
7084     constexpr char kVS[] =
7085         R"(#version 310 es
7086         #extension GL_EXT_shader_io_blocks : require
7087 
7088         precision highp float;
7089         in vec4 inputAttribute;
7090         out Block { vec4 v; };
7091         out Inactive1 { vec4 value; };
7092         out Inactive2 { vec4 value; } named;
7093 
7094         void main()
7095         {
7096             gl_Position    = inputAttribute;
7097             v = vec4(0);
7098         })";
7099 
7100     constexpr char kFS[] =
7101         R"(#version 310 es
7102         #extension GL_EXT_shader_io_blocks : require
7103 
7104         precision highp float;
7105 
7106         in Block { vec4 v; };
7107         in Inactive3 { vec4 value; };
7108         in Inactive4 { vec4 value; } named2;
7109 
7110         layout(location = 0) out mediump vec4 color;
7111         void main()
7112         {
7113             color = vec4(1, v.xy, 1);
7114         })";
7115 
7116     ANGLE_GL_PROGRAM(program, kVS, kFS);
7117     drawQuad(program, "inputAttribute", 0.5f);
7118     ASSERT_GL_NO_ERROR();
7119 
7120     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7121 }
7122 
7123 // Test that a shader IO block varying that's not declared in the fragment shader links
7124 // successfully.
TEST_P(GLSLTest_ES31,VaryingIOBlockNotDeclaredInFragmentShader)7125 TEST_P(GLSLTest_ES31, VaryingIOBlockNotDeclaredInFragmentShader)
7126 {
7127     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
7128 
7129     constexpr char kVS[] =
7130         R"(#version 310 es
7131         #extension GL_EXT_shader_io_blocks : require
7132 
7133         precision highp float;
7134         in vec4 inputAttribute;
7135         out Block_inout { vec4 value; } user_out;
7136 
7137         void main()
7138         {
7139             gl_Position    = inputAttribute;
7140             user_out.value = vec4(4.0, 5.0, 6.0, 7.0);
7141         })";
7142 
7143     constexpr char kFS[] =
7144         R"(#version 310 es
7145         #extension GL_EXT_shader_io_blocks : require
7146 
7147         precision highp float;
7148         layout(location = 0) out mediump vec4 color;
7149         void main()
7150         {
7151             color = vec4(1, 0, 0, 1);
7152         })";
7153 
7154     ANGLE_GL_PROGRAM(program, kVS, kFS);
7155     drawQuad(program, "inputAttribute", 0.5f);
7156     ASSERT_GL_NO_ERROR();
7157 
7158     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7159 }
7160 
7161 // Test that a shader IO block varying that's not declared in the vertex shader links
7162 // successfully.
TEST_P(GLSLTest_ES31,VaryingIOBlockNotDeclaredInVertexShader)7163 TEST_P(GLSLTest_ES31, VaryingIOBlockNotDeclaredInVertexShader)
7164 {
7165     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
7166 
7167     constexpr char kVS[] =
7168         R"(#version 310 es
7169         #extension GL_EXT_shader_io_blocks : require
7170 
7171         precision highp float;
7172         in vec4 inputAttribute;
7173 
7174         void main()
7175         {
7176             gl_Position = inputAttribute;
7177         })";
7178 
7179     constexpr char kFS[] =
7180         R"(#version 310 es
7181         #extension GL_EXT_shader_io_blocks : require
7182 
7183         precision highp float;
7184         in Block_inout { vec4 value; } user_in;
7185         layout(location = 0) out mediump vec4 color;
7186 
7187         void main()
7188         {
7189             color = vec4(1, 0, 0, 1);
7190         })";
7191 
7192     ANGLE_GL_PROGRAM(program, kVS, kFS);
7193     drawQuad(program, "inputAttribute", 0.5f);
7194     ASSERT_GL_NO_ERROR();
7195 
7196     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7197 }
7198 
7199 // Test that a shader with sample in / sample out can be linked successfully.
TEST_P(GLSLTest_ES31,VaryingTessellationSampleInAndOut)7200 TEST_P(GLSLTest_ES31, VaryingTessellationSampleInAndOut)
7201 {
7202     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
7203     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_multisample_interpolation"));
7204 
7205     constexpr char kVS[] =
7206         R"(#version 310 es
7207         #extension GL_OES_shader_multisample_interpolation : require
7208 
7209         precision highp float;
7210         in vec4 inputAttribute;
7211 
7212         sample out mediump float tc_in;
7213         void main()
7214         {
7215             tc_in = inputAttribute[0];
7216             gl_Position = inputAttribute;
7217         })";
7218 
7219     constexpr char kTCS[] =
7220         R"(#version 310 es
7221         #extension GL_EXT_tessellation_shader : require
7222         #extension GL_OES_shader_multisample_interpolation : require
7223         layout (vertices=3) out;
7224 
7225         sample in mediump float tc_in[];
7226         sample out mediump float tc_out[];
7227         void main()
7228         {
7229             tc_out[gl_InvocationID] = tc_in[gl_InvocationID];
7230             gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
7231             gl_TessLevelInner[0] = 2.0;
7232             gl_TessLevelInner[1] = 2.0;
7233             gl_TessLevelOuter[0] = 2.0;
7234             gl_TessLevelOuter[1] = 2.0;
7235             gl_TessLevelOuter[2] = 2.0;
7236             gl_TessLevelOuter[3] = 2.0;
7237         })";
7238 
7239     constexpr char kTES[] =
7240         R"(#version 310 es
7241         #extension GL_EXT_tessellation_shader : require
7242         #extension GL_OES_shader_multisample_interpolation : require
7243         layout (triangles) in;
7244 
7245         sample in mediump float tc_out[];
7246         sample out mediump float te_out;
7247         void main()
7248         {
7249             te_out = tc_out[2];
7250             gl_Position = gl_TessCoord[0] * gl_in[0].gl_Position;
7251         })";
7252 
7253     constexpr char kFS[] =
7254         R"(#version 310 es
7255         #extension GL_OES_shader_multisample_interpolation : require
7256 
7257         precision highp float;
7258         sample in mediump float te_out;
7259         layout(location = 0) out mediump vec4 color;
7260 
7261         void main()
7262         {
7263             float out0 = te_out;
7264             color = vec4(1, 0, 0, 1);
7265         })";
7266 
7267     ANGLE_GL_PROGRAM_WITH_TESS(program, kVS, kTCS, kTES, kFS);
7268     drawPatches(program, "inputAttribute", 0.5f, 1.0f, GL_FALSE);
7269     ASSERT_GL_NO_ERROR();
7270 }
7271 
7272 // Test that `smooth sample` and `flat sample` pass the validation.
TEST_P(GLSLTest_ES3,AliasedSampleQualifiers)7273 TEST_P(GLSLTest_ES3, AliasedSampleQualifiers)
7274 {
7275     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_multisample_interpolation"));
7276 
7277     constexpr char kVS[] =
7278         R"(#version 300 es
7279         #extension GL_OES_shader_multisample_interpolation : require
7280 
7281         smooth sample out mediump float f;
7282         flat sample out mediump int i;
7283         void main()
7284         {
7285             f = 1.0;
7286             i = 1;
7287             gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
7288         })";
7289 
7290     constexpr char kFS[] =
7291         R"(#version 300 es
7292         #extension GL_OES_shader_multisample_interpolation : require
7293 
7294         smooth sample in mediump float f;
7295         flat sample in mediump int i;
7296         out mediump vec4 color;
7297         void main()
7298         {
7299             color = vec4(f, float(i), 0, 1);
7300         })";
7301 
7302     ANGLE_GL_PROGRAM(program, kVS, kFS);
7303 }
7304 
7305 // Test that `noperspective centroid` passes the validation and compiles.
TEST_P(GLSLTest_ES3,NoPerspectiveCentroid)7306 TEST_P(GLSLTest_ES3, NoPerspectiveCentroid)
7307 {
7308     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_shader_noperspective_interpolation"));
7309 
7310     constexpr char kVS[] =
7311         R"(#version 300 es
7312         #extension GL_NV_shader_noperspective_interpolation : require
7313 
7314         noperspective centroid out mediump float f;
7315         void main()
7316         {
7317             f = 1.0;
7318             gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
7319         })";
7320 
7321     constexpr char kFS[] =
7322         R"(#version 300 es
7323         #extension GL_NV_shader_noperspective_interpolation : require
7324 
7325         noperspective centroid in mediump float f;
7326         out mediump vec4 color;
7327         void main()
7328         {
7329             color = vec4(f, 0.0, 0.0, 1.0);
7330         })";
7331 
7332     ANGLE_GL_PROGRAM(program, kVS, kFS);
7333 }
7334 
7335 // Test that `noperspective sample` passes the validation and compiles.
TEST_P(GLSLTest_ES3,NoPerspectiveSample)7336 TEST_P(GLSLTest_ES3, NoPerspectiveSample)
7337 {
7338     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_multisample_interpolation"));
7339     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_shader_noperspective_interpolation"));
7340 
7341     constexpr char kVS[] =
7342         R"(#version 300 es
7343         #extension GL_OES_shader_multisample_interpolation : require
7344         #extension GL_NV_shader_noperspective_interpolation : require
7345 
7346         noperspective sample out mediump float f;
7347         void main()
7348         {
7349             f = 1.0;
7350             gl_Position = vec4(f, 0.0, 0.0, 1.0);
7351         })";
7352 
7353     constexpr char kFS[] =
7354         R"(#version 300 es
7355         #extension GL_OES_shader_multisample_interpolation : require
7356         #extension GL_NV_shader_noperspective_interpolation : require
7357 
7358         noperspective sample in mediump float f;
7359         out mediump vec4 color;
7360         void main()
7361         {
7362             color = vec4(f, 0.0, 0.0, 1.0);
7363         })";
7364 
7365     ANGLE_GL_PROGRAM(program, kVS, kFS);
7366 }
7367 
7368 // Test that a shader with sample in / sample out can be used successfully when the varying
7369 // precision is different between VS and FS.
TEST_P(GLSLTest_ES31,VaryingSampleInAndOutDifferentPrecision)7370 TEST_P(GLSLTest_ES31, VaryingSampleInAndOutDifferentPrecision)
7371 {
7372     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_shader_multisample_interpolation"));
7373 
7374     constexpr char kVS[] =
7375         R"(#version 310 es
7376         #extension GL_OES_shader_multisample_interpolation : require
7377 
7378         precision highp float;
7379         in vec4 inputAttribute;
7380 
7381         sample out highp float v;
7382         void main()
7383         {
7384             v = inputAttribute[0];
7385             gl_Position = inputAttribute;
7386         })";
7387 
7388     constexpr char kFS[] =
7389         R"(#version 310 es
7390         #extension GL_OES_shader_multisample_interpolation : require
7391 
7392         precision highp float;
7393         sample in mediump float v;
7394         layout(location = 0) out mediump vec4 color;
7395 
7396         void main()
7397         {
7398             color = vec4(round((v + 1.) / 2. * 5.) / 5., 0, 0, 1);
7399         })";
7400 
7401     ANGLE_GL_PROGRAM(program, kVS, kFS);
7402     drawQuad(program, "inputAttribute", 0.5f, 1.0f, GL_FALSE);
7403     ASSERT_GL_NO_ERROR();
7404 
7405     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, 0, GLColor::red);
7406 }
7407 
7408 // Test that a shader IO block varying whose block name is declared multiple(in/out) time links
7409 // successfully.
TEST_P(GLSLTest_ES31,VaryingIOBlockDeclaredAsInAndOut)7410 TEST_P(GLSLTest_ES31, VaryingIOBlockDeclaredAsInAndOut)
7411 {
7412     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
7413     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
7414 
7415     constexpr char kVS[] = R"(#version 310 es
7416     #extension GL_EXT_shader_io_blocks : require
7417     precision highp float;
7418     in vec4 inputAttribute;
7419     out Vertex
7420     {
7421         vec4 fv;
7422     } outVertex;
7423     void main()
7424     {
7425         gl_Position = inputAttribute;
7426         outVertex.fv = gl_Position;
7427     })";
7428 
7429     constexpr char kTCS[] = R"(#version 310 es
7430     #extension GL_EXT_tessellation_shader : require
7431     #extension GL_EXT_shader_io_blocks : require
7432     precision mediump float;
7433     in Vertex
7434     {
7435         vec4 fv;
7436     } inVertex[];
7437     layout(vertices = 2) out;
7438     out Vertex
7439     {
7440         vec4 fv;
7441     } outVertex[];
7442 
7443     void main()
7444     {
7445         gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
7446         outVertex[gl_InvocationID].fv = inVertex[gl_InvocationID].fv;
7447         gl_TessLevelInner[0] = 1.0;
7448             gl_TessLevelInner[1] = 1.0;
7449             gl_TessLevelOuter[0] = 1.0;
7450             gl_TessLevelOuter[1] = 1.0;
7451             gl_TessLevelOuter[2] = 1.0;
7452             gl_TessLevelOuter[3] = 1.0;
7453     })";
7454 
7455     constexpr char kTES[] = R"(#version 310 es
7456     #extension GL_EXT_tessellation_shader : require
7457     #extension GL_EXT_shader_io_blocks : require
7458     precision mediump float;
7459     layout (isolines, point_mode) in;
7460     in Vertex
7461     {
7462         vec4 fv;
7463     } inVertex[];
7464     out vec4 result_fv;
7465 
7466     void main()
7467     {
7468         gl_Position = gl_in[0].gl_Position;
7469         result_fv = inVertex[0].fv;
7470     })";
7471 
7472     constexpr char kFS[] = R"(#version 310 es
7473     precision mediump float;
7474 
7475     layout(location = 0) out mediump vec4 color;
7476 
7477     void main()
7478     {
7479         // Output solid green
7480         color = vec4(0, 1.0, 0, 1.0);
7481     })";
7482 
7483     ANGLE_GL_PROGRAM_WITH_TESS(program, kVS, kTCS, kTES, kFS);
7484     drawPatches(program, "inputAttribute", 0.5f, 1.0f, GL_FALSE);
7485     ASSERT_GL_NO_ERROR();
7486 }
7487 
testTessellationTextureBufferAccess(const APIExtensionVersion usedExtension)7488 void GLSLTest_ES31::testTessellationTextureBufferAccess(const APIExtensionVersion usedExtension)
7489 {
7490     ASSERT(usedExtension == APIExtensionVersion::EXT || usedExtension == APIExtensionVersion::OES);
7491 
7492     // Vertex shader
7493     constexpr char kVS[] = R"(#version 310 es
7494 precision highp float;
7495 in vec4 inputAttribute;
7496 
7497 void main()
7498 {
7499 gl_Position = inputAttribute;
7500 })";
7501 
7502     // Tessellation shaders
7503     constexpr char kGLSLVersion[] = R"(#version 310 es
7504 )";
7505     constexpr char kTessEXT[]     = R"(#extension GL_EXT_tessellation_shader : require
7506 )";
7507     constexpr char kTessOES[]     = R"(#extension GL_OES_tessellation_shader : require
7508 )";
7509     constexpr char kTexBufEXT[]   = R"(#extension GL_EXT_texture_buffer : require
7510 )";
7511     constexpr char kTexBufOES[]   = R"(#extension GL_OES_texture_buffer : require
7512 )";
7513 
7514     std::string tcs;
7515     std::string tes;
7516 
7517     tcs.append(kGLSLVersion);
7518     tes.append(kGLSLVersion);
7519 
7520     if (usedExtension == APIExtensionVersion::EXT)
7521     {
7522         tcs.append(kTessEXT);
7523         tes.append(kTessEXT);
7524         tes.append(kTexBufEXT);
7525     }
7526     else
7527     {
7528         tcs.append(kTessOES);
7529         tes.append(kTessOES);
7530         tes.append(kTexBufOES);
7531     }
7532 
7533     constexpr char kTCSBody[] = R"(precision mediump float;
7534 layout(vertices = 2) out;
7535 
7536 void main()
7537 {
7538 gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
7539 gl_TessLevelInner[0] = 1.0;
7540 gl_TessLevelInner[1] = 1.0;
7541 gl_TessLevelOuter[0] = 1.0;
7542 gl_TessLevelOuter[1] = 1.0;
7543 gl_TessLevelOuter[2] = 1.0;
7544 gl_TessLevelOuter[3] = 1.0;
7545 })";
7546     tcs.append(kTCSBody);
7547 
7548     constexpr char kTESBody[] = R"(precision mediump float;
7549 layout (isolines, point_mode) in;
7550 
7551 uniform highp samplerBuffer tex;
7552 
7553 out vec4 tex_color;
7554 
7555 void main()
7556 {
7557 tex_color = texelFetch(tex, 0);
7558 gl_Position = gl_in[0].gl_Position;
7559 })";
7560     tes.append(kTESBody);
7561 
7562     // Fragment shader
7563     constexpr char kFS[] = R"(#version 310 es
7564 precision mediump float;
7565 layout(location = 0) out mediump vec4 color;
7566 
7567 in vec4 tex_color;
7568 
7569 void main()
7570 {
7571 color = tex_color;
7572 })";
7573 
7574     constexpr GLint kBufferSize = 4;
7575     GLubyte texData[]           = {0u, 255u, 0u, 255u};
7576 
7577     GLTexture texture;
7578     glBindTexture(GL_TEXTURE_BUFFER, texture);
7579 
7580     GLBuffer buffer;
7581     glBindBuffer(GL_TEXTURE_BUFFER, buffer);
7582     glBufferData(GL_TEXTURE_BUFFER, kBufferSize, texData, GL_STATIC_DRAW);
7583     glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGBA8, buffer);
7584     ASSERT_GL_NO_ERROR();
7585 
7586     glClearColor(1.0, 0, 0, 1.0);
7587     glClear(GL_COLOR_BUFFER_BIT);
7588 
7589     ANGLE_GL_PROGRAM_WITH_TESS(program, kVS, tcs.c_str(), tes.c_str(), kFS);
7590     drawPatches(program, "inputAttribute", 0.5f, 1.0f, GL_FALSE);
7591     ASSERT_GL_NO_ERROR();
7592 }
7593 
7594 // Test that texture buffers can be accessed in a tessellation stage (using EXT)
TEST_P(GLSLTest_ES31,TessellationTextureBufferAccessEXT)7595 TEST_P(GLSLTest_ES31, TessellationTextureBufferAccessEXT)
7596 {
7597     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
7598     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_buffer"));
7599     testTessellationTextureBufferAccess(APIExtensionVersion::EXT);
7600 }
7601 
7602 // Test that texture buffers can be accessed in a tessellation stage (using OES)
TEST_P(GLSLTest_ES31,TessellationTextureBufferAccessOES)7603 TEST_P(GLSLTest_ES31, TessellationTextureBufferAccessOES)
7604 {
7605     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_tessellation_shader"));
7606     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_buffer"));
7607     testTessellationTextureBufferAccess(APIExtensionVersion::OES);
7608 }
7609 
7610 // Test that a varying struct that's not declared in the fragment shader links successfully.
7611 // GLSL ES 3.00.6 section 4.3.10.
TEST_P(GLSLTest_ES3,VaryingStructNotDeclaredInFragmentShader)7612 TEST_P(GLSLTest_ES3, VaryingStructNotDeclaredInFragmentShader)
7613 {
7614     constexpr char kVS[] =
7615         "#version 300 es\n"
7616         "struct S {\n"
7617         "    vec4 field;\n"
7618         "};\n"
7619         "out S varStruct;\n"
7620         "void main()\n"
7621         "{\n"
7622         "    gl_Position = vec4(1.0);\n"
7623         "    varStruct.field = vec4(0.0, 0.5, 0.0, 0.0);\n"
7624         "}\n";
7625 
7626     constexpr char kFS[] =
7627         "#version 300 es\n"
7628         "precision mediump float;\n"
7629         "out vec4 col;\n"
7630         "void main()\n"
7631         "{\n"
7632         "    col = vec4(1.0);\n"
7633         "}\n";
7634 
7635     ANGLE_GL_PROGRAM(program, kVS, kFS);
7636 }
7637 
7638 // Test that a varying struct that's not declared in the vertex shader, and is unused in the
7639 // fragment shader links successfully.
TEST_P(GLSLTest_ES3,VaryingStructNotDeclaredInVertexShader)7640 TEST_P(GLSLTest_ES3, VaryingStructNotDeclaredInVertexShader)
7641 {
7642     // GLSL ES allows the vertex shader to not declare a varying if the fragment shader is not
7643     // going to use it.  See section 9.1 in
7644     // https://www.khronos.org/registry/OpenGL/specs/es/3.2/GLSL_ES_Specification_3.20.pdf or
7645     // section 4.3.5 in https://www.khronos.org/files/opengles_shading_language.pdf
7646     //
7647     // However, nvidia OpenGL ES drivers fail to link this program.
7648     //
7649     // http://anglebug.com/42262078
7650     ANGLE_SKIP_TEST_IF(IsOpenGLES() && IsNVIDIA());
7651 
7652     constexpr char kVS[] =
7653         "#version 300 es\n"
7654         "void main()\n"
7655         "{\n"
7656         "    gl_Position = vec4(1.0);\n"
7657         "}\n";
7658 
7659     constexpr char kFS[] =
7660         "#version 300 es\n"
7661         "precision mediump float;\n"
7662         "out vec4 col;\n"
7663         "struct S {\n"
7664         "    vec4 field;\n"
7665         "};\n"
7666         "in S varStruct;\n"
7667         "void main()\n"
7668         "{\n"
7669         "    col = vec4(1.0);\n"
7670         "}\n";
7671 
7672     ANGLE_GL_PROGRAM(program, kVS, kFS);
7673 }
7674 
7675 // Test that a varying struct that's not initialized in the vertex shader links successfully.
TEST_P(WebGL2GLSLTest,VaryingStructNotInitializedInVertexShader)7676 TEST_P(WebGL2GLSLTest, VaryingStructNotInitializedInVertexShader)
7677 {
7678     // GLSL ES allows the vertex shader to declare but not initialize a varying (with a
7679     // specification that the varying values are undefined in the fragment stage).  See section 9.1
7680     // in https://www.khronos.org/registry/OpenGL/specs/es/3.2/GLSL_ES_Specification_3.20.pdf
7681     // or section 4.3.5 in https://www.khronos.org/files/opengles_shading_language.pdf
7682     //
7683     // However, windows and mac OpenGL drivers fail to link this program.  With a message like:
7684     //
7685     // > Input of fragment shader 'varStruct' not written by vertex shader
7686     //
7687     // http://anglebug.com/42262078
7688     ANGLE_SKIP_TEST_IF(IsDesktopOpenGL() && (IsMac() || (IsWindows() && !IsNVIDIA())));
7689 
7690     constexpr char kVS[] =
7691         "#version 300 es\n"
7692         "struct S {\n"
7693         "    vec4 field;\n"
7694         "};\n"
7695         "out S varStruct;\n"
7696         "void main()\n"
7697         "{\n"
7698         "    gl_Position = vec4(1.0);\n"
7699         "}\n";
7700 
7701     constexpr char kFS[] =
7702         "#version 300 es\n"
7703         "precision mediump float;\n"
7704         "out vec4 col;\n"
7705         "struct S {\n"
7706         "    vec4 field;\n"
7707         "};\n"
7708         "in S varStruct;\n"
7709         "void main()\n"
7710         "{\n"
7711         "    col = varStruct.field;\n"
7712         "}\n";
7713 
7714     ANGLE_GL_PROGRAM(program, kVS, kFS);
7715 }
7716 
7717 // Test that a varying struct that gets used in the fragment shader works.
TEST_P(GLSLTest_ES3,VaryingStructUsedInFragmentShader)7718 TEST_P(GLSLTest_ES3, VaryingStructUsedInFragmentShader)
7719 {
7720     constexpr char kVS[] =
7721         "#version 300 es\n"
7722         "in vec4 inputAttribute;\n"
7723         "struct S {\n"
7724         "    vec4 field;\n"
7725         "};\n"
7726         "out S varStruct;\n"
7727         "out S varStruct2;\n"
7728         "void main()\n"
7729         "{\n"
7730         "    gl_Position = inputAttribute;\n"
7731         "    varStruct.field = vec4(0.0, 0.5, 0.0, 1.0);\n"
7732         "    varStruct2.field = vec4(0.0, 0.5, 0.0, 1.0);\n"
7733         "}\n";
7734 
7735     constexpr char kFS[] =
7736         "#version 300 es\n"
7737         "precision mediump float;\n"
7738         "out vec4 col;\n"
7739         "struct S {\n"
7740         "    vec4 field;\n"
7741         "};\n"
7742         "in S varStruct;\n"
7743         "in S varStruct2;\n"
7744         "void main()\n"
7745         "{\n"
7746         "    col = varStruct.field + varStruct2.field;\n"
7747         "}\n";
7748 
7749     ANGLE_GL_PROGRAM(program, kVS, kFS);
7750     drawQuad(program, "inputAttribute", 0.5f);
7751     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7752 }
7753 
7754 // This is a regression test to make sure a red quad is rendered without issues
7755 // when a passthrough function with a vec3 input parameter is used in the fragment shader.
TEST_P(GLSLTest_ES31,SamplerPassthroughFailedLink)7756 TEST_P(GLSLTest_ES31, SamplerPassthroughFailedLink)
7757 {
7758     constexpr char kVS[] =
7759         "precision mediump float;\n"
7760         "attribute vec4 inputAttribute;\n"
7761         "varying mediump vec2 texCoord;\n"
7762         "void main() {\n"
7763         "    texCoord = inputAttribute.xy;\n"
7764         "    gl_Position = vec4(inputAttribute.x, inputAttribute.y, 0.0, 1.0);\n"
7765         "}\n";
7766 
7767     constexpr char kFS[] =
7768         "precision mediump float;\n"
7769         "varying mediump vec2 texCoord;\n"
7770         "uniform sampler2D testSampler;\n"
7771         "vec3 passthrough(vec3 c) {\n"
7772         "    return c;\n"
7773         "}\n"
7774         "void main() {\n"
7775         "    gl_FragColor = vec4(passthrough(texture2D(testSampler, texCoord).rgb), 1.0);\n"
7776         "}\n";
7777     ANGLE_GL_PROGRAM(program, kVS, kFS);
7778 
7779     // Initialize basic red texture.
7780     GLTexture texture;
7781     glBindTexture(GL_TEXTURE_2D, texture);
7782     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
7783                  GLColor::red.data());
7784     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7785     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7786     ASSERT_GL_NO_ERROR();
7787 
7788     drawQuad(program, "inputAttribute", 0.5f);
7789     ASSERT_GL_NO_ERROR();
7790     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7791 }
7792 
7793 // This is a regression test to make sure a red quad is rendered without issues
7794 // when a passthrough function with a vec4 input parameter is used in the fragment shader.
TEST_P(GLSLTest_ES31,SamplerPassthroughIncorrectColor)7795 TEST_P(GLSLTest_ES31, SamplerPassthroughIncorrectColor)
7796 {
7797     constexpr char kVS[] =
7798         "precision mediump float;\n"
7799         "attribute vec4 inputAttribute;\n"
7800         "varying mediump vec2 texCoord;\n"
7801         "void main() {\n"
7802         "    texCoord = inputAttribute.xy;\n"
7803         "    gl_Position = vec4(inputAttribute.x, inputAttribute.y, 0.0, 1.0);\n"
7804         "}\n";
7805 
7806     constexpr char kFS[] =
7807         "precision mediump float;\n"
7808         "varying mediump vec2 texCoord;\n"
7809         "uniform sampler2D testSampler;\n"
7810         "vec4 passthrough(vec4 c) {\n"
7811         "    return c;\n"
7812         "}\n"
7813         "void main() {\n"
7814         "    gl_FragColor = vec4(passthrough(texture2D(testSampler, texCoord)));\n"
7815         "}\n";
7816     ANGLE_GL_PROGRAM(program, kVS, kFS);
7817 
7818     // Initialize basic red texture.
7819     GLTexture texture;
7820     glBindTexture(GL_TEXTURE_2D, texture);
7821     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
7822                  GLColor::red.data());
7823     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7824     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7825     ASSERT_GL_NO_ERROR();
7826 
7827     drawQuad(program, "inputAttribute", 0.5f);
7828     ASSERT_GL_NO_ERROR();
7829     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7830 }
7831 
7832 // Test that multiple multi-field varying structs that get used in the fragment shader work.
TEST_P(GLSLTest_ES3,ComplexVaryingStructsUsedInFragmentShader)7833 TEST_P(GLSLTest_ES3, ComplexVaryingStructsUsedInFragmentShader)
7834 {
7835     // TODO(syoussefi): fails on android with:
7836     //
7837     // > Internal Vulkan error: A return array was too small for the result
7838     //
7839     // http://anglebug.com/42261898
7840     ANGLE_SKIP_TEST_IF(IsVulkan() && IsAndroid());
7841 
7842     constexpr char kVS[] =
7843         "#version 300 es\n"
7844         "in vec4 inputAttribute;\n"
7845         "struct S {\n"
7846         "    vec4 field1;\n"
7847         "    vec4 field2;\n"
7848         "};\n"
7849         "out S varStruct;\n"
7850         "out S varStruct2;\n"
7851         "void main()\n"
7852         "{\n"
7853         "    gl_Position = inputAttribute;\n"
7854         "    varStruct.field1 = vec4(0.0, 0.5, 0.0, 1.0);\n"
7855         "    varStruct.field2 = vec4(0.0, 0.5, 0.0, 1.0);\n"
7856         "    varStruct2.field1 = vec4(0.0, 0.5, 0.0, 1.0);\n"
7857         "    varStruct2.field2 = vec4(0.0, 0.5, 0.0, 1.0);\n"
7858         "}\n";
7859 
7860     constexpr char kFS[] =
7861         "#version 300 es\n"
7862         "precision mediump float;\n"
7863         "out vec4 col;\n"
7864         "struct S {\n"
7865         "    vec4 field1;\n"
7866         "    vec4 field2;\n"
7867         "};\n"
7868         "in S varStruct;\n"
7869         "in S varStruct2;\n"
7870         "void main()\n"
7871         "{\n"
7872         "    col = varStruct.field1 + varStruct2.field2;\n"
7873         "}\n";
7874 
7875     ANGLE_GL_PROGRAM(program, kVS, kFS);
7876     drawQuad(program, "inputAttribute", 0.5f);
7877     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7878 }
7879 
7880 // Test that an inactive varying array that doesn't get used in the fragment shader works.
TEST_P(GLSLTest_ES3,InactiveVaryingArrayUnusedInFragmentShader)7881 TEST_P(GLSLTest_ES3, InactiveVaryingArrayUnusedInFragmentShader)
7882 {
7883     constexpr char kVS[] =
7884         "#version 300 es\n"
7885         "in vec4 inputAttribute;\n"
7886         "out vec4 varArray[4];\n"
7887         "void main()\n"
7888         "{\n"
7889         "    gl_Position = inputAttribute;\n"
7890         "    varArray[0] = vec4(1.0, 0.0, 0.0, 1.0);\n"
7891         "    varArray[1] = vec4(0.0, 1.0, 0.0, 1.0);\n"
7892         "    varArray[2] = vec4(0.0, 0.0, 1.0, 1.0);\n"
7893         "    varArray[3] = vec4(1.0, 1.0, 0.0, 1.0);\n"
7894         "}\n";
7895 
7896     constexpr char kFS[] =
7897         "#version 300 es\n"
7898         "precision mediump float;\n"
7899         "out vec4 col;\n"
7900         "void main()\n"
7901         "{\n"
7902         "    col = vec4(0.0, 0.0, 0.0, 1.0);\n"
7903         "}\n";
7904 
7905     ANGLE_GL_PROGRAM(program, kVS, kFS);
7906     drawQuad(program, "inputAttribute", 0.5f);
7907     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
7908 }
7909 
7910 // Test that an inactive varying struct that doesn't get used in the fragment shader works.
TEST_P(GLSLTest_ES3,InactiveVaryingStructUnusedInFragmentShader)7911 TEST_P(GLSLTest_ES3, InactiveVaryingStructUnusedInFragmentShader)
7912 {
7913     constexpr char kVS[] =
7914         "#version 300 es\n"
7915         "in vec4 inputAttribute;\n"
7916         "struct S {\n"
7917         "    vec4 field;\n"
7918         "};\n"
7919         "out S varStruct;\n"
7920         "out S varStruct2;\n"
7921         "void main()\n"
7922         "{\n"
7923         "    gl_Position = inputAttribute;\n"
7924         "    varStruct.field = vec4(0.0, 1.0, 0.0, 1.0);\n"
7925         "    varStruct2.field = vec4(0.0, 1.0, 0.0, 1.0);\n"
7926         "}\n";
7927 
7928     constexpr char kFS[] =
7929         "#version 300 es\n"
7930         "precision mediump float;\n"
7931         "out vec4 col;\n"
7932         "struct S {\n"
7933         "    vec4 field;\n"
7934         "};\n"
7935         "in S varStruct;\n"
7936         "in S varStruct2;\n"
7937         "void main()\n"
7938         "{\n"
7939         "    col = varStruct.field;\n"
7940         "}\n";
7941 
7942     ANGLE_GL_PROGRAM(program, kVS, kFS);
7943     drawQuad(program, "inputAttribute", 0.5f);
7944     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7945 }
7946 
7947 // Test that multiple varying matrices that get used in the fragment shader work.
TEST_P(GLSLTest_ES3,VaryingMatrices)7948 TEST_P(GLSLTest_ES3, VaryingMatrices)
7949 {
7950     constexpr char kVS[] =
7951         "#version 300 es\n"
7952         "in vec4 inputAttribute;\n"
7953         "out mat2x2 varMat;\n"
7954         "out mat2x2 varMat2;\n"
7955         "out mat4x3 varMat3;\n"
7956         "void main()\n"
7957         "{\n"
7958         "    gl_Position = inputAttribute;\n"
7959         "    varMat[0] = vec2(1, 1);\n"
7960         "    varMat[1] = vec2(1, 1);\n"
7961         "    varMat2[0] = vec2(0.5, 0.5);\n"
7962         "    varMat2[1] = vec2(0.5, 0.5);\n"
7963         "    varMat3[0] = vec3(0.75, 0.75, 0.75);\n"
7964         "    varMat3[1] = vec3(0.75, 0.75, 0.75);\n"
7965         "    varMat3[2] = vec3(0.75, 0.75, 0.75);\n"
7966         "    varMat3[3] = vec3(0.75, 0.75, 0.75);\n"
7967         "}\n";
7968 
7969     constexpr char kFS[] =
7970         "#version 300 es\n"
7971         "precision mediump float;\n"
7972         "out vec4 col;\n"
7973         "in mat2x2 varMat;\n"
7974         "in mat2x2 varMat2;\n"
7975         "in mat4x3 varMat3;\n"
7976         "void main()\n"
7977         "{\n"
7978         "    col = vec4(varMat[0].x, varMat2[1].y, varMat3[2].z, 1);\n"
7979         "}\n";
7980 
7981     ANGLE_GL_PROGRAM(program, kVS, kFS);
7982     drawQuad(program, "inputAttribute", 0.5f);
7983     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 127, 191, 255), 1);
7984 }
7985 
7986 // This test covers passing a struct containing a sampler as a function argument.
TEST_P(GLSLTest,StructsWithSamplersAsFunctionArg)7987 TEST_P(GLSLTest, StructsWithSamplersAsFunctionArg)
7988 {
7989     // Shader failed to compile on Nexus devices. http://anglebug.com/42260860
7990     ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
7991 
7992     const char kFragmentShader[] = R"(precision mediump float;
7993 struct S { sampler2D samplerMember; };
7994 uniform S uStruct;
7995 uniform vec2 uTexCoord;
7996 vec4 foo(S structVar)
7997 {
7998     return texture2D(structVar.samplerMember, uTexCoord);
7999 }
8000 void main()
8001 {
8002     gl_FragColor = foo(uStruct);
8003 })";
8004 
8005     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
8006 
8007     // Initialize the texture with green.
8008     GLTexture tex;
8009     glActiveTexture(GL_TEXTURE0);
8010     glBindTexture(GL_TEXTURE_2D, tex);
8011     GLubyte texData[] = {0u, 255u, 0u, 255u};
8012     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
8013     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8014     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8015     ASSERT_GL_NO_ERROR();
8016 
8017     // Draw
8018     glUseProgram(program);
8019     GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMember");
8020     ASSERT_NE(-1, samplerMemberLoc);
8021     glUniform1i(samplerMemberLoc, 0);
8022     GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
8023     ASSERT_NE(-1, texCoordLoc);
8024     glUniform2f(texCoordLoc, 0.5f, 0.5f);
8025 
8026     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
8027     ASSERT_GL_NO_ERROR();
8028 
8029     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
8030 }
8031 
8032 // This test covers passing a struct containing a sampler as a function argument.
TEST_P(GLSLTest,StructsWithSamplersAsFunctionArgWithPrototype)8033 TEST_P(GLSLTest, StructsWithSamplersAsFunctionArgWithPrototype)
8034 {
8035     // Shader failed to compile on Android. http://anglebug.com/42260860
8036     ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
8037 
8038     const char kFragmentShader[] = R"(precision mediump float;
8039 struct S { sampler2D samplerMember; };
8040 uniform S uStruct;
8041 uniform vec2 uTexCoord;
8042 vec4 foo(S structVar);
8043 vec4 foo(S structVar)
8044 {
8045     return texture2D(structVar.samplerMember, uTexCoord);
8046 }
8047 void main()
8048 {
8049     gl_FragColor = foo(uStruct);
8050 })";
8051 
8052     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
8053 
8054     // Initialize the texture with green.
8055     GLTexture tex;
8056     glActiveTexture(GL_TEXTURE0);
8057     glBindTexture(GL_TEXTURE_2D, tex);
8058     GLubyte texData[] = {0u, 255u, 0u, 255u};
8059     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
8060     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8061     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8062     ASSERT_GL_NO_ERROR();
8063 
8064     // Draw
8065     glUseProgram(program);
8066     GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMember");
8067     ASSERT_NE(-1, samplerMemberLoc);
8068     glUniform1i(samplerMemberLoc, 0);
8069     GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
8070     ASSERT_NE(-1, texCoordLoc);
8071     glUniform2f(texCoordLoc, 0.5f, 0.5f);
8072 
8073     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
8074     ASSERT_GL_NO_ERROR();
8075 
8076     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
8077 }
8078 
8079 // This test covers passing a struct containing a sampler as a function argument, where the function
8080 // has non-return branch statements.
TEST_P(GLSLTest_ES3,StructsWithSamplersAsFunctionArgWithBranch)8081 TEST_P(GLSLTest_ES3, StructsWithSamplersAsFunctionArgWithBranch)
8082 {
8083     // Shader failed to compile on Nexus devices. http://anglebug.com/42260860
8084     ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
8085 
8086     const char kFragmentShader[] = R"(precision mediump float;
8087 struct S { sampler2D samplerMember; };
8088 uniform S uStruct;
8089 uniform vec2 uTexCoord;
8090 vec4 foo(S structVar)
8091 {
8092     vec4 result;
8093     while (true)
8094     {
8095         result = texture2D(structVar.samplerMember, uTexCoord);
8096         if (result.x == 12345.)
8097         {
8098             continue;
8099         }
8100         break;
8101     }
8102     return result;
8103 }
8104 void main()
8105 {
8106     gl_FragColor = foo(uStruct);
8107 })";
8108 
8109     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
8110 
8111     // Initialize the texture with green.
8112     GLTexture tex;
8113     glActiveTexture(GL_TEXTURE0);
8114     glBindTexture(GL_TEXTURE_2D, tex);
8115     GLubyte texData[] = {0u, 255u, 0u, 255u};
8116     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
8117     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8118     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8119     ASSERT_GL_NO_ERROR();
8120 
8121     // Draw
8122     glUseProgram(program);
8123     GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMember");
8124     ASSERT_NE(-1, samplerMemberLoc);
8125     glUniform1i(samplerMemberLoc, 0);
8126     GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
8127     ASSERT_NE(-1, texCoordLoc);
8128     glUniform2f(texCoordLoc, 0.5f, 0.5f);
8129 
8130     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
8131     ASSERT_GL_NO_ERROR();
8132 
8133     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
8134 }
8135 
8136 // This test covers passing an array of structs containing samplers as a function argument.
TEST_P(GLSLTest,ArrayOfStructsWithSamplersAsFunctionArg)8137 TEST_P(GLSLTest, ArrayOfStructsWithSamplersAsFunctionArg)
8138 {
8139     // Shader failed to compile on Nexus devices. http://anglebug.com/42260860
8140     ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
8141 
8142     constexpr char kFS[] =
8143         "precision mediump float;\n"
8144         "struct S\n"
8145         "{\n"
8146         "    sampler2D samplerMember; \n"
8147         "};\n"
8148         "uniform S uStructs[2];\n"
8149         "uniform vec2 uTexCoord;\n"
8150         "\n"
8151         "vec4 foo(S[2] structs)\n"
8152         "{\n"
8153         "    return texture2D(structs[0].samplerMember, uTexCoord);\n"
8154         "}\n"
8155         "void main()\n"
8156         "{\n"
8157         "    gl_FragColor = foo(uStructs);\n"
8158         "}\n";
8159 
8160     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
8161 
8162     // Initialize the texture with green.
8163     GLTexture tex;
8164     glActiveTexture(GL_TEXTURE0);
8165     glBindTexture(GL_TEXTURE_2D, tex);
8166     GLubyte texData[] = {0u, 255u, 0u, 255u};
8167     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
8168     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8169     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8170     ASSERT_GL_NO_ERROR();
8171 
8172     // Draw
8173     glUseProgram(program);
8174     GLint samplerMemberLoc = glGetUniformLocation(program, "uStructs[0].samplerMember");
8175     ASSERT_NE(-1, samplerMemberLoc);
8176     glUniform1i(samplerMemberLoc, 0);
8177     GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
8178     ASSERT_NE(-1, texCoordLoc);
8179     glUniform2f(texCoordLoc, 0.5f, 0.5f);
8180 
8181     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
8182     ASSERT_GL_NO_ERROR();
8183 
8184     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
8185 }
8186 
8187 // This test covers passing a struct containing an array of samplers as a function argument.
TEST_P(GLSLTest,StructWithSamplerArrayAsFunctionArg)8188 TEST_P(GLSLTest, StructWithSamplerArrayAsFunctionArg)
8189 {
8190     // Shader failed to compile on Nexus devices. http://anglebug.com/42260860
8191     ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
8192 
8193     constexpr char kFS[] =
8194         "precision mediump float;\n"
8195         "struct S\n"
8196         "{\n"
8197         "    sampler2D samplerMembers[2];\n"
8198         "};\n"
8199         "uniform S uStruct;\n"
8200         "uniform vec2 uTexCoord;\n"
8201         "\n"
8202         "vec4 foo(S str)\n"
8203         "{\n"
8204         "    return texture2D(str.samplerMembers[0], uTexCoord);\n"
8205         "}\n"
8206         "void main()\n"
8207         "{\n"
8208         "    gl_FragColor = foo(uStruct);\n"
8209         "}\n";
8210 
8211     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
8212 
8213     // Initialize the texture with green.
8214     GLTexture tex;
8215     glActiveTexture(GL_TEXTURE0);
8216     glBindTexture(GL_TEXTURE_2D, tex);
8217     GLubyte texData[] = {0u, 255u, 0u, 255u};
8218     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
8219     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8220     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8221     ASSERT_GL_NO_ERROR();
8222 
8223     // Draw
8224     glUseProgram(program);
8225     GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMembers[0]");
8226     ASSERT_NE(-1, samplerMemberLoc);
8227     glUniform1i(samplerMemberLoc, 0);
8228     GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
8229     ASSERT_NE(-1, texCoordLoc);
8230     glUniform2f(texCoordLoc, 0.5f, 0.5f);
8231 
8232     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
8233     ASSERT_GL_NO_ERROR();
8234 
8235     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
8236 }
8237 
8238 // This test covers passing nested structs containing a sampler as a function argument.
TEST_P(GLSLTest,NestedStructsWithSamplersAsFunctionArg)8239 TEST_P(GLSLTest, NestedStructsWithSamplersAsFunctionArg)
8240 {
8241     // Shader failed to compile on Nexus devices. http://anglebug.com/42260860
8242     ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
8243 
8244     // TODO(anglebug.com/40096747): Failing on ARM-based Apple DTKs.
8245     ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && IsDesktopOpenGL());
8246 
8247     const char kFragmentShader[] = R"(precision mediump float;
8248 struct S { sampler2D samplerMember; };
8249 struct T { S nest; };
8250 uniform T uStruct;
8251 uniform vec2 uTexCoord;
8252 vec4 foo2(S structVar)
8253 {
8254     return texture2D(structVar.samplerMember, uTexCoord);
8255 }
8256 vec4 foo(T structVar)
8257 {
8258     return foo2(structVar.nest);
8259 }
8260 void main()
8261 {
8262     gl_FragColor = foo(uStruct);
8263 })";
8264 
8265     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
8266 
8267     // Initialize the texture with green.
8268     GLTexture tex;
8269     glActiveTexture(GL_TEXTURE0);
8270     glBindTexture(GL_TEXTURE_2D, tex);
8271     GLubyte texData[] = {0u, 255u, 0u, 255u};
8272     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
8273     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8274     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8275     ASSERT_GL_NO_ERROR();
8276 
8277     // Draw
8278     glUseProgram(program);
8279     GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.nest.samplerMember");
8280     ASSERT_NE(-1, samplerMemberLoc);
8281     glUniform1i(samplerMemberLoc, 0);
8282     GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
8283     ASSERT_NE(-1, texCoordLoc);
8284     glUniform2f(texCoordLoc, 0.5f, 0.5f);
8285 
8286     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
8287     ASSERT_GL_NO_ERROR();
8288 
8289     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
8290 }
8291 
8292 // This test covers passing a compound structs containing a sampler as a function argument.
TEST_P(GLSLTest,CompoundStructsWithSamplersAsFunctionArg)8293 TEST_P(GLSLTest, CompoundStructsWithSamplersAsFunctionArg)
8294 {
8295     // Shader failed to compile on Nexus devices. http://anglebug.com/42260860
8296     ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
8297 
8298     const char kFragmentShader[] = R"(precision mediump float;
8299 struct S { sampler2D samplerMember; bool b; };
8300 uniform S uStruct;
8301 uniform vec2 uTexCoord;
8302 vec4 foo(S structVar)
8303 {
8304     if (structVar.b)
8305         return texture2D(structVar.samplerMember, uTexCoord);
8306     else
8307         return vec4(1, 0, 0, 1);
8308 }
8309 void main()
8310 {
8311     gl_FragColor = foo(uStruct);
8312 })";
8313 
8314     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
8315 
8316     // Initialize the texture with green.
8317     GLTexture tex;
8318     glActiveTexture(GL_TEXTURE0);
8319     glBindTexture(GL_TEXTURE_2D, tex);
8320     GLubyte texData[] = {0u, 255u, 0u, 255u};
8321     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
8322     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8323     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8324     ASSERT_GL_NO_ERROR();
8325 
8326     // Draw
8327     glUseProgram(program);
8328     GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.samplerMember");
8329     ASSERT_NE(-1, samplerMemberLoc);
8330     glUniform1i(samplerMemberLoc, 0);
8331     GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
8332     ASSERT_NE(-1, texCoordLoc);
8333     glUniform2f(texCoordLoc, 0.5f, 0.5f);
8334     GLint bLoc = glGetUniformLocation(program, "uStruct.b");
8335     ASSERT_NE(-1, bLoc);
8336     glUniform1i(bLoc, 1);
8337 
8338     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
8339     ASSERT_GL_NO_ERROR();
8340 
8341     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
8342 }
8343 
8344 // This test covers passing nested compound structs containing a sampler as a function argument.
TEST_P(GLSLTest,NestedCompoundStructsWithSamplersAsFunctionArg)8345 TEST_P(GLSLTest, NestedCompoundStructsWithSamplersAsFunctionArg)
8346 {
8347     // Shader failed to compile on Nexus devices. http://anglebug.com/42260860
8348     ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
8349 
8350     // TODO(anglebug.com/40096747): Failing on ARM-based Apple DTKs.
8351     ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && IsDesktopOpenGL());
8352 
8353     const char kFragmentShader[] = R"(precision mediump float;
8354 struct S { sampler2D samplerMember; bool b; };
8355 struct T { S nest; bool b; };
8356 uniform T uStruct;
8357 uniform vec2 uTexCoord;
8358 vec4 foo2(S structVar)
8359 {
8360     if (structVar.b)
8361         return texture2D(structVar.samplerMember, uTexCoord);
8362     else
8363         return vec4(1, 0, 0, 1);
8364 }
8365 vec4 foo(T structVar)
8366 {
8367     if (structVar.b)
8368         return foo2(structVar.nest);
8369     else
8370         return vec4(1, 0, 0, 1);
8371 }
8372 void main()
8373 {
8374     gl_FragColor = foo(uStruct);
8375 })";
8376 
8377     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
8378 
8379     // Initialize the texture with green.
8380     GLTexture tex;
8381     glActiveTexture(GL_TEXTURE0);
8382     glBindTexture(GL_TEXTURE_2D, tex);
8383     GLubyte texData[] = {0u, 255u, 0u, 255u};
8384     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
8385     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8386     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8387     ASSERT_GL_NO_ERROR();
8388 
8389     // Draw
8390     glUseProgram(program);
8391     GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.nest.samplerMember");
8392     ASSERT_NE(-1, samplerMemberLoc);
8393     glUniform1i(samplerMemberLoc, 0);
8394     GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
8395     ASSERT_NE(-1, texCoordLoc);
8396     glUniform2f(texCoordLoc, 0.5f, 0.5f);
8397 
8398     GLint bLoc = glGetUniformLocation(program, "uStruct.b");
8399     ASSERT_NE(-1, bLoc);
8400     glUniform1i(bLoc, 1);
8401 
8402     GLint nestbLoc = glGetUniformLocation(program, "uStruct.nest.b");
8403     ASSERT_NE(-1, nestbLoc);
8404     glUniform1i(nestbLoc, 1);
8405 
8406     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
8407     ASSERT_GL_NO_ERROR();
8408 
8409     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
8410 }
8411 
8412 // Same as the prior test but with reordered struct members.
TEST_P(GLSLTest,MoreNestedCompoundStructsWithSamplersAsFunctionArg)8413 TEST_P(GLSLTest, MoreNestedCompoundStructsWithSamplersAsFunctionArg)
8414 {
8415     // Shader failed to compile on Nexus devices. http://anglebug.com/42260860
8416     ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
8417 
8418     // TODO(anglebug.com/40096747): Failing on ARM-based Apple DTKs.
8419     ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && IsDesktopOpenGL());
8420 
8421     const char kFragmentShader[] = R"(precision mediump float;
8422 struct S { bool b; sampler2D samplerMember; };
8423 struct T { bool b; S nest; };
8424 uniform T uStruct;
8425 uniform vec2 uTexCoord;
8426 vec4 foo2(S structVar)
8427 {
8428     if (structVar.b)
8429         return texture2D(structVar.samplerMember, uTexCoord);
8430     else
8431         return vec4(1, 0, 0, 1);
8432 }
8433 vec4 foo(T structVar)
8434 {
8435     if (structVar.b)
8436         return foo2(structVar.nest);
8437     else
8438         return vec4(1, 0, 0, 1);
8439 }
8440 void main()
8441 {
8442     gl_FragColor = foo(uStruct);
8443 })";
8444 
8445     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
8446 
8447     // Initialize the texture with green.
8448     GLTexture tex;
8449     glActiveTexture(GL_TEXTURE0);
8450     glBindTexture(GL_TEXTURE_2D, tex);
8451     GLubyte texData[] = {0u, 255u, 0u, 255u};
8452     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
8453     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8454     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8455     ASSERT_GL_NO_ERROR();
8456 
8457     // Draw
8458     glUseProgram(program);
8459     GLint samplerMemberLoc = glGetUniformLocation(program, "uStruct.nest.samplerMember");
8460     ASSERT_NE(-1, samplerMemberLoc);
8461     glUniform1i(samplerMemberLoc, 0);
8462     GLint texCoordLoc = glGetUniformLocation(program, "uTexCoord");
8463     ASSERT_NE(-1, texCoordLoc);
8464     glUniform2f(texCoordLoc, 0.5f, 0.5f);
8465 
8466     GLint bLoc = glGetUniformLocation(program, "uStruct.b");
8467     ASSERT_NE(-1, bLoc);
8468     glUniform1i(bLoc, 1);
8469 
8470     GLint nestbLoc = glGetUniformLocation(program, "uStruct.nest.b");
8471     ASSERT_NE(-1, nestbLoc);
8472     glUniform1i(nestbLoc, 1);
8473 
8474     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
8475     ASSERT_GL_NO_ERROR();
8476 
8477     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
8478 }
8479 // Test that a global variable declared after main() works. This is a regression test for an issue
8480 // in global variable initialization.
TEST_P(WebGLGLSLTest,GlobalVariableDeclaredAfterMain)8481 TEST_P(WebGLGLSLTest, GlobalVariableDeclaredAfterMain)
8482 {
8483     constexpr char kFS[] =
8484         "precision mediump float;\n"
8485         "int getFoo();\n"
8486         "uniform int u_zero;\n"
8487         "void main()\n"
8488         "{\n"
8489         "    gl_FragColor = vec4(1, 0, 0, 1);\n"
8490         "    if (getFoo() == 0)\n"
8491         "    {\n"
8492         "        gl_FragColor = vec4(0, 1, 0, 1);\n"
8493         "    }\n"
8494         "}\n"
8495         "int foo;\n"
8496         "int getFoo()\n"
8497         "{\n"
8498         "    foo = u_zero;\n"
8499         "    return foo;\n"
8500         "}\n";
8501 
8502     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
8503     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
8504     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8505 }
8506 
8507 // Test calling array length() with a "this" expression having side effects inside a loop condition.
8508 // The spec says that sequence operator operands need to run in sequence.
TEST_P(GLSLTest_ES3,ArrayLengthOnExpressionWithSideEffectsInLoopCondition)8509 TEST_P(GLSLTest_ES3, ArrayLengthOnExpressionWithSideEffectsInLoopCondition)
8510 {
8511     // "a" gets doubled three times in the below program.
8512     constexpr char kFS[] = R"(#version 300 es
8513 precision highp float;
8514 out vec4 my_FragColor;
8515 uniform int u_zero;
8516 int a;
8517 int[2] doubleA()
8518 {
8519     a *= 2;
8520     return int[2](a, a);
8521 }
8522 void main()
8523 {
8524     a = u_zero + 1;
8525     for (int i = 0; i < doubleA().length(); ++i)
8526     {}
8527     if (a == 8)
8528     {
8529         my_FragColor = vec4(0, 1, 0, 1);
8530     }
8531     else
8532     {
8533         my_FragColor = vec4(1, 0, 0, 1);
8534     }
8535 })";
8536 
8537     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8538     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
8539     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8540 }
8541 
8542 // Test calling array length() with a "this" expression having side effects that interact with side
8543 // effects of another operand of the same sequence operator. The spec says that sequence operator
8544 // operands need to run in order from left to right (ESSL 3.00.6 section 5.9).
TEST_P(GLSLTest_ES3,ArrayLengthOnExpressionWithSideEffectsInSequence)8545 TEST_P(GLSLTest_ES3, ArrayLengthOnExpressionWithSideEffectsInSequence)
8546 {
8547     constexpr char kFS[] = R"(#version 300 es
8548 precision highp float;
8549 out vec4 my_FragColor;
8550 uniform int u_zero;
8551 int a;
8552 int[3] doubleA()
8553 {
8554     a *= 2;
8555     return int[3](a, a, a);
8556 }
8557 void main()
8558 {
8559     a = u_zero;
8560     int b = (a++, doubleA().length());
8561     if (b == 3 && a == 2)
8562     {
8563         my_FragColor = vec4(0, 1, 0, 1);
8564     }
8565     else
8566     {
8567         my_FragColor = vec4(1, 0, 0, 1);
8568     }
8569 })";
8570 
8571     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8572     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
8573     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8574 }
8575 
8576 // Test calling array length() with a "this" expression that also contains a call of array length().
8577 // Both "this" expressions also have side effects.
TEST_P(GLSLTest_ES3,NestedArrayLengthMethodsWithSideEffects)8578 TEST_P(GLSLTest_ES3, NestedArrayLengthMethodsWithSideEffects)
8579 {
8580     constexpr char kFS[] = R"(#version 300 es
8581 precision highp float;
8582 out vec4 my_FragColor;
8583 uniform int u_zero;
8584 int a;
8585 int[3] multiplyA(int multiplier)
8586 {
8587     a *= multiplier;
8588     return int[3](a, a, a);
8589 }
8590 void main()
8591 {
8592     a = u_zero + 1;
8593     int b = multiplyA(multiplyA(2).length()).length();
8594     if (b == 3 && a == 6)
8595     {
8596         my_FragColor = vec4(0, 1, 0, 1);
8597     }
8598     else
8599     {
8600         my_FragColor = vec4(1, 0, 0, 1);
8601     }
8602 })";
8603 
8604     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8605     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
8606     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8607 }
8608 
8609 // Test calling array length() with a "this" expression having side effects inside an if condition.
8610 // This is an issue if the the side effect can be short circuited.
TEST_P(GLSLTest_ES3,ArrayLengthOnShortCircuitedExpressionWithSideEffectsInIfCondition)8611 TEST_P(GLSLTest_ES3, ArrayLengthOnShortCircuitedExpressionWithSideEffectsInIfCondition)
8612 {
8613     // Bug in the shader translator.  http://anglebug.com/42262472
8614     ANGLE_SKIP_TEST_IF(true);
8615 
8616     // "a" shouldn't get modified by this shader.
8617     constexpr char kFS[] = R"(#version 300 es
8618 precision highp float;
8619 out vec4 my_FragColor;
8620 uniform int u_zero;
8621 int a;
8622 int[2] doubleA()
8623 {
8624     a *= 2;
8625     return int[2](a, a);
8626 }
8627 void main()
8628 {
8629     a = u_zero + 1;
8630     if (u_zero != 0 && doubleA().length() == 2)
8631     {
8632         ++a;
8633     }
8634     if (a == 1)
8635     {
8636         my_FragColor = vec4(0, 1, 0, 1);
8637     }
8638     else
8639     {
8640         my_FragColor = vec4(1, 0, 0, 1);
8641     }
8642 })";
8643 
8644     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8645     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
8646     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8647 }
8648 
8649 // Test calling array length() with a "this" expression having side effects in a statement where the
8650 // side effect can be short circuited.
TEST_P(GLSLTest_ES3,ArrayLengthOnShortCircuitedExpressionWithSideEffectsInStatement)8651 TEST_P(GLSLTest_ES3, ArrayLengthOnShortCircuitedExpressionWithSideEffectsInStatement)
8652 {
8653     // Bug in the shader translator.  http://anglebug.com/42262472
8654     ANGLE_SKIP_TEST_IF(true);
8655 
8656     // "a" shouldn't get modified by this shader.
8657     constexpr char kFS[] = R"(#version 300 es
8658 precision highp float;
8659 out vec4 my_FragColor;
8660 uniform int u_zero;
8661 int a;
8662 int[2] doubleA()
8663 {
8664     a *= 2;
8665     return int[2](a, a);
8666 }
8667 void main()
8668 {
8669     a = u_zero + 1;
8670     bool test = u_zero != 0 && doubleA().length() == 2;
8671     if (a == 1)
8672     {
8673         my_FragColor = vec4(0, 1, 0, 1);
8674     }
8675     else
8676     {
8677         my_FragColor = vec4(1, 0, 0, 1);
8678     }
8679 })";
8680 
8681     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8682     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
8683     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8684 }
8685 
8686 // Test that array length inside vector constructor works.
TEST_P(GLSLTest_ES3,ArrayLengthInVectorConstructor)8687 TEST_P(GLSLTest_ES3, ArrayLengthInVectorConstructor)
8688 {
8689     const char kVS[] = R"(#version 300 es
8690 precision highp float;
8691 flat out uvec4 v;
8692 
8693 int[1] f0()
8694 {
8695     return int[1](1);
8696 }
8697 void main()
8698 {
8699     v = uvec4(vec4(f0().length()));
8700 
8701     gl_Position.x = ((gl_VertexID & 1) == 0 ? -1.0 : 1.0);
8702     gl_Position.y = ((gl_VertexID & 2) == 0 ? -1.0 : 1.0);
8703     gl_Position.zw = vec2(0, 1);
8704 })";
8705 
8706     const char kFS[] = R"(#version 300 es
8707 precision highp float;
8708 flat in uvec4 v;
8709 out vec4 color;
8710 
8711 bool isEq(uint a, float b) { return abs(float(a) - b) < 0.01; }
8712 
8713 void main()
8714 {
8715     if (isEq(v[0], 1.) &&
8716         isEq(v[1], 1.) &&
8717         isEq(v[2], 1.) &&
8718         isEq(v[3], 1.))
8719     {
8720         color = vec4(0, 1, 0, 1);
8721     }
8722     else
8723     {
8724         color = vec4(1, 0, 0, 1);
8725     }
8726 })";
8727 
8728     ANGLE_GL_PROGRAM(program, kVS, kFS);
8729     glUseProgram(program);
8730     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
8731     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8732 }
8733 
8734 // Test that array length inside vector constructor works in complex expression.
TEST_P(GLSLTest_ES3,ArrayLengthInVectorConstructorComplex)8735 TEST_P(GLSLTest_ES3, ArrayLengthInVectorConstructorComplex)
8736 {
8737     const char kVS[] = R"(#version 300 es
8738 precision highp float;
8739 out vec4 v;
8740 
8741 int[1] f0()
8742 {
8743     return int[1](1);
8744 }
8745 void main()
8746 {
8747     v = vec4(float(uint(f0().length()) + 1u) / 4.);
8748 
8749     gl_Position.x = ((gl_VertexID & 1) == 0 ? -1.0 : 1.0);
8750     gl_Position.y = ((gl_VertexID & 2) == 0 ? -1.0 : 1.0);
8751     gl_Position.zw = vec2(0, 1);
8752 })";
8753 
8754     const char kFS[] = R"(#version 300 es
8755 precision highp float;
8756 in vec4 v;
8757 out vec4 color;
8758 
8759 bool isEq(float a, float b) { return abs(float(a) - b) < 0.01; }
8760 
8761 void main()
8762 {
8763     if (isEq(v[0], 0.5) &&
8764         isEq(v[1], 0.5) &&
8765         isEq(v[2], 0.5) &&
8766         isEq(v[3], 0.5))
8767     {
8768         color = vec4(0, 1, 0, 1);
8769     }
8770     else
8771     {
8772         color = vec4(1, 0, 0, 1);
8773     }
8774 })";
8775 
8776     ANGLE_GL_PROGRAM(program, kVS, kFS);
8777     glUseProgram(program);
8778     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
8779     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8780 }
8781 
8782 // Test that array length inside matrix constructor works.
TEST_P(GLSLTest_ES3,ArrayLengthInMatrixConstructor)8783 TEST_P(GLSLTest_ES3, ArrayLengthInMatrixConstructor)
8784 {
8785     const char kVS[] = R"(#version 300 es
8786 precision highp float;
8787 out mat2x2 v;
8788 
8789 int[1] f0()
8790 {
8791     return int[1](1);
8792 }
8793 void main()
8794 {
8795     v = mat2x2(f0().length());
8796 
8797     gl_Position.x = ((gl_VertexID & 1) == 0 ? -1.0 : 1.0);
8798     gl_Position.y = ((gl_VertexID & 2) == 0 ? -1.0 : 1.0);
8799     gl_Position.zw = vec2(0, 1);
8800 })";
8801 
8802     const char kFS[] = R"(#version 300 es
8803 precision highp float;
8804 in mat2x2 v;
8805 out vec4 color;
8806 
8807 bool isEq(float a, float b) { return abs(a - b) < 0.01; }
8808 
8809 void main()
8810 {
8811     if (isEq(v[0][0], 1.) &&
8812         isEq(v[0][1], 0.) &&
8813         isEq(v[1][0], 0.) &&
8814         isEq(v[1][1], 1.))
8815     {
8816         color = vec4(0, 1, 0, 1);
8817     }
8818     else
8819     {
8820         color = vec4(1, 0, 0, 1);
8821     }
8822 })";
8823 
8824     ANGLE_GL_PROGRAM(program, kVS, kFS);
8825     glUseProgram(program);
8826     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
8827     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8828 }
8829 
8830 // Test that array length inside vector constructor inside matrix constructor works.
TEST_P(GLSLTest_ES3,ArrayLengthInVectorInMatrixConstructor)8831 TEST_P(GLSLTest_ES3, ArrayLengthInVectorInMatrixConstructor)
8832 {
8833     const char kVS[] = R"(#version 300 es
8834 precision highp float;
8835 out mat2x2 v;
8836 
8837 int[1] f0()
8838 {
8839     return int[1](1);
8840 }
8841 void main()
8842 {
8843     v = mat2x2(vec2(f0().length()), f0().length(), 0);
8844 
8845     gl_Position.x = ((gl_VertexID & 1) == 0 ? -1.0 : 1.0);
8846     gl_Position.y = ((gl_VertexID & 2) == 0 ? -1.0 : 1.0);
8847     gl_Position.zw = vec2(0, 1);
8848 })";
8849 
8850     const char kFS[] = R"(#version 300 es
8851 precision highp float;
8852 in mat2x2 v;
8853 out vec4 color;
8854 
8855 bool isEq(float a, float b) { return abs(a - b) < 0.01; }
8856 
8857 void main()
8858 {
8859     if (isEq(v[0][0], 1.) &&
8860         isEq(v[0][1], 1.) &&
8861         isEq(v[1][0], 1.) &&
8862         isEq(v[1][1], 0.))
8863     {
8864         color = vec4(0, 1, 0, 1);
8865     }
8866     else
8867     {
8868         color = vec4(1, 0, 0, 1);
8869     }
8870 })";
8871 
8872     ANGLE_GL_PROGRAM(program, kVS, kFS);
8873     glUseProgram(program);
8874     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
8875     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8876 }
8877 
8878 // Test that statements inside switch() get translated to correct HLSL.
TEST_P(GLSLTest_ES3,DifferentStatementsInsideSwitch)8879 TEST_P(GLSLTest_ES3, DifferentStatementsInsideSwitch)
8880 {
8881     constexpr char kFS[] = R"(#version 300 es
8882 precision highp float;
8883 uniform int u;
8884 void main()
8885 {
8886     switch (u)
8887     {
8888         case 0:
8889             ivec2 i;
8890             i.yx;
8891     }
8892 })";
8893 
8894     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8895 }
8896 
8897 // Test that switch fall-through works correctly.
8898 // This is a regression test for http://anglebug.com/40644631
TEST_P(GLSLTest_ES3,SwitchFallThroughCodeDuplication)8899 TEST_P(GLSLTest_ES3, SwitchFallThroughCodeDuplication)
8900 {
8901     constexpr char kFS[] = R"(#version 300 es
8902 precision highp float;
8903 out vec4 my_FragColor;
8904 uniform int u_zero;
8905 
8906 void main()
8907 {
8908     int i = 0;
8909     // switch should fall through both cases.
8910     switch(u_zero)
8911     {
8912         case 0:
8913             i += 1;
8914         case 1:
8915             i += 2;
8916     }
8917     if (i == 3)
8918     {
8919         my_FragColor = vec4(0, 1, 0, 1);
8920     }
8921     else
8922     {
8923         my_FragColor = vec4(1, 0, 0, 1);
8924     }
8925 })";
8926 
8927     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8928     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
8929     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8930 }
8931 
8932 // Test switch/case where default is last.
TEST_P(GLSLTest_ES3,SwitchWithDefaultAtTheEnd)8933 TEST_P(GLSLTest_ES3, SwitchWithDefaultAtTheEnd)
8934 {
8935     constexpr char kFS[] = R"(#version 300 es
8936 
8937 precision highp float;
8938 out vec4 my_FragColor;
8939 
8940 uniform int u_zero;
8941 
8942 void main()
8943 {
8944     switch (u_zero)
8945     {
8946         case 1:
8947             my_FragColor = vec4(1, 0, 0, 1);
8948             break;
8949         default:
8950             my_FragColor = vec4(0, 1, 0, 1);
8951     }
8952 })";
8953 
8954     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8955     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
8956     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8957 }
8958 
8959 // Test that a switch statement with an empty block inside as a final statement compiles.
TEST_P(GLSLTest_ES3,SwitchFinalCaseHasEmptyBlock)8960 TEST_P(GLSLTest_ES3, SwitchFinalCaseHasEmptyBlock)
8961 {
8962     constexpr char kFS[] = R"(#version 300 es
8963 
8964 precision mediump float;
8965 uniform int i;
8966 void main()
8967 {
8968     switch (i)
8969     {
8970         case 0:
8971             break;
8972         default:
8973             {}
8974     }
8975 })";
8976     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8977 }
8978 
8979 // Test that a switch statement with an empty declaration inside as a final statement compiles.
TEST_P(GLSLTest_ES3,SwitchFinalCaseHasEmptyDeclaration)8980 TEST_P(GLSLTest_ES3, SwitchFinalCaseHasEmptyDeclaration)
8981 {
8982     constexpr char kFS[] = R"(#version 300 es
8983 
8984 precision mediump float;
8985 uniform int i;
8986 void main()
8987 {
8988     switch (i)
8989     {
8990         case 0:
8991             break;
8992         default:
8993             float;
8994     }
8995 })";
8996     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
8997 }
8998 
8999 // Test switch/case where break/return statements are within blocks.
TEST_P(GLSLTest_ES3,SwitchBreakOrReturnInsideBlocks)9000 TEST_P(GLSLTest_ES3, SwitchBreakOrReturnInsideBlocks)
9001 {
9002     constexpr char kFS[] = R"(#version 300 es
9003 
9004 precision highp float;
9005 
9006 uniform int u_zero;
9007 out vec4 my_FragColor;
9008 
9009 bool test(int n)
9010 {
9011     switch(n) {
9012         case 0:
9013         {
9014             {
9015                 break;
9016             }
9017         }
9018         case 1:
9019         {
9020             return true;
9021         }
9022         case 2:
9023         {
9024             n++;
9025         }
9026     }
9027     return false;
9028 }
9029 
9030 void main()
9031 {
9032     my_FragColor = test(u_zero + 1) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
9033 })";
9034 
9035     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9036     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
9037     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9038 }
9039 
9040 // Test switch/case where a variable is declared inside one of the cases and is accessed by a
9041 // subsequent case.
TEST_P(GLSLTest_ES3,SwitchWithVariableDeclarationInside)9042 TEST_P(GLSLTest_ES3, SwitchWithVariableDeclarationInside)
9043 {
9044     constexpr char kFS[] = R"(#version 300 es
9045 
9046 precision highp float;
9047 out vec4 my_FragColor;
9048 
9049 uniform int u_zero;
9050 
9051 void main()
9052 {
9053     my_FragColor = vec4(1, 0, 0, 1);
9054     switch (u_zero)
9055     {
9056         case 0:
9057             ivec2 i;
9058             i = ivec2(1, 0);
9059         default:
9060             my_FragColor = vec4(0, i[0], 0, 1);
9061     }
9062 })";
9063 
9064     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9065     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
9066     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9067 }
9068 
9069 // Test nested switch/case where a variable is declared inside one of the cases and is accessed by a
9070 // subsequent case.
TEST_P(GLSLTest_ES3,NestedSwitchWithVariableDeclarationInside)9071 TEST_P(GLSLTest_ES3, NestedSwitchWithVariableDeclarationInside)
9072 {
9073     constexpr char kFS[] = R"(#version 300 es
9074 
9075 precision highp float;
9076 out vec4 my_FragColor;
9077 
9078 uniform int u_zero;
9079 uniform int u_zero2;
9080 
9081 void main()
9082 {
9083     my_FragColor = vec4(1, 0, 0, 1);
9084     switch (u_zero)
9085     {
9086         case 0:
9087             ivec2 i;
9088             i = ivec2(1, 0);
9089             switch (u_zero2)
9090             {
9091                 case 0:
9092                     int j;
9093                 default:
9094                     j = 1;
9095                     i *= j;
9096             }
9097         default:
9098             my_FragColor = vec4(0, i[0], 0, 1);
9099     }
9100 })";
9101 
9102     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9103     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
9104     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9105 }
9106 
9107 // Test that an empty switch/case statement is translated in a way that compiles and executes the
9108 // init-statement.
TEST_P(GLSLTest_ES3,EmptySwitch)9109 TEST_P(GLSLTest_ES3, EmptySwitch)
9110 {
9111     constexpr char kFS[] = R"(#version 300 es
9112 
9113 precision highp float;
9114 
9115 uniform int u_zero;
9116 out vec4 my_FragColor;
9117 
9118 void main()
9119 {
9120     int i = u_zero;
9121     switch(++i) {}
9122     my_FragColor = (i == 1) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
9123 })";
9124 
9125     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9126     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
9127     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9128 }
9129 
9130 // Test that an switch over a constant with mismatching cases works.
TEST_P(GLSLTest_ES3,SwitchWithConstantExpr)9131 TEST_P(GLSLTest_ES3, SwitchWithConstantExpr)
9132 {
9133     constexpr char kFS[] = R"(#version 300 es
9134 precision highp float;
9135 out vec4 color;
9136 
9137 void main()
9138 {
9139     float r = 0.;
9140     float g = 1.;
9141     float b = 0.;
9142 
9143     switch(10)
9144     {
9145         case 44:
9146             r = 0.5;
9147         case 50:
9148             break;
9149     }
9150 
9151     switch(20)
9152     {
9153         case 198:
9154             g = 0.5;
9155         default:
9156             g -= 1.;
9157             break;
9158     }
9159 
9160     switch(30)
9161     {
9162         default:
9163             b = 0.5;
9164         case 4:
9165             b += 0.5;
9166             break;
9167     }
9168 
9169     color = vec4(r, g, b, 1);
9170 })";
9171 
9172     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9173     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
9174     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
9175 }
9176 
9177 // Test that basic infinite loops are either rejected or are pruned in WebGL
TEST_P(WebGL2GLSLTest,BasicInfiniteLoop)9178 TEST_P(WebGL2GLSLTest, BasicInfiniteLoop)
9179 {
9180     constexpr char kFS[] = R"(#version 300 es
9181 precision highp float;
9182 uniform uint zero;
9183 out vec4 color;
9184 
9185 bool globalConstantVariable = true;
9186 
9187 float f()
9188 {
9189     // Should not be pruned
9190     while (true)
9191     {
9192         // Should not be pruned
9193         for (int i = 0; true; ++i)
9194         {
9195             if (zero < 10u)
9196             {
9197                 switch (zero)
9198                 {
9199                     case 0u:
9200                         // Loops should be pruned because of this `return`.
9201                         return 0.7;
9202                     default:
9203                         break;
9204                 }
9205             }
9206         }
9207     }
9208 }
9209 
9210 void main()
9211 {
9212     float r = 0.;
9213     float g = 1.;
9214     float b = 0.;
9215 
9216     bool localConstantVariable = true;
9217     bool localVariable = true;
9218 
9219     // Should be pruned
9220     while (true)
9221     {
9222         r += 0.1;
9223         if (r > 0.)
9224         {
9225             continue;
9226         }
9227     }
9228 
9229     if (zero != 0u)
9230     {
9231         localVariable = false;
9232     }
9233 
9234     // Should be pruned
9235     while (localConstantVariable)
9236     {
9237         g -= 0.1;
9238     }
9239 
9240     // Should not be pruned
9241     while (localConstantVariable)
9242     {
9243         b += 0.3;
9244 
9245         if (g > 0.4) { break; }
9246     }
9247 
9248     // Should be pruned
9249     for (; globalConstantVariable; )
9250     {
9251         g -= 0.1;
9252 
9253         switch (zero)
9254         {
9255             case 0u:
9256                 r = 0.4;
9257                 break;
9258             default:
9259                 r = 0.2;
9260                 break;
9261         }
9262     }
9263 
9264     // Should not be pruned
9265     while (localVariable)
9266     {
9267         b += 0.2;
9268         localVariable = !localVariable;
9269     }
9270 
9271     r = f();
9272 
9273     color = vec4(r, g, b, 1);
9274 })";
9275 
9276     if (getEGLWindow()->isFeatureEnabled(Feature::RejectWebglShadersWithUndefinedBehavior))
9277     {
9278         GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
9279         EXPECT_EQ(0u, shader);
9280     }
9281     else
9282     {
9283         ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9284         drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
9285         EXPECT_PIXEL_NEAR(0, 0, 178, 255, 127, 255, 1);
9286     }
9287 }
9288 
9289 // Test that while(true) loops with break/return are not rejected
TEST_P(WebGL2GLSLTest,NotInfiniteLoop)9290 TEST_P(WebGL2GLSLTest, NotInfiniteLoop)
9291 {
9292     constexpr char kFS[] = R"(#version 300 es
9293 precision highp float;
9294 uniform uint zero;
9295 out vec4 color;
9296 
9297 void main()
9298 {
9299     float r = 0.;
9300     float g = 1.;
9301     float b = 0.;
9302 
9303     while (true)
9304     {
9305         r += 0.1;
9306         if (r > 0.4)
9307         {
9308             break;
9309         }
9310     }
9311 
9312     for (;;)
9313     {
9314         g -= 0.1;
9315 
9316         switch (zero)
9317         {
9318             case 0u:
9319                 g -= 0.6;
9320                 color = vec4(r, g, b, 1);
9321                 return;
9322             default:
9323                 r = 0.2;
9324                 break;
9325         }
9326     }
9327 })";
9328 
9329     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9330     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
9331     EXPECT_PIXEL_NEAR(0, 0, 127, 76, 0, 255, 1);
9332 }
9333 
9334 // Test that a constant struct inside an expression is handled correctly.
TEST_P(GLSLTest_ES3,ConstStructInsideExpression)9335 TEST_P(GLSLTest_ES3, ConstStructInsideExpression)
9336 {
9337     // Incorrect output color was seen on Android. http://anglebug.com/42260946
9338     ANGLE_SKIP_TEST_IF(IsAndroid() && !IsNVIDIA() && IsOpenGLES());
9339 
9340     constexpr char kFS[] = R"(#version 300 es
9341 
9342 precision highp float;
9343 out vec4 my_FragColor;
9344 
9345 uniform float u_zero;
9346 
9347 struct S
9348 {
9349     float field;
9350 };
9351 
9352 void main()
9353 {
9354     const S constS = S(1.0);
9355     S nonConstS = constS;
9356     nonConstS.field = u_zero;
9357     bool fail = (constS == nonConstS);
9358     my_FragColor = vec4(0, 1, 0, 1);
9359     if (fail)
9360     {
9361         my_FragColor = vec4(1, 0, 0, 1);
9362     }
9363 })";
9364 
9365     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
9366     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
9367     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9368 }
9369 
9370 // Test that a varying struct that's defined as a part of the declaration is handled correctly.
TEST_P(GLSLTest_ES3,VaryingStructWithInlineDefinition)9371 TEST_P(GLSLTest_ES3, VaryingStructWithInlineDefinition)
9372 {
9373     constexpr char kVS[] = R"(#version 300 es
9374 in vec4 inputAttribute;
9375 
9376 flat out struct S
9377 {
9378     int field;
9379 } v_s;
9380 
9381 void main()
9382 {
9383     v_s.field = 1;
9384     gl_Position = inputAttribute;
9385 })";
9386 
9387     constexpr char kFS[] = R"(#version 300 es
9388 
9389 precision highp float;
9390 out vec4 my_FragColor;
9391 
9392 flat in struct S
9393 {
9394     int field;
9395 } v_s;
9396 
9397 void main()
9398 {
9399     bool success = (v_s.field == 1);
9400     my_FragColor = vec4(1, 0, 0, 1);
9401     if (success)
9402     {
9403         my_FragColor = vec4(0, 1, 0, 1);
9404     }
9405 })";
9406 
9407     ANGLE_GL_PROGRAM(program, kVS, kFS);
9408     drawQuad(program, "inputAttribute", 0.5f);
9409     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9410 }
9411 
9412 // Test that multi variables struct should not crash in separated struct expressions.
TEST_P(GLSLTest_ES3,VaryingStructWithInlineDefinition2)9413 TEST_P(GLSLTest_ES3, VaryingStructWithInlineDefinition2)
9414 {
9415     constexpr char kVS[] = R"(#version 300 es
9416 in vec4 inputAttribute;
9417 flat out struct A
9418 {
9419     int a;
9420 } z1, z2;
9421 void main()
9422 {
9423     z1.a = 1;
9424     z2.a = 2;
9425     gl_Position = inputAttribute;
9426 })";
9427     constexpr char kFS[] = R"(#version 300 es
9428 precision highp float;
9429 out vec4 my_FragColor;
9430 flat in struct A
9431 {
9432     int a;
9433 } z1, z2;
9434 void main()
9435 {
9436     bool success = (z1.a == 1 && z2.a == 2);
9437     my_FragColor = vec4(1, 0, 0, 1);
9438     if (success)
9439     {
9440         my_FragColor = vec4(0, 1, 0, 1);
9441     }
9442 })";
9443 
9444     ANGLE_GL_PROGRAM(program, kVS, kFS);
9445     drawQuad(program.get(), "inputAttribute", 0.5f);
9446     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9447 }
9448 
9449 // Test that a varying anonymous struct that is defined as a part of the declaration is handled
9450 // correctly.
TEST_P(GLSLTest_ES3,VaryingAnonymousStructWithInlineDefinition)9451 TEST_P(GLSLTest_ES3, VaryingAnonymousStructWithInlineDefinition)
9452 {
9453     constexpr char kVS[] = R"(#version 300 es
9454 in vec4 inputAttribute;
9455 flat out struct
9456 {
9457     int field;
9458 } v_s;
9459 
9460 void main()
9461 {
9462     v_s.field = 1;
9463     gl_Position = inputAttribute;
9464 })";
9465 
9466     constexpr char kFS[] = R"(#version 300 es
9467 precision highp float;
9468 out vec4 my_FragColor;
9469 flat in struct
9470 {
9471     int field;
9472 } v_s;
9473 void main()
9474 {
9475     bool success = (v_s.field == 1);
9476     my_FragColor = vec4(1, 0, 0, 1);
9477     if (success)
9478     {
9479         my_FragColor = vec4(0, 1, 0, 1);
9480     }
9481 })";
9482     ANGLE_GL_PROGRAM(program, kVS, kFS);
9483     drawQuad(program.get(), "inputAttribute", 0.5f);
9484     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9485 }
9486 
9487 // Test that a varying anonymous structs that are defined as a part of the declaration is handled
9488 // correctly.
TEST_P(GLSLTest_ES3,VaryingAnonymousStructWithInlineDefinition2)9489 TEST_P(GLSLTest_ES3, VaryingAnonymousStructWithInlineDefinition2)
9490 {
9491     constexpr char kVS[] = R"(#version 300 es
9492 in vec4 inputAttribute;
9493 flat out struct
9494 {
9495     int field;
9496 } v_s0, v_s1;
9497 void main()
9498 {
9499     v_s0.field = 1;
9500     v_s1.field = 2;
9501     gl_Position = inputAttribute;
9502 })";
9503     constexpr char kFS[] = R"(#version 300 es
9504 precision highp float;
9505 out vec4 my_FragColor;
9506 flat in struct
9507 {
9508     int field;
9509 } v_s0, v_s1;
9510 void main()
9511 {
9512     bool success = (v_s0.field == 1 && v_s1.field == 2);
9513     my_FragColor = vec4(1, 0, 0, 1);
9514     if (success)
9515     {
9516         my_FragColor = vec4(0, 1, 0, 1);
9517     }
9518 })";
9519     ANGLE_GL_PROGRAM(program, kVS, kFS);
9520     drawQuad(program.get(), "inputAttribute", 0.5f);
9521     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9522 }
9523 
9524 // Test that a varying anonymous structs that are defined as a part of the declaration is handled
9525 // in a specific way. Highlights ambiguity of ES "Chapter 9. Shader Interface Matching":
9526 //  "When linking shaders, the type of declared vertex outputs and fragment inputs with the same
9527 //  name must match"
TEST_P(GLSLTest_ES3,VaryingAnonymousStructWithInlineDefinition3)9528 TEST_P(GLSLTest_ES3, VaryingAnonymousStructWithInlineDefinition3)
9529 {
9530     constexpr char kVS[] = R"(#version 300 es
9531 in vec4 inputAttribute;
9532 flat out struct
9533 {
9534     int field;
9535 } v_s0;
9536 flat out struct
9537 {
9538     int field;
9539 } v_s1;
9540 flat out struct
9541 {
9542     int field;
9543 } v_s2, v_s3;
9544 void main()
9545 {
9546     v_s0.field = 1;
9547     v_s1.field = 2;
9548     v_s2.field = 3;
9549     v_s3.field = 4;
9550     gl_Position = inputAttribute;
9551 })";
9552 
9553     constexpr char kFS[] = R"(#version 300 es
9554 precision highp float;
9555 out vec4 my_FragColor;
9556 flat in struct
9557 {
9558     int field;
9559 } v_s0, v_s1, v_s2, v_s3;
9560 void main()
9561 {
9562     bool success = v_s0.field == 1 && v_s1.field == 2 && v_s2.field == 3 && v_s3.field == 4;
9563     my_FragColor = vec4(1, 0, 0, 1);
9564     if (success)
9565     {
9566         my_FragColor = vec4(0, 1, 0, 1);
9567     }
9568 })";
9569 
9570     ANGLE_GL_PROGRAM(program, kVS, kFS);
9571     drawQuad(program.get(), "inputAttribute", 0.5f);
9572     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9573 }
9574 
9575 // Test that a varying anonymous structs can be compared for equality.
TEST_P(GLSLTest_ES3,VaryingAnonymousStructEquality)9576 TEST_P(GLSLTest_ES3, VaryingAnonymousStructEquality)
9577 {
9578     constexpr char kVS[] = R"(#version 300 es
9579 in vec4 inputAttribute;
9580 flat out struct
9581 {
9582     int field;
9583 } v_s0;
9584 flat out struct
9585 {
9586     int field;
9587 } v_s1;
9588 flat out struct
9589 {
9590     int field;
9591 } v_s2, v_s3;
9592 
9593 void main()
9594 {
9595     v_s0.field = 1;
9596     v_s1.field = 2;
9597     v_s2.field = 3;
9598     v_s3.field = 4;
9599     gl_Position = inputAttribute;
9600 })";
9601 
9602     constexpr char kFS[] = R"(#version 300 es
9603 precision highp float;
9604 out vec4 my_FragColor;
9605 flat in struct
9606 {
9607     int field;
9608 } v_s0, v_s1, v_s2, v_s3;
9609 void main()
9610 {
9611     bool success = v_s0 != v_s1 && v_s0 != v_s2 && v_s0 != v_s3 && v_s1 != v_s2 && v_s1 != v_s3 && v_s2 != v_s3;
9612     success = success && v_s0.field == 1 && v_s1.field == 2 && v_s2.field == 3 && v_s3.field == 4;
9613     my_FragColor = vec4(1, 0, 0, 1);
9614     if (success)
9615     {
9616         my_FragColor = vec4(0, 1, 0, 1);
9617     }
9618 })";
9619 
9620     ANGLE_GL_PROGRAM(program, kVS, kFS);
9621     drawQuad(program.get(), "inputAttribute", 0.5f);
9622     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9623 }
9624 
9625 // Test mismatched precision in varying is handled correctly.
TEST_P(GLSLTest_ES3,MismatchPrecisionFloat)9626 TEST_P(GLSLTest_ES3, MismatchPrecisionFloat)
9627 {
9628     constexpr char kVS[] = R"(#version 300 es
9629 in vec4 position;
9630 uniform highp float inVal;
9631 out highp float myVarying;
9632 
9633 void main()
9634 {
9635     myVarying = inVal;
9636     gl_Position = position;
9637 })";
9638 
9639     constexpr char kFS[] = R"(#version 300 es
9640 precision highp float;
9641 out vec4 my_FragColor;
9642 in mediump float myVarying;
9643 
9644 void main()
9645 {
9646     my_FragColor = vec4(1, 0, 0, 1);
9647     if (myVarying > 1.0)
9648     {
9649         my_FragColor = vec4(0, 1, 0, 1);
9650     }
9651 })";
9652 
9653     ANGLE_GL_PROGRAM(program, kVS, kFS);
9654 
9655     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
9656     glClear(GL_COLOR_BUFFER_BIT);
9657     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
9658 
9659     glUseProgram(program);
9660     GLint positionLocation              = glGetAttribLocation(program, "position");
9661     std::array<Vector3, 6> quadVertices = GetQuadVertices();
9662     for (Vector3 &vertex : quadVertices)
9663     {
9664         vertex.z() = 0.5f;
9665     }
9666     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
9667     glEnableVertexAttribArray(positionLocation);
9668 
9669     GLint inValLoc = glGetUniformLocation(program, "inVal");
9670     ASSERT_NE(-1, inValLoc);
9671     glUniform1f(inValLoc, static_cast<GLfloat>(1.003));
9672 
9673     glDrawArrays(GL_TRIANGLES, 0, 6);
9674     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9675 }
9676 
9677 // Test mismatched precision in varying is handled correctly.
TEST_P(GLSLTest_ES3,MismatchPrecisionlowpFloat)9678 TEST_P(GLSLTest_ES3, MismatchPrecisionlowpFloat)
9679 {
9680     // Note: SPIRV only has relaxed precision so both lowp and mediump turn into "relaxed
9681     // precision", thus this is the same test as MismatchPrecisionFloat but including it for
9682     // completeness in case something changes.
9683     constexpr char kVS[] = R"(#version 300 es
9684 in vec4 position;
9685 uniform highp float inVal;
9686 out highp float myVarying;
9687 
9688 void main()
9689 {
9690     myVarying = inVal;
9691     gl_Position = position;
9692 })";
9693 
9694     constexpr char kFS[] = R"(#version 300 es
9695 precision highp float;
9696 out vec4 my_FragColor;
9697 in lowp float myVarying;
9698 
9699 void main()
9700 {
9701     my_FragColor = vec4(1, 0, 0, 1);
9702     if (myVarying > 1.0)
9703     {
9704         my_FragColor = vec4(0, 1, 0, 1);
9705     }
9706 })";
9707 
9708     ANGLE_GL_PROGRAM(program, kVS, kFS);
9709 
9710     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
9711     glClear(GL_COLOR_BUFFER_BIT);
9712     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
9713 
9714     glUseProgram(program);
9715     GLint positionLocation              = glGetAttribLocation(program, "position");
9716     std::array<Vector3, 6> quadVertices = GetQuadVertices();
9717     for (Vector3 &vertex : quadVertices)
9718     {
9719         vertex.z() = 0.5f;
9720     }
9721     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
9722     glEnableVertexAttribArray(positionLocation);
9723 
9724     GLint inValLoc = glGetUniformLocation(program, "inVal");
9725     ASSERT_NE(-1, inValLoc);
9726     glUniform1f(inValLoc, static_cast<GLfloat>(1.003));
9727 
9728     glDrawArrays(GL_TRIANGLES, 0, 6);
9729     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9730 }
9731 
9732 // Test mismatched precision in varying is handled correctly.
TEST_P(GLSLTest_ES3,MismatchPrecisionVec2UnusedVarying)9733 TEST_P(GLSLTest_ES3, MismatchPrecisionVec2UnusedVarying)
9734 {
9735     constexpr char kVS[] = R"(#version 300 es
9736 in vec2 position;
9737 uniform highp float inVal;
9738 out highp float myVarying;
9739 out highp vec2 texCoord;
9740 
9741 void main()
9742 {
9743     myVarying = inVal;
9744     gl_Position = vec4(position, 0, 1);
9745     texCoord = position * 0.5 + vec2(0.5);
9746 })";
9747 
9748     constexpr char kFS[] = R"(#version 300 es
9749 precision highp float;
9750 out vec4 my_FragColor;
9751 in mediump float myVarying;
9752 in mediump vec2 texCoord;
9753 
9754 void main()
9755 {
9756     my_FragColor = vec4(1, 0, 0, 1);
9757     if (myVarying > 1.0)
9758     {
9759         my_FragColor = vec4(0, 1, 0, 1);
9760     }
9761 })";
9762 
9763     ANGLE_GL_PROGRAM(program, kVS, kFS);
9764 
9765     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
9766     glClear(GL_COLOR_BUFFER_BIT);
9767     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
9768 
9769     glUseProgram(program);
9770     GLint positionLocation              = glGetAttribLocation(program, "position");
9771     std::array<Vector3, 6> quadVertices = GetQuadVertices();
9772     for (Vector3 &vertex : quadVertices)
9773     {
9774         vertex.z() = 0.5f;
9775     }
9776     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
9777     glEnableVertexAttribArray(positionLocation);
9778 
9779     GLint inValLoc = glGetUniformLocation(program, "inVal");
9780     ASSERT_NE(-1, inValLoc);
9781     glUniform1f(inValLoc, static_cast<GLfloat>(1.003));
9782 
9783     glDrawArrays(GL_TRIANGLES, 0, 6);
9784     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9785 }
9786 
9787 // Test mismatched precision in varying is handled correctly.
TEST_P(GLSLTest_ES3,MismatchPrecisionMedToHigh)9788 TEST_P(GLSLTest_ES3, MismatchPrecisionMedToHigh)
9789 {
9790     constexpr char kVS[] = R"(#version 300 es
9791 in vec2 position;
9792 uniform highp float inVal;
9793 out mediump float myVarying;
9794 
9795 void main()
9796 {
9797     myVarying = inVal;
9798     gl_Position = vec4(position, 0, 1);
9799 })";
9800 
9801     constexpr char kFS[] = R"(#version 300 es
9802 precision highp float;
9803 out vec4 my_FragColor;
9804 in highp float myVarying;
9805 
9806 void main()
9807 {
9808     my_FragColor = vec4(1, 0, 0, 1);
9809     if (myVarying > 1.0)
9810     {
9811         my_FragColor = vec4(0, 1, 0, 1);
9812     }
9813 })";
9814 
9815     ANGLE_GL_PROGRAM(program, kVS, kFS);
9816 
9817     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
9818     glClear(GL_COLOR_BUFFER_BIT);
9819     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
9820 
9821     glUseProgram(program);
9822     GLint positionLocation              = glGetAttribLocation(program, "position");
9823     std::array<Vector3, 6> quadVertices = GetQuadVertices();
9824     for (Vector3 &vertex : quadVertices)
9825     {
9826         vertex.z() = 0.5f;
9827     }
9828     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
9829     glEnableVertexAttribArray(positionLocation);
9830 
9831     GLint inValLoc = glGetUniformLocation(program, "inVal");
9832     ASSERT_NE(-1, inValLoc);
9833     glUniform1f(inValLoc, static_cast<GLfloat>(1.003));
9834 
9835     glDrawArrays(GL_TRIANGLES, 0, 6);
9836     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9837 }
9838 
9839 // Test that *= on boolean vectors fails compilation
TEST_P(GLSLTest,BVecMultiplyAssign)9840 TEST_P(GLSLTest, BVecMultiplyAssign)
9841 {
9842     constexpr char kFS[] = R"(bvec4 c,s;void main(){s*=c;})";
9843 
9844     GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
9845     EXPECT_EQ(fs, 0u);
9846 }
9847 
9848 // Test vector/scalar arithmetic (in this case multiplication and addition).
TEST_P(GLSLTest,VectorScalarMultiplyAndAddInLoop)9849 TEST_P(GLSLTest, VectorScalarMultiplyAndAddInLoop)
9850 {
9851     constexpr char kFS[] = R"(precision mediump float;
9852 
9853 void main() {
9854     gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
9855     for (int i = 0; i < 2; i++)
9856     {
9857         gl_FragColor += (2.0 * gl_FragCoord.x);
9858     }
9859     if (gl_FragColor.g == gl_FragColor.r &&
9860         gl_FragColor.b == gl_FragColor.r &&
9861         gl_FragColor.a == gl_FragColor.r)
9862     {
9863         gl_FragColor = vec4(0, 1, 0, 1);
9864     }
9865 })";
9866 
9867     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
9868     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
9869     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9870 }
9871 
9872 // Test vector/scalar arithmetic (in this case compound division and addition).
TEST_P(GLSLTest,VectorScalarDivideAndAddInLoop)9873 TEST_P(GLSLTest, VectorScalarDivideAndAddInLoop)
9874 {
9875     constexpr char kFS[] = R"(precision mediump float;
9876 
9877 void main() {
9878     gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
9879     for (int i = 0; i < 2; i++)
9880     {
9881         float x = gl_FragCoord.x;
9882         gl_FragColor = gl_FragColor + (x /= 2.0);
9883     }
9884     if (gl_FragColor.g == gl_FragColor.r &&
9885         gl_FragColor.b == gl_FragColor.r &&
9886         gl_FragColor.a == gl_FragColor.r)
9887     {
9888         gl_FragColor = vec4(0, 1, 0, 1);
9889     }
9890 })";
9891 
9892     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
9893     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
9894     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9895 }
9896 
9897 // Test a fuzzer-discovered bug with the VectorizeVectorScalarArithmetic transformation.
TEST_P(GLSLTest,VectorScalarArithmeticWithSideEffectInLoop)9898 TEST_P(GLSLTest, VectorScalarArithmeticWithSideEffectInLoop)
9899 {
9900     // The VectorizeVectorScalarArithmetic transformation was generating invalid code in the past
9901     // (notice how sbcd references i outside the for loop.  The loop condition doesn't look right
9902     // either):
9903     //
9904     //     #version 450
9905     //     void main(){
9906     //     (gl_Position = vec4(0.0, 0.0, 0.0, 0.0));
9907     //     mat3 _utmp = mat3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
9908     //     vec3 _ures = vec3(0.0, 0.0, 0.0);
9909     //     vec3 sbcd = vec3(_ures[_ui]);
9910     //     for (int _ui = 0; (_ures[((_utmp[_ui] += (((sbcd *= _ures[_ui]), (_ures[_ui] = sbcd.x)),
9911     //     sbcd)), _ui)], (_ui < 7)); )
9912     //     {
9913     //     }
9914     //     }
9915 
9916     constexpr char kVS[] = R"(
9917 void main()
9918 {
9919     mat3 tmp;
9920     vec3 res;
9921     for(int i; res[tmp[i]+=res[i]*=res[i],i],i<7;);
9922 })";
9923 
9924     GLuint shader = glCreateShader(GL_VERTEX_SHADER);
9925 
9926     const char *sourceArray[1] = {kVS};
9927     GLint lengths[1]           = {static_cast<GLint>(sizeof(kVS) - 1)};
9928     glShaderSource(shader, 1, sourceArray, lengths);
9929     glCompileShader(shader);
9930 
9931     GLint compileResult;
9932     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
9933     EXPECT_NE(compileResult, 0);
9934 }
9935 
9936 // Test that packing of excessive 3-column variables does not overflow the count of 3-column
9937 // variables in VariablePacker
TEST_P(WebGL2GLSLTest,ExcessiveMat3UniformPacking)9938 TEST_P(WebGL2GLSLTest, ExcessiveMat3UniformPacking)
9939 {
9940     std::ostringstream srcStream;
9941 
9942     srcStream << "#version 300 es\n";
9943     srcStream << "precision mediump float;\n";
9944     srcStream << "out vec4 finalColor;\n";
9945     srcStream << "in vec4 color;\n";
9946     srcStream << "uniform mat4 r[254];\n";
9947 
9948     srcStream << "uniform mat3 ";
9949     constexpr size_t kNumUniforms = 10000;
9950     for (size_t i = 0; i < kNumUniforms; ++i)
9951     {
9952         if (i > 0)
9953         {
9954             srcStream << ", ";
9955         }
9956         srcStream << "m3a_" << i << "[256]";
9957     }
9958     srcStream << ";\n";
9959 
9960     srcStream << "void main(void) { finalColor = color; }\n";
9961     std::string src = std::move(srcStream).str();
9962 
9963     GLuint shader = glCreateShader(GL_VERTEX_SHADER);
9964 
9965     const char *sourceArray[1] = {src.c_str()};
9966     GLint lengths[1]           = {static_cast<GLint>(src.length())};
9967     glShaderSource(shader, 1, sourceArray, lengths);
9968     glCompileShader(shader);
9969 
9970     GLint compileResult;
9971     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
9972     EXPECT_EQ(compileResult, 0);
9973 }
9974 
9975 // Test that a varying with a flat qualifier that is used as an operand of a folded ternary operator
9976 // is handled correctly.
TEST_P(GLSLTest_ES3,FlatVaryingUsedInFoldedTernary)9977 TEST_P(GLSLTest_ES3, FlatVaryingUsedInFoldedTernary)
9978 {
9979     constexpr char kVS[] = R"(#version 300 es
9980 
9981 in vec4 inputAttribute;
9982 
9983 flat out int v;
9984 
9985 void main()
9986 {
9987     v = 1;
9988     gl_Position = inputAttribute;
9989 })";
9990 
9991     constexpr char kFS[] = R"(#version 300 es
9992 
9993 precision highp float;
9994 out vec4 my_FragColor;
9995 
9996 flat in int v;
9997 
9998 void main()
9999 {
10000     my_FragColor = vec4(0, (true ? v : 0), 0, 1);
10001 })";
10002 
10003     ANGLE_GL_PROGRAM(program, kVS, kFS);
10004     drawQuad(program, "inputAttribute", 0.5f);
10005     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10006 }
10007 
10008 // Verify that the link error message from last link failure is cleared when the new link is
10009 // finished.
TEST_P(GLSLTest,ClearLinkErrorLog)10010 TEST_P(GLSLTest, ClearLinkErrorLog)
10011 {
10012     constexpr char kVS[] = R"(attribute vec4 vert_in;
10013 varying vec4 vert_out;
10014 void main()
10015 {
10016     gl_Position = vert_in;
10017     vert_out = vert_in;
10018 })";
10019 
10020     constexpr char kFS[] = R"(precision mediump float;
10021 varying vec4 frag_in;
10022 void main()
10023 {
10024     gl_FragColor = frag_in;
10025 })";
10026 
10027     GLuint vs = CompileShader(GL_VERTEX_SHADER, kVS);
10028     GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
10029 
10030     GLuint program = glCreateProgram();
10031 
10032     // The first time the program link fails because of lack of fragment shader.
10033     glAttachShader(program, vs);
10034     glLinkProgram(program);
10035     GLint linkStatus = GL_TRUE;
10036     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
10037     ASSERT_FALSE(linkStatus);
10038 
10039     const std::string lackOfFragmentShader = QueryErrorMessage(program);
10040     EXPECT_TRUE(lackOfFragmentShader != "");
10041 
10042     // The second time the program link fails because of the mismatch of the varying types.
10043     glAttachShader(program, fs);
10044     glLinkProgram(program);
10045     linkStatus = GL_TRUE;
10046     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
10047     ASSERT_FALSE(linkStatus);
10048 
10049     const std::string varyingTypeMismatch = QueryErrorMessage(program);
10050     EXPECT_TRUE(varyingTypeMismatch != "");
10051 
10052     EXPECT_EQ(std::string::npos, varyingTypeMismatch.find(lackOfFragmentShader));
10053 
10054     glDetachShader(program, vs);
10055     glDetachShader(program, fs);
10056     glDeleteShader(vs);
10057     glDeleteShader(fs);
10058     glDeleteProgram(program);
10059 
10060     ASSERT_GL_NO_ERROR();
10061 }
10062 
10063 // Verify that a valid program still draws correctly after a shader link error
TEST_P(GLSLTest,DrawAfterShaderLinkError)10064 TEST_P(GLSLTest, DrawAfterShaderLinkError)
10065 {
10066     constexpr char kVS[]    = R"(attribute vec4 position;
10067         varying vec4 vColor;
10068         void main()
10069         {
10070             vColor = vec4(0.0, 1.0, 0.0, 1.0);
10071             gl_Position = position;
10072         })";
10073     constexpr char kFS[]    = R"(precision mediump float;
10074         varying vec4 vColor;
10075         void main()
10076         {
10077             gl_FragColor = vColor;
10078         })";
10079     constexpr char kBadFS[] = R"(WILL NOT COMPILE;)";
10080 
10081     GLuint fsBad = glCreateShader(GL_FRAGMENT_SHADER);
10082 
10083     // Create bad fragment shader
10084     {
10085         const char *sourceArray[1] = {kBadFS};
10086         glShaderSource(fsBad, 1, sourceArray, nullptr);
10087         glCompileShader(fsBad);
10088 
10089         GLint compileResult;
10090         glGetShaderiv(fsBad, GL_COMPILE_STATUS, &compileResult);
10091         ASSERT_FALSE(compileResult);
10092     }
10093 
10094     ANGLE_GL_PROGRAM(program, kVS, kFS);
10095     GLuint fs = GetProgramShader(program, GL_FRAGMENT_SHADER);
10096 
10097     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
10098     glClear(GL_COLOR_BUFFER_BIT);
10099     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
10100 
10101     glUseProgram(program);
10102     GLint positionLocation              = glGetAttribLocation(program, "position");
10103     std::array<Vector3, 6> quadVertices = GetQuadVertices();
10104     for (Vector3 &vertex : quadVertices)
10105     {
10106         vertex.z() = 0.5f;
10107     }
10108     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
10109     glEnableVertexAttribArray(positionLocation);
10110     glDrawArrays(GL_TRIANGLES, 0, 6);
10111     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10112 
10113     glDetachShader(program, fs);
10114     glAttachShader(program, fsBad);
10115     glLinkProgram(program);
10116     GLint linkStatus = GL_TRUE;
10117     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
10118     ASSERT_FALSE(linkStatus);
10119 
10120     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
10121     glClear(GL_COLOR_BUFFER_BIT);
10122     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
10123 
10124     glDrawArrays(GL_TRIANGLES, 0, 6);
10125     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10126 }
10127 
10128 // Validate error messages when the link mismatch occurs on the type of a non-struct varying.
TEST_P(GLSLTest,ErrorMessageOfVaryingMismatch)10129 TEST_P(GLSLTest, ErrorMessageOfVaryingMismatch)
10130 {
10131     constexpr char kVS[] = R"(attribute vec4 inputAttribute;
10132 varying vec4 vertex_out;
10133 void main()
10134 {
10135     vertex_out = inputAttribute;
10136     gl_Position = inputAttribute;
10137 })";
10138 
10139     constexpr char kFS[] = R"(precision mediump float;
10140 varying float vertex_out;
10141 void main()
10142 {
10143     gl_FragColor = vec4(vertex_out, 0.0, 0.0, 1.0);
10144 })";
10145 
10146     validateComponentsInErrorMessage(kVS, kFS, "Types", "varying 'vertex_out'");
10147 }
10148 
10149 // Validate error messages when the link mismatch occurs on the name of a varying field.
TEST_P(GLSLTest_ES3,ErrorMessageOfVaryingStructFieldNameMismatch)10150 TEST_P(GLSLTest_ES3, ErrorMessageOfVaryingStructFieldNameMismatch)
10151 {
10152     constexpr char kVS[] = R"(#version 300 es
10153 in vec4 inputAttribute;
10154 struct S {
10155     float val1;
10156     vec4 val2;
10157 };
10158 out S vertex_out;
10159 void main()
10160 {
10161     vertex_out.val2 = inputAttribute;
10162     vertex_out.val1 = inputAttribute[0];
10163     gl_Position = inputAttribute;
10164 })";
10165 
10166     constexpr char kFS[] = R"(#version 300 es
10167 precision mediump float;
10168 struct S {
10169     float val1;
10170     vec4 val3;
10171 };
10172 in S vertex_out;
10173 layout (location = 0) out vec4 frag_out;
10174 void main()
10175 {
10176     frag_out = vec4(vertex_out.val1, 0.0, 0.0, 1.0);
10177 })";
10178 
10179     validateComponentsInErrorMessage(kVS, kFS, "Field names", "varying 'vertex_out'");
10180 }
10181 
10182 // Validate error messages when the link mismatch occurs on the type of a varying field.
TEST_P(GLSLTest_ES3,ErrorMessageOfVaryingStructFieldMismatch)10183 TEST_P(GLSLTest_ES3, ErrorMessageOfVaryingStructFieldMismatch)
10184 {
10185     constexpr char kVS[] = R"(#version 300 es
10186 in vec4 inputAttribute;
10187 struct S {
10188     float val1;
10189     vec4 val2;
10190 };
10191 out S vertex_out;
10192 void main()
10193 {
10194     vertex_out.val2 = inputAttribute;
10195     vertex_out.val1 = inputAttribute[0];
10196     gl_Position = inputAttribute;
10197 })";
10198 
10199     constexpr char kFS[] = R"(#version 300 es
10200 precision mediump float;
10201 struct S {
10202     float val1;
10203     vec2 val2;
10204 };
10205 in S vertex_out;
10206 layout (location = 0) out vec4 frag_out;
10207 void main()
10208 {
10209     frag_out = vec4(vertex_out.val1, 0.0, 0.0, 1.0);
10210 })";
10211 
10212     validateComponentsInErrorMessage(kVS, kFS, "Types",
10213                                      "varying 'vertex_out' member 'vertex_out.val2'");
10214 }
10215 
10216 // Validate error messages when the link mismatch occurs on the name of a struct member of a uniform
10217 // field.
TEST_P(GLSLTest,ErrorMessageOfLinkUniformStructFieldNameMismatch)10218 TEST_P(GLSLTest, ErrorMessageOfLinkUniformStructFieldNameMismatch)
10219 {
10220     constexpr char kVS[] = R"(
10221 struct T
10222 {
10223     vec2 t1;
10224     vec3 t2;
10225 };
10226 struct S {
10227     T val1;
10228     vec4 val2;
10229 };
10230 uniform S uni;
10231 
10232 attribute vec4 inputAttribute;
10233 varying vec4 vertex_out;
10234 void main()
10235 {
10236     vertex_out = uni.val2;
10237     gl_Position = inputAttribute;
10238 })";
10239 
10240     constexpr char kFS[] = R"(precision highp float;
10241 struct T
10242 {
10243     vec2 t1;
10244     vec3 t3;
10245 };
10246 struct S {
10247     T val1;
10248     vec4 val2;
10249 };
10250 uniform S uni;
10251 
10252 varying vec4 vertex_out;
10253 void main()
10254 {
10255     gl_FragColor = vec4(uni.val1.t1[0], 0.0, 0.0, 1.0);
10256 })";
10257 
10258     validateComponentsInErrorMessage(kVS, kFS, "Field names", "uniform 'uni' member 'uni.val1'");
10259 }
10260 
10261 // Validate error messages  when the link mismatch occurs on the type of a non-struct uniform block
10262 // field.
TEST_P(GLSLTest_ES3,ErrorMessageOfLinkInterfaceBlockFieldMismatch)10263 TEST_P(GLSLTest_ES3, ErrorMessageOfLinkInterfaceBlockFieldMismatch)
10264 {
10265     constexpr char kVS[] = R"(#version 300 es
10266 uniform S {
10267     vec2 val1;
10268     vec4 val2;
10269 } uni;
10270 
10271 in vec4 inputAttribute;
10272 out vec4 vertex_out;
10273 void main()
10274 {
10275     vertex_out = uni.val2;
10276     gl_Position = inputAttribute;
10277 })";
10278 
10279     constexpr char kFS[] = R"(#version 300 es
10280 precision highp float;
10281 uniform S {
10282     vec2 val1;
10283     vec3 val2;
10284 } uni;
10285 
10286 in vec4 vertex_out;
10287 layout (location = 0) out vec4 frag_out;
10288 void main()
10289 {
10290     frag_out = vec4(uni.val1[0], 0.0, 0.0, 1.0);
10291 })";
10292 
10293     validateComponentsInErrorMessage(kVS, kFS, "Types", "uniform block 'S' member 'S.val2'");
10294 }
10295 
10296 // Validate error messages  when the link mismatch occurs on the type of a member of a uniform block
10297 // struct field.
TEST_P(GLSLTest_ES3,ErrorMessageOfLinkInterfaceBlockStructFieldMismatch)10298 TEST_P(GLSLTest_ES3, ErrorMessageOfLinkInterfaceBlockStructFieldMismatch)
10299 {
10300     constexpr char kVS[] = R"(#version 300 es
10301 struct T
10302 {
10303     vec2 t1;
10304     vec3 t2;
10305 };
10306 uniform S {
10307     T val1;
10308     vec4 val2;
10309 } uni;
10310 
10311 in vec4 inputAttribute;
10312 out vec4 vertex_out;
10313 void main()
10314 {
10315     vertex_out = uni.val2;
10316     gl_Position = inputAttribute;
10317 })";
10318 
10319     constexpr char kFS[] = R"(#version 300 es
10320 precision highp float;
10321 struct T
10322 {
10323     vec2 t1;
10324     vec4 t2;
10325 };
10326 uniform S {
10327     T val1;
10328     vec4 val2;
10329 } uni;
10330 
10331 in vec4 vertex_out;
10332 layout (location = 0) out vec4 frag_out;
10333 void main()
10334 {
10335     frag_out = vec4(uni.val1.t1[0], 0.0, 0.0, 1.0);
10336 })";
10337 
10338     validateComponentsInErrorMessage(kVS, kFS, "Types", "uniform block 'S' member 'S.val1.t2'");
10339 }
10340 
10341 // Test a vertex shader that doesn't declare any varyings with a fragment shader that statically
10342 // uses a varying, but in a statement that gets trivially optimized out by the compiler.
TEST_P(GLSLTest_ES3,FragmentShaderStaticallyUsesVaryingMissingFromVertex)10343 TEST_P(GLSLTest_ES3, FragmentShaderStaticallyUsesVaryingMissingFromVertex)
10344 {
10345     constexpr char kVS[] = R"(#version 300 es
10346 precision mediump float;
10347 
10348 void main()
10349 {
10350     gl_Position = vec4(0, 1, 0, 1);
10351 })";
10352 
10353     constexpr char kFS[] = R"(#version 300 es
10354 precision mediump float;
10355 in float foo;
10356 out vec4 my_FragColor;
10357 
10358 void main()
10359 {
10360     if (false)
10361     {
10362         float unreferenced = foo;
10363     }
10364     my_FragColor = vec4(0, 1, 0, 1);
10365 })";
10366 
10367     validateComponentsInErrorMessage(kVS, kFS, "does not match any", "foo");
10368 }
10369 
10370 // Test a varying that is statically used but not active in the fragment shader.
TEST_P(GLSLTest_ES3,VaryingStaticallyUsedButNotActiveInFragmentShader)10371 TEST_P(GLSLTest_ES3, VaryingStaticallyUsedButNotActiveInFragmentShader)
10372 {
10373     constexpr char kVS[] = R"(#version 300 es
10374 precision mediump float;
10375 in vec4 iv;
10376 out vec4 v;
10377 void main()
10378 {
10379     gl_Position = iv;
10380     v = iv;
10381 })";
10382 
10383     constexpr char kFS[] = R"(#version 300 es
10384 precision mediump float;
10385 in vec4 v;
10386 out vec4 color;
10387 void main()
10388 {
10389     color = true ? vec4(0.0) : v;
10390 })";
10391 
10392     ANGLE_GL_PROGRAM(program, kVS, kFS);
10393 }
10394 
10395 // Test that linking varyings by location works.
TEST_P(GLSLTest_ES31,LinkVaryingsByLocation)10396 TEST_P(GLSLTest_ES31, LinkVaryingsByLocation)
10397 {
10398     constexpr char kVS[] = R"(#version 310 es
10399 precision highp float;
10400 in vec4 position;
10401 layout(location = 1) out vec4 shaderOutput;
10402 void main() {
10403     gl_Position = position;
10404     shaderOutput = vec4(0.0, 1.0, 0.0, 1.0);
10405 })";
10406 
10407     constexpr char kFS[] = R"(#version 310 es
10408 precision highp float;
10409 layout(location = 1) in vec4 shaderInput;
10410 out vec4 outColor;
10411 void main() {
10412     outColor = shaderInput;
10413 })";
10414 
10415     ANGLE_GL_PROGRAM(program, kVS, kFS);
10416     drawQuad(program, "position", 0.5f);
10417     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10418 }
10419 
10420 // Test nesting floor() calls with a large multiplier inside.
TEST_P(GLSLTest_ES3,NestedFloorWithLargeMultiplierInside)10421 TEST_P(GLSLTest_ES3, NestedFloorWithLargeMultiplierInside)
10422 {
10423     // D3D11 seems to ignore the floor() calls in this particular case, so one of the corners ends
10424     // up red. http://crbug.com/838885
10425     ANGLE_SKIP_TEST_IF(IsD3D11());
10426 
10427     constexpr char kFS[] = R"(#version 300 es
10428 precision highp float;
10429 out vec4 my_FragColor;
10430 void main()
10431 {
10432     vec2 coord = gl_FragCoord.xy / 500.0;
10433     my_FragColor = vec4(1, 0, 0, 1);
10434     if (coord.y + 0.1 > floor(1e-6 * floor(coord.x*4e5)))
10435     {
10436         my_FragColor = vec4(0, 1, 0, 1);
10437     }
10438 })";
10439 
10440     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
10441     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
10442     // Verify that all the corners of the rendered result are green.
10443     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10444     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
10445     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, 0, GLColor::green);
10446     EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() - 1, GLColor::green);
10447 }
10448 
10449 // Verify that a link error is generated when the sum of the number of active image uniforms and
10450 // active shader storage blocks in a rendering pipeline exceeds
10451 // GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES.
TEST_P(GLSLTest_ES31,ExceedCombinedShaderOutputResourcesInVSAndFS)10452 TEST_P(GLSLTest_ES31, ExceedCombinedShaderOutputResourcesInVSAndFS)
10453 {
10454     // TODO(jiawei.shao@intel.com): enable this test when shader storage buffer is supported on
10455     // D3D11 back-ends.
10456     ANGLE_SKIP_TEST_IF(IsD3D11());
10457 
10458     GLint maxVertexShaderStorageBlocks;
10459     GLint maxVertexImageUniforms;
10460     GLint maxFragmentShaderStorageBlocks;
10461     GLint maxFragmentImageUniforms;
10462     GLint maxCombinedShaderStorageBlocks;
10463     GLint maxCombinedImageUniforms;
10464     glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &maxVertexShaderStorageBlocks);
10465     glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &maxVertexImageUniforms);
10466     glGetIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &maxFragmentShaderStorageBlocks);
10467     glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &maxFragmentImageUniforms);
10468     glGetIntegerv(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, &maxCombinedShaderStorageBlocks);
10469     glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS, &maxCombinedImageUniforms);
10470 
10471     ASSERT_GE(maxCombinedShaderStorageBlocks, maxVertexShaderStorageBlocks);
10472     ASSERT_GE(maxCombinedShaderStorageBlocks, maxFragmentShaderStorageBlocks);
10473     ASSERT_GE(maxCombinedImageUniforms, maxVertexImageUniforms);
10474     ASSERT_GE(maxCombinedImageUniforms, maxFragmentImageUniforms);
10475 
10476     GLint vertexSSBOs   = maxVertexShaderStorageBlocks;
10477     GLint fragmentSSBOs = maxFragmentShaderStorageBlocks;
10478     // Limit the sum of ssbos in vertex and fragment shaders to maxCombinedShaderStorageBlocks.
10479     if (vertexSSBOs + fragmentSSBOs > maxCombinedShaderStorageBlocks)
10480     {
10481         fragmentSSBOs = maxCombinedShaderStorageBlocks - vertexSSBOs;
10482     }
10483 
10484     GLint vertexImages   = maxVertexImageUniforms;
10485     GLint fragmentImages = maxFragmentImageUniforms;
10486     // Limit the sum of images in vertex and fragment shaders to maxCombinedImageUniforms.
10487     if (vertexImages + fragmentImages > maxCombinedImageUniforms)
10488     {
10489         vertexImages = maxCombinedImageUniforms - fragmentImages;
10490     }
10491 
10492     GLint maxDrawBuffers;
10493     glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
10494 
10495     GLint maxCombinedShaderOutputResources;
10496     glGetIntegerv(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, &maxCombinedShaderOutputResources);
10497     ASSERT_GL_NO_ERROR();
10498 
10499     ANGLE_SKIP_TEST_IF(vertexSSBOs + fragmentSSBOs + vertexImages + fragmentImages +
10500                            maxDrawBuffers <=
10501                        maxCombinedShaderOutputResources);
10502 
10503     std::ostringstream vertexStream;
10504     vertexStream << "#version 310 es\n";
10505     for (int i = 0; i < vertexSSBOs; ++i)
10506     {
10507         vertexStream << "layout(shared, binding = " << i << ") buffer blockName" << i
10508                      << "{\n"
10509                         "    float data;\n"
10510                         "} ssbo"
10511                      << i << ";\n";
10512     }
10513     vertexStream << "layout(r32f, binding = 0) uniform highp image2D imageArray[" << vertexImages
10514                  << "];\n";
10515     vertexStream << "void main()\n"
10516                     "{\n"
10517                     "    float val = 0.1;\n"
10518                     "    vec4 val2 = vec4(0.0);\n";
10519     for (int i = 0; i < vertexSSBOs; ++i)
10520     {
10521         vertexStream << "    val += ssbo" << i << ".data; \n";
10522     }
10523     for (int i = 0; i < vertexImages; ++i)
10524     {
10525         vertexStream << "    val2 += imageLoad(imageArray[" << i << "], ivec2(0, 0)); \n";
10526     }
10527     vertexStream << "    gl_Position = vec4(val, val2);\n"
10528                     "}\n";
10529 
10530     std::ostringstream fragmentStream;
10531     fragmentStream << "#version 310 es\n" << "precision highp float;\n";
10532     for (int i = 0; i < fragmentSSBOs; ++i)
10533     {
10534         fragmentStream << "layout(shared, binding = " << i << ") buffer blockName" << i
10535                        << "{\n"
10536                           "    float data;\n"
10537                           "} ssbo"
10538                        << i << ";\n";
10539     }
10540     fragmentStream << "layout(r32f, binding = 0) uniform highp image2D imageArray["
10541                    << fragmentImages << "];\n";
10542     fragmentStream << "layout (location = 0) out vec4 foutput[" << maxDrawBuffers << "];\n";
10543 
10544     fragmentStream << "void main()\n"
10545                       "{\n"
10546                       "    float val = 0.1;\n"
10547                       "    vec4 val2 = vec4(0.0);\n";
10548     for (int i = 0; i < fragmentSSBOs; ++i)
10549     {
10550         fragmentStream << "    val += ssbo" << i << ".data; \n";
10551     }
10552     for (int i = 0; i < fragmentImages; ++i)
10553     {
10554         fragmentStream << "    val2 += imageLoad(imageArray[" << i << "], ivec2(0, 0)); \n";
10555     }
10556     for (int i = 0; i < maxDrawBuffers; ++i)
10557     {
10558         fragmentStream << "    foutput[" << i << "] = vec4(val, val2);\n";
10559     }
10560     fragmentStream << "}\n";
10561 
10562     GLuint program = CompileProgram(vertexStream.str().c_str(), fragmentStream.str().c_str());
10563     EXPECT_EQ(0u, program);
10564 
10565     ASSERT_GL_NO_ERROR();
10566 }
10567 
10568 // Test that assigning an assignment expression to a swizzled vector field in a user-defined
10569 // function works correctly.
TEST_P(GLSLTest_ES3,AssignToSwizzled)10570 TEST_P(GLSLTest_ES3, AssignToSwizzled)
10571 {
10572     constexpr char kFS[] = R"(#version 300 es
10573 precision highp float;
10574 out vec4 my_FragColor;
10575 
10576 uniform float uzero;
10577 
10578 vec3 fun(float s, float v)
10579 {
10580     vec3 r = vec3(0);
10581     if (s < 1.0) {
10582         r.x = r.y = r.z = v;
10583         return r;
10584     }
10585     return r;
10586 }
10587 
10588 void main()
10589 {
10590     my_FragColor.a = 1.0;
10591     my_FragColor.rgb = fun(uzero, 1.0);
10592 })";
10593 
10594     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
10595     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
10596     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
10597 }
10598 
10599 // Similar to AssignToSwizzled, but uses other assignment operators than `=`.
TEST_P(GLSLTest_ES3,AssignToSwizzled2)10600 TEST_P(GLSLTest_ES3, AssignToSwizzled2)
10601 {
10602     constexpr char kFS[] = R"(#version 300 es
10603 precision highp float;
10604 out vec4 my_FragColor;
10605 
10606 uniform float uzero;
10607 
10608 vec3 fun(float s, float v)
10609 {
10610     vec3 r = vec3(0.125, 0.5, 0.);
10611     if (s < 1.0) {
10612         r.x /= r.y *= r.z += v;
10613         return r;
10614     }
10615     return r;
10616 }
10617 
10618 void main()
10619 {
10620     my_FragColor.a = 1.0;
10621     my_FragColor.rgb = fun(uzero, 1.0);
10622 })";
10623 
10624     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
10625     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
10626     EXPECT_PIXEL_NEAR(0, 0, 63, 127, 255, 255, 1);
10627 }
10628 
10629 // Test that swizzled vector to bool cast works correctly.
TEST_P(GLSLTest_ES3,SwizzledToBoolCoercion)10630 TEST_P(GLSLTest_ES3, SwizzledToBoolCoercion)
10631 {
10632     constexpr char kFS[] = R"(#version 300 es
10633 precision highp float;
10634 out vec4 o;
10635 uniform vec2 u;
10636 void main()
10637 {
10638     bvec2 b = bvec2(u.yx);
10639     if (b.x&&!b.y)
10640         o = vec4(1.0);
10641 })";
10642     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
10643     glUseProgram(program);
10644     GLint uloc = glGetUniformLocation(program, "u");
10645     ASSERT_NE(uloc, -1);
10646     glUniform2f(uloc, 0, 1);
10647     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
10648     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
10649 }
10650 
10651 // Test a fragment shader that returns inside if (that being the only branch that actually gets
10652 // executed). Regression test for http://anglebug.com/42261034
TEST_P(GLSLTest,IfElseIfAndReturn)10653 TEST_P(GLSLTest, IfElseIfAndReturn)
10654 {
10655     constexpr char kVS[] = R"(attribute vec4 a_position;
10656 varying vec2 vPos;
10657 void main()
10658 {
10659     gl_Position = a_position;
10660     vPos = a_position.xy;
10661 })";
10662 
10663     constexpr char kFS[] = R"(precision mediump float;
10664 varying vec2 vPos;
10665 void main()
10666 {
10667     if (vPos.x < 1.0) // This colors the whole canvas green
10668     {
10669         gl_FragColor = vec4(0, 1, 0, 1);
10670         return;
10671     }
10672     else if (vPos.x < 1.1) // This should have no effect
10673     {
10674         gl_FragColor = vec4(1, 0, 0, 1);
10675     }
10676 })";
10677 
10678     ANGLE_GL_PROGRAM(program, kVS, kFS);
10679     drawQuad(program, "a_position", 0.5f);
10680     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10681 }
10682 
10683 // Test that if-else blocks whose contents get pruned due to compile-time constant conditions work.
TEST_P(GLSLTest,IfElsePrunedBlocks)10684 TEST_P(GLSLTest, IfElsePrunedBlocks)
10685 {
10686     constexpr char kFS[] = R"(precision mediump float;
10687 uniform float u;
10688 void main()
10689 {
10690     // if with only a pruned true block
10691     if (u > 0.0)
10692         if (false) discard;
10693 
10694     // if with a pruned true block and a false block
10695     if (u > 0.0)
10696     {
10697         if (false) discard;
10698     }
10699     else
10700         ;
10701 
10702     // if with a true block and a pruned false block
10703     if (u > 0.0)
10704         ;
10705     else
10706         if (false) discard;
10707 
10708     // if with a pruned true block and a pruned false block
10709     if (u > 0.0)
10710     {
10711         if (false) discard;
10712     }
10713     else
10714         if (false) discard;
10715 
10716     gl_FragColor = vec4(0, 1, 0, 1);
10717 })";
10718 
10719     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
10720     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
10721     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10722 }
10723 
10724 // Tests that PointCoord behaves the same betweeen a user FBO and the back buffer.
TEST_P(GLSLTest,PointCoordConsistency)10725 TEST_P(GLSLTest, PointCoordConsistency)
10726 {
10727     constexpr char kPointCoordVS[] = R"(attribute vec2 position;
10728 uniform vec2 viewportSize;
10729 void main()
10730 {
10731    gl_Position = vec4(position, 0, 1);
10732    gl_PointSize = viewportSize.x;
10733 })";
10734 
10735     constexpr char kPointCoordFS[] = R"(void main()
10736 {
10737     gl_FragColor = vec4(gl_PointCoord.xy, 0, 1);
10738 })";
10739 
10740     ANGLE_GL_PROGRAM(program, kPointCoordVS, kPointCoordFS);
10741     glUseProgram(program);
10742 
10743     GLint uniLoc = glGetUniformLocation(program, "viewportSize");
10744     ASSERT_NE(-1, uniLoc);
10745     glUniform2f(uniLoc, static_cast<GLfloat>(getWindowWidth()),
10746                 static_cast<GLfloat>(getWindowHeight()));
10747 
10748     // Draw to backbuffer.
10749     glClear(GL_COLOR_BUFFER_BIT);
10750     glDrawArrays(GL_POINTS, 0, 1);
10751     ASSERT_GL_NO_ERROR();
10752 
10753     std::vector<GLColor> backbufferData(getWindowWidth() * getWindowHeight());
10754     glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
10755                  backbufferData.data());
10756 
10757     GLTexture tex;
10758     glBindTexture(GL_TEXTURE_2D, tex);
10759     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
10760                  GL_UNSIGNED_BYTE, nullptr);
10761 
10762     GLFramebuffer fbo;
10763     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
10764     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
10765     ASSERT_GL_NO_ERROR();
10766     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
10767 
10768     // Draw to user FBO.
10769     glClear(GL_COLOR_BUFFER_BIT);
10770     glDrawArrays(GL_POINTS, 0, 1);
10771     ASSERT_GL_NO_ERROR();
10772 
10773     std::vector<GLColor> userFBOData(getWindowWidth() * getWindowHeight());
10774     glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
10775                  userFBOData.data());
10776 
10777     ASSERT_GL_NO_ERROR();
10778     ASSERT_EQ(userFBOData.size(), backbufferData.size());
10779     EXPECT_EQ(userFBOData, backbufferData);
10780 }
10781 
SubrectEquals(const std::vector<GLColor> & bigArray,const std::vector<GLColor> & smallArray,int bigSize,int offset,int smallSize)10782 bool SubrectEquals(const std::vector<GLColor> &bigArray,
10783                    const std::vector<GLColor> &smallArray,
10784                    int bigSize,
10785                    int offset,
10786                    int smallSize)
10787 {
10788     int badPixels = 0;
10789     for (int y = 0; y < smallSize; y++)
10790     {
10791         for (int x = 0; x < smallSize; x++)
10792         {
10793             int bigOffset   = (y + offset) * bigSize + x + offset;
10794             int smallOffset = y * smallSize + x;
10795             if (bigArray[bigOffset] != smallArray[smallOffset])
10796                 badPixels++;
10797         }
10798     }
10799     return badPixels == 0;
10800 }
10801 
10802 // Tests that FragCoord behaves the same betweeen a user FBO and the back buffer.
TEST_P(GLSLTest,FragCoordConsistency)10803 TEST_P(GLSLTest, FragCoordConsistency)
10804 {
10805     constexpr char kFragCoordShader[] = R"(uniform mediump vec2 viewportSize;
10806 void main()
10807 {
10808     gl_FragColor = vec4(gl_FragCoord.xy / viewportSize, 0, 1);
10809 })";
10810 
10811     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragCoordShader);
10812     glUseProgram(program);
10813 
10814     GLint uniLoc = glGetUniformLocation(program, "viewportSize");
10815     ASSERT_NE(-1, uniLoc);
10816     glUniform2f(uniLoc, static_cast<GLfloat>(getWindowWidth()),
10817                 static_cast<GLfloat>(getWindowHeight()));
10818 
10819     // Draw to backbuffer.
10820     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
10821     ASSERT_GL_NO_ERROR();
10822 
10823     std::vector<GLColor> backbufferData(getWindowWidth() * getWindowHeight());
10824     glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
10825                  backbufferData.data());
10826 
10827     GLTexture tex;
10828     glBindTexture(GL_TEXTURE_2D, tex);
10829     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
10830                  GL_UNSIGNED_BYTE, nullptr);
10831 
10832     GLFramebuffer fbo;
10833     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
10834     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
10835     ASSERT_GL_NO_ERROR();
10836     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
10837 
10838     // Draw to user FBO.
10839     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
10840     ASSERT_GL_NO_ERROR();
10841 
10842     std::vector<GLColor> userFBOData(getWindowWidth() * getWindowHeight());
10843     glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
10844                  userFBOData.data());
10845 
10846     ASSERT_GL_NO_ERROR();
10847     ASSERT_EQ(userFBOData.size(), backbufferData.size());
10848     EXPECT_EQ(userFBOData, backbufferData)
10849         << "FragCoord should be the same to default and user FBO";
10850 
10851     // Repeat the same test but with a smaller viewport.
10852     ASSERT_EQ(getWindowHeight(), getWindowWidth());
10853     const int kQuarterSize = getWindowWidth() >> 2;
10854     glViewport(kQuarterSize, kQuarterSize, kQuarterSize * 2, kQuarterSize * 2);
10855 
10856     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
10857     glClear(GL_COLOR_BUFFER_BIT);
10858     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
10859 
10860     std::vector<GLColor> userFBOViewportData(kQuarterSize * kQuarterSize * 4);
10861     glReadPixels(kQuarterSize, kQuarterSize, kQuarterSize * 2, kQuarterSize * 2, GL_RGBA,
10862                  GL_UNSIGNED_BYTE, userFBOViewportData.data());
10863 
10864     glBindFramebuffer(GL_FRAMEBUFFER, 0);
10865     glClear(GL_COLOR_BUFFER_BIT);
10866     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
10867 
10868     std::vector<GLColor> defaultFBOViewportData(kQuarterSize * kQuarterSize * 4);
10869     glReadPixels(kQuarterSize, kQuarterSize, kQuarterSize * 2, kQuarterSize * 2, GL_RGBA,
10870                  GL_UNSIGNED_BYTE, defaultFBOViewportData.data());
10871     ASSERT_GL_NO_ERROR();
10872     EXPECT_EQ(userFBOViewportData, defaultFBOViewportData)
10873         << "FragCoord should be the same to default and user FBO even with a custom viewport";
10874 
10875     // Check that the subrectangles are the same between the viewport and non-viewport modes.
10876     EXPECT_TRUE(SubrectEquals(userFBOData, userFBOViewportData, getWindowWidth(), kQuarterSize,
10877                               kQuarterSize * 2));
10878     EXPECT_TRUE(SubrectEquals(backbufferData, defaultFBOViewportData, getWindowWidth(),
10879                               kQuarterSize, kQuarterSize * 2));
10880 }
10881 
10882 // Ensure that using defined in a macro works in this simple case. This mirrors a dEQP test.
TEST_P(GLSLTest,DefinedInMacroSucceeds)10883 TEST_P(GLSLTest, DefinedInMacroSucceeds)
10884 {
10885     constexpr char kVS[] = R"(precision mediump float;
10886 attribute highp vec4 position;
10887 varying vec2 out0;
10888 
10889 void main()
10890 {
10891 #define AAA defined(BBB)
10892 
10893 #if !AAA
10894     out0 = vec2(0.0, 1.0);
10895 #else
10896     out0 = vec2(1.0, 0.0);
10897 #endif
10898     gl_Position = position;
10899 })";
10900 
10901     constexpr char kFS[] = R"(precision mediump float;
10902 varying vec2 out0;
10903 void main()
10904 {
10905     gl_FragColor = vec4(out0, 0, 1);
10906 })";
10907 
10908     ANGLE_GL_PROGRAM(program, kVS, kFS);
10909     drawQuad(program, "position", 0.5f);
10910     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10911 }
10912 
10913 // Validate the defined operator is evaluated when the macro is called, not when defined.
TEST_P(GLSLTest,DefinedInMacroWithUndef)10914 TEST_P(GLSLTest, DefinedInMacroWithUndef)
10915 {
10916     constexpr char kVS[] = R"(precision mediump float;
10917 attribute highp vec4 position;
10918 varying vec2 out0;
10919 
10920 void main()
10921 {
10922 #define BBB 1
10923 #define AAA defined(BBB)
10924 #undef BBB
10925 
10926 #if AAA
10927     out0 = vec2(1.0, 0.0);
10928 #else
10929     out0 = vec2(0.0, 1.0);
10930 #endif
10931     gl_Position = position;
10932 })";
10933 
10934     constexpr char kFS[] = R"(precision mediump float;
10935 varying vec2 out0;
10936 void main()
10937 {
10938     gl_FragColor = vec4(out0, 0, 1);
10939 })";
10940 
10941     ANGLE_GL_PROGRAM(program, kVS, kFS);
10942     drawQuad(program, "position", 0.5f);
10943     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10944 }
10945 
10946 // Validate the defined operator is evaluated when the macro is called, not when defined.
TEST_P(GLSLTest,DefinedAfterMacroUsage)10947 TEST_P(GLSLTest, DefinedAfterMacroUsage)
10948 {
10949     constexpr char kVS[] = R"(precision mediump float;
10950 attribute highp vec4 position;
10951 varying vec2 out0;
10952 
10953 void main()
10954 {
10955 #define AAA defined(BBB)
10956 #define BBB 1
10957 
10958 #if AAA
10959     out0 = vec2(0.0, 1.0);
10960 #else
10961     out0 = vec2(1.0, 0.0);
10962 #endif
10963     gl_Position = position;
10964 })";
10965 
10966     constexpr char kFS[] = R"(precision mediump float;
10967 varying vec2 out0;
10968 void main()
10969 {
10970     gl_FragColor = vec4(out0, 0, 1);
10971 })";
10972 
10973     ANGLE_GL_PROGRAM(program, kVS, kFS);
10974     drawQuad(program, "position", 0.5f);
10975     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10976 }
10977 
10978 // Test generating "defined" by concatenation when a macro is called. This is not allowed.
TEST_P(GLSLTest,DefinedInMacroConcatenationNotAllowed)10979 TEST_P(GLSLTest, DefinedInMacroConcatenationNotAllowed)
10980 {
10981     constexpr char kVS[] = R"(precision mediump float;
10982 attribute highp vec4 position;
10983 varying vec2 out0;
10984 
10985 void main()
10986 {
10987 #define BBB 1
10988 #define AAA(defi, ned) defi ## ned(BBB)
10989 
10990 #if AAA(defi, ned)
10991     out0 = vec2(0.0, 1.0);
10992 #else
10993     out0 = vec2(1.0, 0.0);
10994 #endif
10995     gl_Position = position;
10996 })";
10997 
10998     constexpr char kFS[] = R"(precision mediump float;
10999 varying vec2 out0;
11000 void main()
11001 {
11002     gl_FragColor = vec4(out0, 0, 1);
11003 })";
11004 
11005     GLuint program = CompileProgram(kVS, kFS);
11006     EXPECT_EQ(0u, program);
11007     glDeleteProgram(program);
11008 }
11009 
11010 // Test using defined in a macro parameter name. This is not allowed.
TEST_P(GLSLTest,DefinedAsParameterNameNotAllowed)11011 TEST_P(GLSLTest, DefinedAsParameterNameNotAllowed)
11012 {
11013     constexpr char kVS[] = R"(precision mediump float;
11014 attribute highp vec4 position;
11015 varying vec2 out0;
11016 
11017 void main()
11018 {
11019 #define BBB 1
11020 #define AAA(defined) defined(BBB)
11021 
11022 #if AAA(defined)
11023     out0 = vec2(0.0, 1.0);
11024 #else
11025     out0 = vec2(1.0, 0.0);
11026 #endif
11027     gl_Position = position;
11028 })";
11029 
11030     constexpr char kFS[] = R"(precision mediump float;
11031 varying vec2 out0;
11032 void main()
11033 {
11034     gl_FragColor = vec4(out0, 0, 1);
11035 })";
11036 
11037     GLuint program = CompileProgram(kVS, kFS);
11038     EXPECT_EQ(0u, program);
11039     glDeleteProgram(program);
11040 }
11041 
11042 // Ensure that defined in a macro is no accepted in WebGL.
TEST_P(WebGLGLSLTest,DefinedInMacroFails)11043 TEST_P(WebGLGLSLTest, DefinedInMacroFails)
11044 {
11045     constexpr char kVS[] = R"(precision mediump float;
11046 attribute highp vec4 position;
11047 varying float out0;
11048 
11049 void main()
11050 {
11051 #define AAA defined(BBB)
11052 
11053 #if !AAA
11054     out0 = 1.0;
11055 #else
11056     out0 = 0.0;
11057 #endif
11058     gl_Position = dEQP_Position;
11059 })";
11060 
11061     constexpr char kFS[] = R"(precision mediump float;
11062 varying float out0;
11063 void main()
11064 {
11065     gl_FragColor = vec4(out0, 0, 0, 1);
11066 })";
11067 
11068     GLuint program = CompileProgram(kVS, kFS);
11069     EXPECT_EQ(0u, program);
11070     glDeleteProgram(program);
11071 }
11072 
11073 // Simple test using a define macro in WebGL.
TEST_P(WebGLGLSLTest,DefinedGLESSymbol)11074 TEST_P(WebGLGLSLTest, DefinedGLESSymbol)
11075 {
11076     constexpr char kVS[] = R"(void main()
11077 {
11078     gl_Position = vec4(1, 0, 0, 1);
11079 })";
11080 
11081     constexpr char kFS[] = R"(#if defined(GL_ES)
11082 precision mediump float;
11083 void main()
11084 {
11085     gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
11086 }
11087 #else
11088 foo
11089 #endif
11090 )";
11091 
11092     ANGLE_GL_PROGRAM(program, kVS, kFS);
11093 }
11094 
11095 // Test that inactive output variables compile ok in combination with initOutputVariables
11096 // (which is enabled on WebGL).
TEST_P(WebGL2GLSLTest,InactiveOutput)11097 TEST_P(WebGL2GLSLTest, InactiveOutput)
11098 {
11099     constexpr char kFS[] = R"(#version 300 es
11100 precision highp float;
11101 out vec4 _cassgl_2_;
11102 void main()
11103 {
11104 })";
11105 
11106     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
11107     EXPECT_NE(shader, 0u);
11108 }
11109 
11110 // Test that clamp applied on non-literal indices is correct on es 100 shaders.
TEST_P(GLSLTest,ValidIndexClampES100)11111 TEST_P(GLSLTest, ValidIndexClampES100)
11112 {
11113     // http://anglebug.com/42264558
11114     ANGLE_SKIP_TEST_IF(IsD3D9());
11115 
11116     constexpr char kFS[] = R"(
11117 precision mediump float;
11118 uniform int u;
11119 uniform mat4 m[2];
11120 void main()
11121 {
11122     gl_FragColor = vec4(m[u][1].xyz, 1);
11123 }
11124 )";
11125 
11126     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
11127     glUseProgram(program);
11128 
11129     GLint uniformLocation = glGetUniformLocation(program, "u");
11130     ASSERT_NE(-1, uniformLocation);
11131 
11132     GLint matrixLocation = glGetUniformLocation(program, "m");
11133     ASSERT_NE(matrixLocation, -1);
11134     const std::array<GLfloat, 32> mValue = {{0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f,
11135                                              0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f,
11136                                              1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
11137                                              0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}};
11138     glUniformMatrix4fv(matrixLocation, 2, false, mValue.data());
11139 
11140     glUniform1i(uniformLocation, 1);
11141     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
11142     EXPECT_GL_NO_ERROR();
11143 
11144     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
11145 }
11146 
11147 // Test that clamp applied on non-literal indices is correct on es 300 shaders.
TEST_P(GLSLTest_ES3,ValidIndexClampES300)11148 TEST_P(GLSLTest_ES3, ValidIndexClampES300)
11149 {
11150     constexpr char kFS[] = R"(#version 300 es
11151 precision mediump float;
11152 out vec4 color;
11153 uniform int u;
11154 mat4 m[4] = mat4[4](mat4(0.25), mat4(0.5), mat4(1), mat4(0.75));
11155 void main()
11156 {
11157     color = vec4(m[u][2].xyz, 1);
11158 }
11159 )";
11160 
11161     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11162     glUseProgram(program);
11163 
11164     GLint uniformLocation = glGetUniformLocation(program, "u");
11165     ASSERT_NE(-1, uniformLocation);
11166 
11167     glUniform1i(uniformLocation, 2);
11168     EXPECT_GL_NO_ERROR();
11169     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
11170     EXPECT_GL_NO_ERROR();
11171 
11172     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
11173 }
11174 
11175 // Tests constant folding of non-square 'matrixCompMult'.
TEST_P(GLSLTest_ES3,NonSquareMatrixCompMult)11176 TEST_P(GLSLTest_ES3, NonSquareMatrixCompMult)
11177 {
11178     constexpr char kFS[] = R"(#version 300 es
11179 precision mediump float;
11180 
11181 const mat4x2 matA = mat4x2(2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0);
11182 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);
11183 
11184 out vec4 color;
11185 
11186 void main()
11187 {
11188     mat4x2 result = matrixCompMult(matA, matB);
11189     vec2 vresult = result * vec4(1.0, 1.0, 1.0, 1.0);
11190     if (vresult == vec2(4.0, 4.0))
11191     {
11192         color = vec4(0.0, 1.0, 0.0, 1.0);
11193     }
11194     else
11195     {
11196         color = vec4(1.0, 0.0, 0.0, 1.0);
11197     }
11198 })";
11199 
11200     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11201     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
11202     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
11203 }
11204 
11205 // Test initializing an array with the same name of previously declared array
TEST_P(GLSLTest_ES3,InitSameNameArray)11206 TEST_P(GLSLTest_ES3, InitSameNameArray)
11207 {
11208     constexpr char kFS[] = R"(#version 300 es
11209       precision highp float;
11210       out vec4 my_FragColor;
11211 
11212       void main()
11213       {
11214           float arr[2] = float[2](1.0, 1.0);
11215           {
11216               float arr[2] = arr;
11217               my_FragColor = vec4(0.0, arr[0], 0.0, arr[1]);
11218           }
11219       })";
11220 
11221     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11222     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
11223     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
11224 }
11225 
11226 // Tests using gl_FragData[0] instead of gl_FragColor.
TEST_P(GLSLTest,FragData)11227 TEST_P(GLSLTest, FragData)
11228 {
11229     constexpr char kFS[] = R"(void main() { gl_FragData[0] = vec4(1, 0, 0, 1); })";
11230     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
11231     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
11232     EXPECT_GL_NO_ERROR();
11233     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
11234 }
11235 
11236 // Tests using gl_FragData[0] instead of gl_FragColor with GL_SAMPLE_ALPHA_TO_COVERAGE
11237 // Regression test for https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/5520
TEST_P(GLSLTest,FragData_AlphaToCoverage)11238 TEST_P(GLSLTest, FragData_AlphaToCoverage)
11239 {
11240     constexpr char kFS[] = R"(void main() { gl_FragData[0] = vec4(1, 0, 0, 1); })";
11241     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
11242     glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
11243     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
11244     EXPECT_GL_NO_ERROR();
11245     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
11246 }
11247 
11248 // Test angle can handle big initial stack size with dynamic stack allocation.
TEST_P(GLSLTest,MemoryExhaustedTest)11249 TEST_P(GLSLTest, MemoryExhaustedTest)
11250 {
11251     GLuint program =
11252         CompileProgram(essl1_shaders::vs::Simple(), BuildBigInitialStackShader(36).c_str());
11253     EXPECT_NE(0u, program);
11254 }
11255 
11256 // Test that inactive samplers in structs don't cause any errors.
TEST_P(GLSLTest,InactiveSamplersInStruct)11257 TEST_P(GLSLTest, InactiveSamplersInStruct)
11258 {
11259     constexpr char kVS[] = R"(attribute vec4 a_position;
11260 void main() {
11261   gl_Position = a_position;
11262 })";
11263 
11264     constexpr char kFS[] = R"(precision highp float;
11265 struct S
11266 {
11267     vec4 v;
11268     sampler2D t[10];
11269 };
11270 uniform S s;
11271 void main() {
11272   gl_FragColor = s.v;
11273 })";
11274 
11275     ANGLE_GL_PROGRAM(program, kVS, kFS);
11276 
11277     drawQuad(program, "a_position", 0.5f);
11278 }
11279 
11280 // Helper functions for MixedRowAndColumnMajorMatrices* tests
11281 
11282 // Round up to alignment, assuming it's a power of 2
RoundUpPow2(uint32_t value,uint32_t alignment)11283 uint32_t RoundUpPow2(uint32_t value, uint32_t alignment)
11284 {
11285     return (value + alignment - 1) & ~(alignment - 1);
11286 }
11287 
CreateOutputBuffer(GLBuffer * buffer,uint32_t binding)11288 void CreateOutputBuffer(GLBuffer *buffer, uint32_t binding)
11289 {
11290     unsigned int outputInitData = 0;
11291     glBindBuffer(GL_SHADER_STORAGE_BUFFER, *buffer);
11292     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
11293     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, binding, *buffer);
11294     EXPECT_GL_NO_ERROR();
11295 }
11296 
11297 // Fill provided buffer with matrices based on the given dimensions.  The buffer should be large
11298 // 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)11299 uint32_t FillBuffer(const std::pair<uint32_t, uint32_t> matrixDims[],
11300                     const bool matrixIsColMajor[],
11301                     size_t matrixCount,
11302                     float data[],
11303                     bool isStd430,
11304                     bool isTransposed)
11305 {
11306     size_t offset = 0;
11307     for (size_t m = 0; m < matrixCount; ++m)
11308     {
11309         uint32_t cols   = matrixDims[m].first;
11310         uint32_t rows   = matrixDims[m].second;
11311         bool isColMajor = matrixIsColMajor[m] != isTransposed;
11312 
11313         uint32_t arraySize              = isColMajor ? cols : rows;
11314         uint32_t arrayElementComponents = isColMajor ? rows : cols;
11315         // Note: stride is generally 4 with std140, except for scalar and gvec2 types (which
11316         // MixedRowAndColumnMajorMatrices* tests don't use).  With std430, small matrices can have
11317         // a stride of 2 between rows/columns.
11318         uint32_t stride = isStd430 ? RoundUpPow2(arrayElementComponents, 2) : 4;
11319 
11320         offset = RoundUpPow2(offset, stride);
11321 
11322         for (uint32_t i = 0; i < arraySize; ++i)
11323         {
11324             for (uint32_t c = 0; c < arrayElementComponents; ++c)
11325             {
11326                 uint32_t row = isColMajor ? c : i;
11327                 uint32_t col = isColMajor ? i : c;
11328 
11329                 data[offset + i * stride + c] = col * 4 + row;
11330             }
11331         }
11332 
11333         offset += arraySize * stride;
11334     }
11335     return offset;
11336 }
11337 
11338 // Initialize and bind the buffer.
11339 template <typename T>
InitBuffer(GLuint program,const char * name,GLuint buffer,uint32_t bindingIndex,const T data[],uint32_t dataSize,bool isUniform)11340 void InitBuffer(GLuint program,
11341                 const char *name,
11342                 GLuint buffer,
11343                 uint32_t bindingIndex,
11344                 const T data[],
11345                 uint32_t dataSize,
11346                 bool isUniform)
11347 {
11348     GLenum bindPoint = isUniform ? GL_UNIFORM_BUFFER : GL_SHADER_STORAGE_BUFFER;
11349 
11350     glBindBufferBase(bindPoint, bindingIndex, buffer);
11351     glBufferData(bindPoint, dataSize * sizeof(*data), data, GL_STATIC_DRAW);
11352 
11353     if (isUniform)
11354     {
11355         GLint blockIndex = glGetUniformBlockIndex(program, name);
11356         glUniformBlockBinding(program, blockIndex, bindingIndex);
11357     }
11358 }
11359 
11360 // Verify that buffer data is written by the shader as expected.
11361 template <typename T>
VerifyBuffer(GLuint buffer,const T data[],uint32_t dataSize)11362 bool VerifyBuffer(GLuint buffer, const T data[], uint32_t dataSize)
11363 {
11364     uint32_t sizeInBytes = dataSize * sizeof(*data);
11365 
11366     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
11367 
11368     glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
11369 
11370     const T *ptr = reinterpret_cast<const T *>(
11371         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeInBytes, GL_MAP_READ_BIT));
11372 
11373     bool isCorrect = memcmp(ptr, data, sizeInBytes) == 0;
11374     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
11375 
11376     return isCorrect;
11377 }
11378 
11379 // Verify that the success output of the shader is as expected.
VerifySuccess(GLuint buffer)11380 bool VerifySuccess(GLuint buffer)
11381 {
11382     uint32_t success = 1;
11383     return VerifyBuffer(buffer, reinterpret_cast<const float *>(&success), 1);
11384 }
11385 
11386 // Test reading from UBOs and SSBOs and writing to SSBOs with mixed row- and colum-major layouts in
11387 // both std140 and std430 layouts.  Tests many combinations of std140 vs std430, struct being used
11388 // as row- or column-major in different UBOs, reading from UBOs and SSBOs and writing to SSBOs,
11389 // nested structs, matrix arrays, inout parameters etc.
11390 //
11391 // Some very specific corner cases that are not covered here are tested in the subsequent tests.
TEST_P(GLSLTest_ES31,MixedRowAndColumnMajorMatrices)11392 TEST_P(GLSLTest_ES31, MixedRowAndColumnMajorMatrices)
11393 {
11394     GLint maxComputeShaderStorageBlocks;
11395     glGetIntegerv(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, &maxComputeShaderStorageBlocks);
11396 
11397     // The test uses 9 SSBOs.  Skip if not that many are supported.
11398     ANGLE_SKIP_TEST_IF(maxComputeShaderStorageBlocks < 9);
11399 
11400     // Fails on Nvidia because having |Matrices| qualified as row-major in one UBO makes the other
11401     // UBO also see it as row-major despite explicit column-major qualifier.
11402     // http://anglebug.com/42262474
11403     ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGL());
11404 
11405     // Fails on mesa because in the first UBO which is qualified as column-major, |Matrices| is
11406     // read column-major despite explicit row-major qualifier.  http://anglebug.com/42262481
11407     ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsOpenGL());
11408 
11409     // Fails on windows AMD on GL: http://anglebug.com/42262482
11410     ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL() && IsAMD());
11411 
11412     // Fails to compile the shader on Android.  http://anglebug.com/42262483
11413     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
11414 
11415     // Fails on assertion in translation to D3D.  http://anglebug.com/42262486
11416     ANGLE_SKIP_TEST_IF(IsD3D11());
11417 
11418     // Fails on SSBO validation on Android/Vulkan.  http://anglebug.com/42262485
11419     ANGLE_SKIP_TEST_IF(IsAndroid() && IsVulkan());
11420 
11421     // Fails input verification as well as std140 SSBO validation.  http://anglebug.com/42262489
11422     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());
11423 
11424     // Fails on ARM on Vulkan.  http://anglebug.com/42263107
11425     ANGLE_SKIP_TEST_IF(IsARM() && IsVulkan());
11426 
11427     constexpr char kCS[] = R"(#version 310 es
11428 precision highp float;
11429 layout(local_size_x=1) in;
11430 
11431 struct Inner
11432 {
11433     mat3x4 m3c4r;
11434     mat4x3 m4c3r;
11435 };
11436 
11437 struct Matrices
11438 {
11439     mat2 m2c2r;
11440     mat2x3 m2c3r[2];
11441     mat3x2 m3c2r;
11442     Inner inner;
11443 };
11444 
11445 // For simplicity, the layouts are either of:
11446 // - col-major mat4, row-major rest
11447 // - row-major mat4, col-major rest
11448 //
11449 // The former is tagged with c, the latter with r.
11450 layout(std140, column_major) uniform Ubo140c
11451 {
11452     mat4 m4c4r;
11453     layout(row_major) Matrices m;
11454 } ubo140cIn;
11455 
11456 layout(std140, row_major) uniform Ubo140r
11457 {
11458     mat4 m4c4r;
11459     layout(column_major) Matrices m;
11460 } ubo140rIn;
11461 
11462 layout(std140, row_major, binding = 0) buffer Ssbo140c
11463 {
11464     layout(column_major) mat4 m4c4r;
11465     Matrices m;
11466 } ssbo140cIn;
11467 
11468 layout(std140, column_major, binding = 1) buffer Ssbo140r
11469 {
11470     layout(row_major) mat4 m4c4r;
11471     Matrices m;
11472 } ssbo140rIn;
11473 
11474 layout(std430, column_major, binding = 2) buffer Ssbo430c
11475 {
11476     mat4 m4c4r;
11477     layout(row_major) Matrices m;
11478 } ssbo430cIn;
11479 
11480 layout(std430, row_major, binding = 3) buffer Ssbo430r
11481 {
11482     mat4 m4c4r;
11483     layout(column_major) Matrices m;
11484 } ssbo430rIn;
11485 
11486 layout(std140, row_major, binding = 4) buffer Ssbo140cOut
11487 {
11488     layout(column_major) mat4 m4c4r;
11489     Matrices m;
11490 } ssbo140cOut;
11491 
11492 layout(std140, column_major, binding = 5) buffer Ssbo140rOut
11493 {
11494     layout(row_major) mat4 m4c4r;
11495     Matrices m;
11496 } ssbo140rOut;
11497 
11498 layout(std430, column_major, binding = 6) buffer Ssbo430cOut
11499 {
11500     mat4 m4c4r;
11501     layout(row_major) Matrices m;
11502 } ssbo430cOut;
11503 
11504 layout(std430, row_major, binding = 7) buffer Ssbo430rOut
11505 {
11506     mat4 m4c4r;
11507     layout(column_major) Matrices m;
11508 } ssbo430rOut;
11509 
11510 layout(std140, binding = 8) buffer Result
11511 {
11512     uint success;
11513 } resultOut;
11514 
11515 #define EXPECT(result, expression, value) if ((expression) != value) { result = false; }
11516 #define EXPECTV(result, expression, value) if (any(notEqual(expression, value))) { result = false; }
11517 
11518 #define VERIFY_IN(result, mat, cols, rows)                  \
11519     EXPECT(result, mat[0].x, 0.0);                          \
11520     EXPECT(result, mat[0][1], 1.0);                         \
11521     EXPECTV(result, mat[0].xy, vec2(0, 1));                 \
11522     EXPECTV(result, mat[1].xy, vec2(4, 5));                 \
11523     for (int c = 0; c < cols; ++c)                          \
11524     {                                                       \
11525         for (int r = 0; r < rows; ++r)                      \
11526         {                                                   \
11527             EXPECT(result, mat[c][r], float(c * 4 + r));    \
11528         }                                                   \
11529     }
11530 
11531 #define COPY(matIn, matOut, cols, rows)     \
11532     matOut = matOut + matIn;                \
11533     /* random operations for testing */     \
11534     matOut[0].x += matIn[0].x + matIn[1].x; \
11535     matOut[0].x -= matIn[1].x;              \
11536     matOut[0][1] += matIn[0][1];            \
11537     matOut[1] += matIn[1];                  \
11538     matOut[1].xy -= matIn[1].xy;            \
11539     /* undo the above to get back matIn */  \
11540     matOut[0].x -= matIn[0].x;              \
11541     matOut[0][1] -= matIn[0][1];            \
11542     matOut[1] -= matIn[1];                  \
11543     matOut[1].xy += matIn[1].xy;
11544 
11545 bool verifyMatrices(in Matrices m)
11546 {
11547     bool result = true;
11548     VERIFY_IN(result, m.m2c2r, 2, 2);
11549     VERIFY_IN(result, m.m2c3r[0], 2, 3);
11550     VERIFY_IN(result, m.m2c3r[1], 2, 3);
11551     VERIFY_IN(result, m.m3c2r, 3, 2);
11552     VERIFY_IN(result, m.inner.m3c4r, 3, 4);
11553     VERIFY_IN(result, m.inner.m4c3r, 4, 3);
11554     return result;
11555 }
11556 
11557 mat4 copyMat4(in mat4 m)
11558 {
11559     return m;
11560 }
11561 
11562 void copyMatrices(in Matrices mIn, inout Matrices mOut)
11563 {
11564     COPY(mIn.m2c2r, mOut.m2c2r, 2, 2);
11565     COPY(mIn.m2c3r[0], mOut.m2c3r[0], 2, 3);
11566     COPY(mIn.m2c3r[1], mOut.m2c3r[1], 2, 3);
11567     COPY(mIn.m3c2r, mOut.m3c2r, 3, 2);
11568     COPY(mIn.inner.m3c4r, mOut.inner.m3c4r, 3, 4);
11569     COPY(mIn.inner.m4c3r, mOut.inner.m4c3r, 4, 3);
11570 }
11571 
11572 void main()
11573 {
11574     bool result = true;
11575 
11576     VERIFY_IN(result, ubo140cIn.m4c4r, 4, 4);
11577     VERIFY_IN(result, ubo140cIn.m.m2c3r[0], 2, 3);
11578     EXPECT(result, verifyMatrices(ubo140cIn.m), true);
11579 
11580     VERIFY_IN(result, ubo140rIn.m4c4r, 4, 4);
11581     VERIFY_IN(result, ubo140rIn.m.m2c2r, 2, 2);
11582     EXPECT(result, verifyMatrices(ubo140rIn.m), true);
11583 
11584     VERIFY_IN(result, ssbo140cIn.m4c4r, 4, 4);
11585     VERIFY_IN(result, ssbo140cIn.m.m3c2r, 3, 2);
11586     EXPECT(result, verifyMatrices(ssbo140cIn.m), true);
11587 
11588     VERIFY_IN(result, ssbo140rIn.m4c4r, 4, 4);
11589     VERIFY_IN(result, ssbo140rIn.m.inner.m4c3r, 4, 3);
11590     EXPECT(result, verifyMatrices(ssbo140rIn.m), true);
11591 
11592     VERIFY_IN(result, ssbo430cIn.m4c4r, 4, 4);
11593     VERIFY_IN(result, ssbo430cIn.m.m2c3r[1], 2, 3);
11594     EXPECT(result, verifyMatrices(ssbo430cIn.m), true);
11595 
11596     VERIFY_IN(result, ssbo430rIn.m4c4r, 4, 4);
11597     VERIFY_IN(result, ssbo430rIn.m.inner.m3c4r, 3, 4);
11598     EXPECT(result, verifyMatrices(ssbo430rIn.m), true);
11599 
11600     // Only assign to SSBO from a single invocation.
11601     if (gl_GlobalInvocationID.x == 0u)
11602     {
11603         ssbo140cOut.m4c4r = copyMat4(ssbo140cIn.m4c4r);
11604         copyMatrices(ssbo430cIn.m, ssbo140cOut.m);
11605         ssbo140cOut.m.m2c3r[1] = mat2x3(0);
11606         COPY(ssbo430cIn.m.m2c3r[1], ssbo140cOut.m.m2c3r[1], 2, 3);
11607 
11608         ssbo140rOut.m4c4r = copyMat4(ssbo140rIn.m4c4r);
11609         copyMatrices(ssbo430rIn.m, ssbo140rOut.m);
11610         ssbo140rOut.m.inner.m3c4r = mat3x4(0);
11611         COPY(ssbo430rIn.m.inner.m3c4r, ssbo140rOut.m.inner.m3c4r, 3, 4);
11612 
11613         ssbo430cOut.m4c4r = copyMat4(ssbo430cIn.m4c4r);
11614         copyMatrices(ssbo140cIn.m, ssbo430cOut.m);
11615         ssbo430cOut.m.m3c2r = mat3x2(0);
11616         COPY(ssbo430cIn.m.m3c2r, ssbo430cOut.m.m3c2r, 3, 2);
11617 
11618         ssbo430rOut.m4c4r = copyMat4(ssbo430rIn.m4c4r);
11619         copyMatrices(ssbo140rIn.m, ssbo430rOut.m);
11620         ssbo430rOut.m.inner.m4c3r = mat4x3(0);
11621         COPY(ssbo430rIn.m.inner.m4c3r, ssbo430rOut.m.inner.m4c3r, 4, 3);
11622 
11623         resultOut.success = uint(result);
11624     }
11625 })";
11626 
11627     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
11628     EXPECT_GL_NO_ERROR();
11629 
11630     constexpr size_t kMatrixCount                                     = 7;
11631     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
11632         {4, 4}, {2, 2}, {2, 3}, {2, 3}, {3, 2}, {3, 4}, {4, 3},
11633     };
11634     constexpr bool kMatrixIsColMajor[kMatrixCount] = {
11635         true, false, false, false, false, false, false,
11636     };
11637 
11638     float dataStd140ColMajor[kMatrixCount * 4 * 4] = {};
11639     float dataStd140RowMajor[kMatrixCount * 4 * 4] = {};
11640     float dataStd430ColMajor[kMatrixCount * 4 * 4] = {};
11641     float dataStd430RowMajor[kMatrixCount * 4 * 4] = {};
11642     float dataZeros[kMatrixCount * 4 * 4]          = {};
11643 
11644     const uint32_t sizeStd140ColMajor =
11645         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, dataStd140ColMajor, false, false);
11646     const uint32_t sizeStd140RowMajor =
11647         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, dataStd140RowMajor, false, true);
11648     const uint32_t sizeStd430ColMajor =
11649         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, dataStd430ColMajor, true, false);
11650     const uint32_t sizeStd430RowMajor =
11651         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, dataStd430RowMajor, true, true);
11652 
11653     GLBuffer uboStd140ColMajor, uboStd140RowMajor;
11654     GLBuffer ssboStd140ColMajor, ssboStd140RowMajor;
11655     GLBuffer ssboStd430ColMajor, ssboStd430RowMajor;
11656     GLBuffer ssboStd140ColMajorOut, ssboStd140RowMajorOut;
11657     GLBuffer ssboStd430ColMajorOut, ssboStd430RowMajorOut;
11658 
11659     InitBuffer(program, "Ubo140c", uboStd140ColMajor, 0, dataStd140ColMajor, sizeStd140ColMajor,
11660                true);
11661     InitBuffer(program, "Ubo140r", uboStd140RowMajor, 1, dataStd140RowMajor, sizeStd140RowMajor,
11662                true);
11663     InitBuffer(program, "Ssbo140c", ssboStd140ColMajor, 0, dataStd140ColMajor, sizeStd140ColMajor,
11664                false);
11665     InitBuffer(program, "Ssbo140r", ssboStd140RowMajor, 1, dataStd140RowMajor, sizeStd140RowMajor,
11666                false);
11667     InitBuffer(program, "Ssbo430c", ssboStd430ColMajor, 2, dataStd430ColMajor, sizeStd430ColMajor,
11668                false);
11669     InitBuffer(program, "Ssbo430r", ssboStd430RowMajor, 3, dataStd430RowMajor, sizeStd430RowMajor,
11670                false);
11671     InitBuffer(program, "Ssbo140cOut", ssboStd140ColMajorOut, 4, dataZeros, sizeStd140ColMajor,
11672                false);
11673     InitBuffer(program, "Ssbo140rOut", ssboStd140RowMajorOut, 5, dataZeros, sizeStd140RowMajor,
11674                false);
11675     InitBuffer(program, "Ssbo430cOut", ssboStd430ColMajorOut, 6, dataZeros, sizeStd430ColMajor,
11676                false);
11677     InitBuffer(program, "Ssbo430rOut", ssboStd430RowMajorOut, 7, dataZeros, sizeStd430RowMajor,
11678                false);
11679     EXPECT_GL_NO_ERROR();
11680 
11681     GLBuffer outputBuffer;
11682     CreateOutputBuffer(&outputBuffer, 8);
11683 
11684     glUseProgram(program);
11685     glDispatchCompute(1, 1, 1);
11686     EXPECT_GL_NO_ERROR();
11687     EXPECT_TRUE(VerifySuccess(outputBuffer));
11688 
11689     EXPECT_TRUE(VerifyBuffer(ssboStd140ColMajorOut, dataStd140ColMajor, sizeStd140ColMajor));
11690     EXPECT_TRUE(VerifyBuffer(ssboStd140RowMajorOut, dataStd140RowMajor, sizeStd140RowMajor));
11691     EXPECT_TRUE(VerifyBuffer(ssboStd430ColMajorOut, dataStd430ColMajor, sizeStd430ColMajor));
11692     EXPECT_TRUE(VerifyBuffer(ssboStd430RowMajorOut, dataStd430RowMajor, sizeStd430RowMajor));
11693 }
11694 
11695 // Test that array UBOs are transformed correctly.
TEST_P(GLSLTest_ES3,RowMajorMatrix_ReadMat4Test)11696 TEST_P(GLSLTest_ES3, RowMajorMatrix_ReadMat4Test)
11697 {
11698     constexpr char kFS[] = R"(#version 300 es
11699 precision highp float;
11700 out vec4 outColor;
11701 
11702 layout(std140, row_major) uniform Ubo
11703 {
11704     mat4 m1;
11705 };
11706 
11707 void main()
11708 {
11709     outColor = m1[3] / 255.0;
11710 })";
11711 
11712     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11713     EXPECT_GL_NO_ERROR();
11714 
11715     constexpr size_t kMatrixCount                                     = 1;
11716     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
11717         {4, 4},
11718     };
11719     constexpr bool kMatrixIsColMajor[kMatrixCount] = {
11720         false,
11721     };
11722 
11723     float data[kMatrixCount * 4 * 4] = {};
11724 
11725     const uint32_t size =
11726         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
11727 
11728     GLBuffer ubos;
11729 
11730     InitBuffer(program, "Ubo", ubos, 0, data, size, true);
11731 
11732     EXPECT_GL_NO_ERROR();
11733 
11734     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
11735     EXPECT_PIXEL_NEAR(0, 0, 12, 13, 14, 15, 0);
11736 }
11737 
11738 // Test that array UBOs are transformed correctly.
TEST_P(GLSLTest_ES3,RowMajorMatrix_ReadMat2x3Test)11739 TEST_P(GLSLTest_ES3, RowMajorMatrix_ReadMat2x3Test)
11740 {
11741     constexpr char kFS[] = R"(#version 300 es
11742 precision highp float;
11743 out vec4 outColor;
11744 
11745 layout(std140, row_major) uniform Ubo
11746 {
11747     mat2x3 m1;
11748 };
11749 
11750 void main()
11751 {
11752     outColor = vec4(m1[1], 0) / 255.0;
11753 })";
11754 
11755     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11756     EXPECT_GL_NO_ERROR();
11757 
11758     constexpr size_t kMatrixCount                                     = 1;
11759     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
11760         {2, 3},
11761     };
11762     constexpr bool kMatrixIsColMajor[kMatrixCount] = {
11763         false,
11764     };
11765 
11766     float data[kMatrixCount * 3 * 4] = {};
11767 
11768     const uint32_t size =
11769         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
11770 
11771     GLBuffer ubos;
11772 
11773     InitBuffer(program, "Ubo", ubos, 0, data, size, true);
11774 
11775     EXPECT_GL_NO_ERROR();
11776 
11777     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
11778     EXPECT_PIXEL_NEAR(0, 0, 4, 5, 6, 0, 0);
11779 }
11780 
TEST_P(GLSLTest_ES3,RowMajorMatrix_ReadMat3x2Test)11781 TEST_P(GLSLTest_ES3, RowMajorMatrix_ReadMat3x2Test)
11782 {
11783     constexpr char kFS[] = R"(#version 300 es
11784 precision highp float;
11785 out vec4 outColor;
11786 
11787 layout(std140, row_major) uniform Ubo
11788 {
11789     mat3x2 m1;
11790 };
11791 
11792 void main()
11793 {
11794     outColor = vec4(m1[2], 0, 0) / 255.0;
11795 })";
11796 
11797     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11798     EXPECT_GL_NO_ERROR();
11799 
11800     constexpr size_t kMatrixCount                                     = 1;
11801     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
11802         {3, 2},
11803     };
11804     constexpr bool kMatrixIsColMajor[kMatrixCount] = {
11805         false,
11806     };
11807 
11808     float data[kMatrixCount * 2 * 4] = {};
11809 
11810     const uint32_t size =
11811         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
11812 
11813     GLBuffer ubos;
11814 
11815     InitBuffer(program, "Ubo", ubos, 0, data, size, true);
11816 
11817     EXPECT_GL_NO_ERROR();
11818 
11819     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
11820     EXPECT_PIXEL_NEAR(0, 0, 8, 9, 0, 0, 0);
11821 }
11822 
TEST_P(GLSLTest_ES3,RowMajorMatrix_NestedExpression)11823 TEST_P(GLSLTest_ES3, RowMajorMatrix_NestedExpression)
11824 {
11825     // Many OpenGL drivers seem to fail this
11826     ANGLE_SKIP_TEST_IF((IsLinux() || IsMac()) && IsOpenGL());
11827 
11828     constexpr char kFS[] = R"(#version 300 es
11829 precision mediump float;
11830 
11831 uniform Ubo {
11832   layout(row_major) mat4 u_mat[3];
11833   layout(row_major) mat4 u_ndx[3];
11834 } stuff;
11835 
11836 precision highp float;
11837 out vec4 outColor;
11838 
11839 void main() {
11840   outColor = stuff.u_mat[int(stuff.u_ndx[1][1][3])][2] / 255.0;
11841 }
11842 )";
11843 
11844     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11845     EXPECT_GL_NO_ERROR();
11846 
11847     typedef float vec4[4];
11848     typedef vec4 mat4[4];
11849 
11850     constexpr size_t kMatrixCount = 6;
11851     mat4 data[]                   = {
11852         {
11853             {0, 1, 2, 3},      //
11854             {4, 5, 6, 7},      //
11855             {8, 9, 10, 11},    //
11856             {12, 13, 14, 15},  //
11857         },
11858         {
11859             //     +-- we should be looking up this column
11860             //     V
11861             {0, 4, 8, 12},   //
11862             {1, 5, 9, 13},   //
11863             {2, 6, 10, 14},  //
11864             {3, 7, 11, 15},  //
11865         },
11866         {
11867             {0, 2, 4, 6},      //
11868             {8, 10, 12, 14},   //
11869             {16, 18, 20, 22},  //
11870             {24, 26, 28, 30},  //
11871         },
11872         {
11873             {0, 0, 0, 0},  //
11874             {0, 0, 0, 0},  //
11875             {0, 0, 0, 0},  //
11876             {0, 0, 0, 0},  //
11877         },
11878         {
11879             {0, 0, 0, 0},  //
11880             {0, 0, 0, 2},  //
11881             {0, 0, 0, 0},  //
11882             {0, 1, 0, 0},
11883             //  ^
11884             //  +-- we should be using this element
11885         },
11886         {
11887             {0, 0, 0, 0},  //
11888             {0, 0, 0, 0},  //
11889             {0, 0, 0, 0},  //
11890             {0, 0, 0, 0},  //
11891         },
11892     };
11893 
11894     GLBuffer ubos;
11895     InitBuffer(program, "Ubo", ubos, 0, data, kMatrixCount, true);
11896     EXPECT_GL_NO_ERROR();
11897 
11898     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
11899     EXPECT_PIXEL_NEAR(0, 0, 8, 9, 10, 11, 0);
11900 }
11901 
11902 // Test that array UBOs are transformed correctly.
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ArrayBufferDeclaration)11903 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ArrayBufferDeclaration)
11904 {
11905     // Fails to compile the shader on Android: http://anglebug.com/42262483
11906     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
11907 
11908     // http://anglebug.com/42262481
11909     ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsOpenGL());
11910 
11911     // Fails on Mac on Intel and AMD: http://anglebug.com/42262487
11912     ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL() && (IsIntel() || IsAMD()));
11913 
11914     // Fails on windows AMD on GL: http://anglebug.com/42262482
11915     ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL() && IsAMD());
11916 
11917     // Fails on D3D due to mistranslation: http://anglebug.com/42262486
11918     ANGLE_SKIP_TEST_IF(IsD3D11());
11919 
11920     constexpr char kFS[] = R"(#version 300 es
11921 precision highp float;
11922 out vec4 outColor;
11923 
11924 layout(std140, column_major) uniform Ubo
11925 {
11926     mat4 m1;
11927     layout(row_major) mat4 m2;
11928 } ubo[3];
11929 
11930 #define EXPECT(result, expression, value) if ((expression) != value) { result = false; }
11931 
11932 #define VERIFY_IN(result, mat, cols, rows)                  \
11933     for (int c = 0; c < cols; ++c)                          \
11934     {                                                       \
11935         for (int r = 0; r < rows; ++r)                      \
11936         {                                                   \
11937             EXPECT(result, mat[c][r], float(c * 4 + r));    \
11938         }                                                   \
11939     }
11940 
11941 void main()
11942 {
11943     bool result = true;
11944 
11945     VERIFY_IN(result, ubo[0].m1, 4, 4);
11946     VERIFY_IN(result, ubo[0].m2, 4, 4);
11947 
11948     VERIFY_IN(result, ubo[1].m1, 4, 4);
11949     VERIFY_IN(result, ubo[1].m2, 4, 4);
11950 
11951     VERIFY_IN(result, ubo[2].m1, 4, 4);
11952     VERIFY_IN(result, ubo[2].m2, 4, 4);
11953 
11954     outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
11955 })";
11956 
11957     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
11958     EXPECT_GL_NO_ERROR();
11959 
11960     constexpr size_t kMatrixCount                                     = 2;
11961     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
11962         {4, 4},
11963         {4, 4},
11964     };
11965     constexpr bool kMatrixIsColMajor[kMatrixCount] = {
11966         true,
11967         false,
11968     };
11969 
11970     float data[kMatrixCount * 4 * 4] = {};
11971 
11972     const uint32_t size =
11973         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
11974 
11975     GLBuffer ubos[3];
11976 
11977     InitBuffer(program, "Ubo[0]", ubos[0], 0, data, size, true);
11978     InitBuffer(program, "Ubo[1]", ubos[1], 0, data, size, true);
11979     InitBuffer(program, "Ubo[2]", ubos[2], 0, data, size, true);
11980 
11981     EXPECT_GL_NO_ERROR();
11982 
11983     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
11984     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
11985 }
11986 
11987 // Test that side effects when transforming read operations are preserved.
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ReadSideEffect)11988 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ReadSideEffect)
11989 {
11990     // Fails on Mac on Intel and AMD: http://anglebug.com/42262487
11991     ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL() && (IsIntel() || IsAMD()));
11992 
11993     // Fails on D3D due to mistranslation: http://anglebug.com/42262486
11994     ANGLE_SKIP_TEST_IF(IsD3D11());
11995 
11996     constexpr char kFS[] = R"(#version 300 es
11997 precision highp float;
11998 out vec4 outColor;
11999 
12000 struct S
12001 {
12002     mat2x3 m2[3];
12003 };
12004 
12005 layout(std140, column_major) uniform Ubo
12006 {
12007     mat4 m1;
12008     layout(row_major) S s[2];
12009 } ubo;
12010 
12011 #define EXPECT(result, expression, value) if ((expression) != value) { result = false; }
12012 
12013 #define VERIFY_IN(result, mat, cols, rows)                  \
12014     for (int c = 0; c < cols; ++c)                          \
12015     {                                                       \
12016         for (int r = 0; r < rows; ++r)                      \
12017         {                                                   \
12018             EXPECT(result, mat[c][r], float(c * 4 + r));    \
12019         }                                                   \
12020     }
12021 
12022 bool verify2x3(mat2x3 mat)
12023 {
12024     bool result = true;
12025 
12026     for (int c = 0; c < 2; ++c)
12027     {
12028         for (int r = 0; r < 3; ++r)
12029         {
12030             EXPECT(result, mat[c][r], float(c * 4 + r));
12031         }
12032     }
12033 
12034     return result;
12035 }
12036 
12037 void main()
12038 {
12039     bool result = true;
12040 
12041     int sideEffect = 0;
12042     VERIFY_IN(result, ubo.m1, 4, 4);
12043     EXPECT(result, verify2x3(ubo.s[0].m2[0]), true);
12044     EXPECT(result, verify2x3(ubo.s[0].m2[sideEffect += 1]), true);
12045     EXPECT(result, verify2x3(ubo.s[0].m2[sideEffect += 1]), true);
12046 
12047     EXPECT(result, sideEffect, 2);
12048 
12049     EXPECT(result, verify2x3(ubo.s[sideEffect = 1].m2[0]), true);
12050     EXPECT(result, verify2x3(ubo.s[1].m2[(sideEffect = 4) - 3]), true);
12051     EXPECT(result, verify2x3(ubo.s[1].m2[sideEffect - 2]), true);
12052 
12053     EXPECT(result, sideEffect, 4);
12054 
12055     outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12056 })";
12057 
12058     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
12059     EXPECT_GL_NO_ERROR();
12060 
12061     constexpr size_t kMatrixCount                                     = 7;
12062     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
12063         {4, 4}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3},
12064     };
12065     constexpr bool kMatrixIsColMajor[kMatrixCount] = {
12066         true, false, false, false, false, false, false,
12067     };
12068 
12069     float data[kMatrixCount * 4 * 4] = {};
12070 
12071     const uint32_t size =
12072         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
12073 
12074     GLBuffer ubo;
12075     InitBuffer(program, "Ubo", ubo, 0, data, size, true);
12076 
12077     EXPECT_GL_NO_ERROR();
12078 
12079     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
12080     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
12081 }
12082 
12083 // Test that side effects respect the order of logical expression operands.
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ReadSideEffectOrder)12084 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ReadSideEffectOrder)
12085 {
12086     // http://anglebug.com/42262481
12087     ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsOpenGL());
12088 
12089     // IntermTraverser::insertStatementsInParentBlock that's used to move side effects does not
12090     // respect the order of evaluation of logical expressions.  http://anglebug.com/42262472.
12091     ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
12092 
12093     constexpr char kFS[] = R"(#version 300 es
12094 precision highp float;
12095 out vec4 outColor;
12096 
12097 layout(std140, column_major) uniform Ubo
12098 {
12099     mat4 m1;
12100     layout(row_major) mat4 m2[2];
12101 } ubo;
12102 
12103 void main()
12104 {
12105     bool result = true;
12106 
12107     int x = 0;
12108     if (x == 0 && ubo.m2[x = 1][1][1] == 5.0)
12109     {
12110         result = true;
12111     }
12112     else
12113     {
12114         result = false;
12115     }
12116 
12117     outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12118 })";
12119 
12120     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
12121     EXPECT_GL_NO_ERROR();
12122 
12123     constexpr size_t kMatrixCount                                     = 3;
12124     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
12125         {4, 4},
12126         {4, 4},
12127         {4, 4},
12128     };
12129     constexpr bool kMatrixIsColMajor[kMatrixCount] = {true, false, false};
12130 
12131     float data[kMatrixCount * 4 * 4] = {};
12132 
12133     const uint32_t size =
12134         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
12135 
12136     GLBuffer ubo;
12137     InitBuffer(program, "Ubo", ubo, 0, data, size, true);
12138 
12139     EXPECT_GL_NO_ERROR();
12140 
12141     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
12142     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
12143 }
12144 
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ReadSideEffectOrderSurroundedByLoop)12145 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ReadSideEffectOrderSurroundedByLoop)
12146 {
12147     // http://anglebug.com/42262481
12148     ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsOpenGL());
12149 
12150     // IntermTraverser::insertStatementsInParentBlock that's used to move side effects does not
12151     // respect the order of evaluation of logical expressions.  http://anglebug.com/42262472.
12152     ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
12153 
12154     constexpr char kFS[] = R"(#version 300 es
12155 precision highp float;
12156 out vec4 outColor;
12157 
12158 layout(std140, column_major) uniform Ubo
12159 {
12160     mat4 m1;
12161     layout(row_major) mat4 m2[2];
12162 } ubo;
12163 
12164 void main()
12165 {
12166     bool result = false;
12167 
12168     for(int x = 0; x < 1; ++x)
12169     {
12170         if (x == 0 && ubo.m2[x = 1][1][1] == 5.0) {
12171           result = true;
12172         }
12173     }
12174     outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12175 })";
12176 
12177     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
12178     EXPECT_GL_NO_ERROR();
12179 
12180     constexpr size_t kMatrixCount                                     = 3;
12181     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
12182         {4, 4},
12183         {4, 4},
12184         {4, 4},
12185     };
12186     constexpr bool kMatrixIsColMajor[kMatrixCount] = {true, false, false};
12187 
12188     float data[kMatrixCount * 4 * 4] = {};
12189 
12190     const uint32_t size =
12191         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
12192 
12193     GLBuffer ubo;
12194     InitBuffer(program, "Ubo", ubo, 0, data, size, true);
12195 
12196     EXPECT_GL_NO_ERROR();
12197 
12198     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
12199     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
12200 }
12201 
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ReadSideEffectOrderInALoop)12202 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ReadSideEffectOrderInALoop)
12203 {
12204     // http://anglebug.com/42262481
12205     ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsOpenGL());
12206 
12207     // IntermTraverser::insertStatementsInParentBlock that's used to move side effects does not
12208     // respect the order of evaluation of logical expressions.  http://anglebug.com/42262472.
12209     ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
12210 
12211     constexpr char kFS[] = R"(#version 300 es
12212 precision highp float;
12213 out vec4 outColor;
12214 
12215 layout(std140, column_major) uniform Ubo
12216 {
12217     mat4 m1;
12218     layout(row_major) mat4 m2[2];
12219 } ubo;
12220 
12221 void main()
12222 {
12223     bool result = false;
12224 
12225     for(int x = 0; x == 0 && ubo.m2[x = 1][1][1] == 5.0;)
12226     {
12227         result = true;
12228     }
12229     outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12230 })";
12231 
12232     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
12233     EXPECT_GL_NO_ERROR();
12234 
12235     constexpr size_t kMatrixCount                                     = 3;
12236     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
12237         {4, 4},
12238         {4, 4},
12239         {4, 4},
12240     };
12241     constexpr bool kMatrixIsColMajor[kMatrixCount] = {true, false, false};
12242 
12243     float data[kMatrixCount * 4 * 4] = {};
12244 
12245     const uint32_t size =
12246         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
12247 
12248     GLBuffer ubo;
12249     InitBuffer(program, "Ubo", ubo, 0, data, size, true);
12250 
12251     EXPECT_GL_NO_ERROR();
12252 
12253     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
12254     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
12255 }
12256 
12257 // Test that side effects respect short-circuit.
TEST_P(GLSLTest_ES3,MixedRowAndColumnMajorMatrices_ReadSideEffectShortCircuit)12258 TEST_P(GLSLTest_ES3, MixedRowAndColumnMajorMatrices_ReadSideEffectShortCircuit)
12259 {
12260     // Fails on Android: http://anglebug.com/42262483
12261     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
12262 
12263     // IntermTraverser::insertStatementsInParentBlock that's used to move side effects does not
12264     // respect the order of evaluation of logical expressions.  http://anglebug.com/42262472.
12265     ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
12266 
12267     constexpr char kFS[] = R"(#version 300 es
12268 precision highp float;
12269 out vec4 outColor;
12270 
12271 layout(std140, column_major) uniform Ubo
12272 {
12273     mat4 m1;
12274     layout(row_major) mat4 m2[2];
12275 } ubo;
12276 
12277 void main()
12278 {
12279     bool result = true;
12280 
12281     int x = 0;
12282     if (x == 1 && ubo.m2[x = 1][1][1] == 5.0)
12283     {
12284         // First x == 1 should prevent the side effect of the second expression (x = 1) from
12285         // being executed.  If x = 1 is run before the if, the condition of the if would be true,
12286         // which is a failure.
12287         result = false;
12288     }
12289     if (x == 1)
12290     {
12291         result = false;
12292     }
12293 
12294     outColor = result ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12295 })";
12296 
12297     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
12298     EXPECT_GL_NO_ERROR();
12299 
12300     constexpr size_t kMatrixCount                                     = 3;
12301     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
12302         {4, 4},
12303         {4, 4},
12304         {4, 4},
12305     };
12306     constexpr bool kMatrixIsColMajor[kMatrixCount] = {true, false, false};
12307 
12308     float data[kMatrixCount * 4 * 4] = {};
12309 
12310     const uint32_t size =
12311         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
12312 
12313     GLBuffer ubo;
12314     InitBuffer(program, "Ubo", ubo, 0, data, size, true);
12315 
12316     EXPECT_GL_NO_ERROR();
12317 
12318     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
12319     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
12320 }
12321 
12322 // Test that indexing swizzles out of bounds fails
TEST_P(GLSLTest_ES3,OutOfBoundsIndexingOfSwizzle)12323 TEST_P(GLSLTest_ES3, OutOfBoundsIndexingOfSwizzle)
12324 {
12325     constexpr char kFS[] = R"(#version 300 es
12326 precision mediump float;
12327 out vec4 colorOut;
12328 uniform vec3 colorIn;
12329 
12330 void main()
12331 {
12332     colorOut = vec4(colorIn.yx[2], 0, 0, 1);
12333 })";
12334 
12335     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
12336     EXPECT_EQ(0u, shader);
12337 }
12338 
12339 // Test that indexing l-value swizzles work
TEST_P(GLSLTest_ES3,IndexingOfSwizzledLValuesShouldWork)12340 TEST_P(GLSLTest_ES3, IndexingOfSwizzledLValuesShouldWork)
12341 {
12342     constexpr char kFS[] = R"(#version 300 es
12343 precision mediump float;
12344 out vec4 oColor;
12345 
12346 bool do_test() {
12347     highp vec3 expected = vec3(3.0, 2.0, 1.0);
12348     highp vec3 vec;
12349 
12350     vec.yzx[2] = 3.0;
12351     vec.yzx[1] = 1.0;
12352     vec.yzx[0] = 2.0;
12353 
12354     return vec == expected;
12355 }
12356 
12357 void main()
12358 {
12359     oColor = vec4(do_test(), 0, 0, 1);
12360 })";
12361 
12362     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
12363     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
12364     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
12365     ASSERT_GL_NO_ERROR();
12366 }
12367 
12368 // Test that indexing r-value swizzles work
TEST_P(GLSLTest_ES3,IndexingOfSwizzledRValuesShouldWork)12369 TEST_P(GLSLTest_ES3, IndexingOfSwizzledRValuesShouldWork)
12370 {
12371     constexpr char kFS[] = R"(#version 300 es
12372 precision mediump float;
12373 out vec4 oColor;
12374 
12375 bool do_test() {
12376     highp vec3 expected = vec3(3.0, 2.0, 1.0);
12377     highp vec3 vecA = vec3(1.0, 3.0, 2.0);
12378     highp vec3 vecB;
12379 
12380     vecB.x = vecA.zxy[2];
12381     vecB.y = vecA.zxy[0];
12382     vecB.z = vecA.zxy[1];
12383 
12384     return vecB == expected;
12385 }
12386 
12387 void main()
12388 {
12389     oColor = vec4(do_test(), 0, 0, 1);
12390 })";
12391 
12392     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
12393     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
12394     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
12395     ASSERT_GL_NO_ERROR();
12396 }
12397 
12398 // Test that dynamic indexing of swizzled l-values should work.
12399 // A simple porting of sdk/tests/conformance2/glsl3/vector-dynamic-indexing-swizzled-lvalue.html
TEST_P(GLSLTest_ES3,DynamicIndexingOfSwizzledLValuesShouldWork)12400 TEST_P(GLSLTest_ES3, DynamicIndexingOfSwizzledLValuesShouldWork)
12401 {
12402     // The shader first assigns v.x to v.z (1.0)
12403     // Then v.y to v.y (2.0)
12404     // Then v.z to v.x (1.0)
12405     constexpr char kFS[] = R"(#version 300 es
12406 precision highp float;
12407 out vec4 my_FragColor;
12408 void main() {
12409     vec3 v = vec3(1.0, 2.0, 3.0);
12410     for (int i = 0; i < 3; i++) {
12411         v.zyx[i] = v[i];
12412     }
12413     my_FragColor = distance(v, vec3(1.0, 2.0, 1.0)) < 0.01 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
12414 })";
12415 
12416     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
12417     EXPECT_GL_NO_ERROR();
12418     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
12419     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
12420 }
12421 
12422 // Another test for dynamic indexing of swizzled l-values.
TEST_P(GLSLTest_ES3,DynamicIndexingOfSwizzledLValuesShouldWork2)12423 TEST_P(GLSLTest_ES3, DynamicIndexingOfSwizzledLValuesShouldWork2)
12424 {
12425     constexpr char kFS[] = R"(#version 300 es
12426 precision mediump float;
12427 out vec4 oColor;
12428 
12429 bool do_test() {
12430     highp vec3 expected = vec3(3.0, 2.0, 1.0);
12431     highp vec3 vec;
12432 
12433     for (int i = 0; i < 3; ++i)
12434     {
12435         vec.zyx[i] = float(1 + i);
12436     }
12437 
12438     return vec == expected;
12439 }
12440 
12441 void main()
12442 {
12443     oColor = vec4(do_test(), 0, 0, 1);
12444 })";
12445 
12446     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
12447     EXPECT_GL_NO_ERROR();
12448     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
12449     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
12450 }
12451 
12452 // Test that dead code after discard, return, continue and branch are pruned.
TEST_P(GLSLTest_ES3,DeadCodeIsPruned)12453 TEST_P(GLSLTest_ES3, DeadCodeIsPruned)
12454 {
12455     constexpr char kFS[] = R"(#version 300 es
12456 precision mediump float;
12457 out vec4 color;
12458 
12459 vec4 f(vec4 c)
12460 {
12461     return c;
12462     // dead code
12463     c = vec4(0, 0, 1, 1);
12464     return c;
12465 }
12466 
12467 void main()
12468 {
12469     vec4 result = vec4(0, 0.5, 0, 1);
12470     int var = int(result.y * 2.2);
12471 
12472     {
12473         if (result.x > 1.0)
12474         {
12475             discard;
12476             // dead code
12477             result = vec4(1, 0, 0, 1);
12478         }
12479         for (int i = 0; i < 3; ++i)
12480         {
12481             if (i < 2)
12482             {
12483                 result = f(result);
12484                 continue;
12485                 // dead code
12486                 result = vec4(1, 0, 1, 1);
12487             }
12488             result = f(result);
12489             break;
12490             // dead code
12491             result = vec4(1, 0, 1, 0);
12492         }
12493         while (true)
12494         {
12495             if (result.x > -1.0)
12496             {
12497                 {
12498                     result = f(result);
12499                     {
12500                         break;
12501                         // dead code
12502                         result = vec4(1, 0, 0, 0);
12503                     }
12504                     // dead code
12505                     for (int j = 0; j < 3; ++j)
12506                     {
12507                         if (j > 1) continue;
12508                         result = vec4(0, 0, 1, 0);
12509                         color = vec4(0.5, 0, 0.5, 0.5);
12510                         return;
12511                     }
12512                 }
12513                 // dead code
12514                 result = vec4(0.5, 0, 0, 0);
12515             }
12516         }
12517         switch (var)
12518         {
12519         case 2:
12520             return;
12521             // dead code
12522             color = vec4(0.25, 0, 0.25, 0.25);
12523         case 1:
12524             {
12525                 // Make sure this path is not pruned due to the return in the previous case.
12526                 result.y += 0.5;
12527                 break;
12528                 // dead code
12529                 color = vec4(0.25, 0, 0, 0);
12530             }
12531             // dead code
12532             color = vec4(0, 0, 0.25, 0);
12533             break;
12534         default:
12535             break;
12536         }
12537 
12538         color = result;
12539         return;
12540         // dead code
12541         color = vec4(0, 0, 0.5, 0);
12542     }
12543     // dead code
12544     color = vec4(0, 0, 0, 0.5);
12545 })";
12546 
12547     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
12548 
12549     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
12550     EXPECT_GL_NO_ERROR();
12551 
12552     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
12553 }
12554 
12555 // Regression test based on fuzzer issue.  If a case has statements that are pruned, and those
12556 // pruned statements in turn have branches, and another case follows, a prior implementation of
12557 // dead-code elimination doubly pruned some statements.
TEST_P(GLSLTest_ES3,DeadCodeBranchInPrunedStatementsInCaseBeforeAnotherCase)12558 TEST_P(GLSLTest_ES3, DeadCodeBranchInPrunedStatementsInCaseBeforeAnotherCase)
12559 {
12560     constexpr char kFS[] = R"(#version 300 es
12561 precision mediump float;
12562 out vec4 color;
12563 void main()
12564 {
12565     color = vec4(0, 1, 0, 1);
12566     switch(0)
12567     {
12568     case 0:
12569         break;
12570         break;
12571         color = vec4(1, 0, 0, 1);   // The bug was pruning this statement twice
12572     default:
12573         color = vec4(0, 0, 1, 1);
12574         break;
12575     }
12576 })";
12577 
12578     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
12579 
12580     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
12581     EXPECT_GL_NO_ERROR();
12582 
12583     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
12584 }
12585 
12586 // Test shader with all resources (default uniform, UBO, SSBO, image, sampler and atomic counter) to
12587 // make sure they are all linked ok.  The front-end sorts these resources and traverses the list of
12588 // "uniforms" to find the range for each resource.  A bug there was causing some resource ranges to
12589 // be empty in the presence of other resources.
TEST_P(GLSLTest_ES31,MixOfAllResources)12590 TEST_P(GLSLTest_ES31, MixOfAllResources)
12591 {
12592     // http://anglebug.com/42263641
12593     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
12594 
12595     constexpr char kComputeShader[] = R"(#version 310 es
12596 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
12597 layout(binding = 1, std430) buffer Output {
12598   uint ubo_value;
12599   uint default_value;
12600   uint sampler_value;
12601   uint ac_value;
12602   uint image_value;
12603 } outbuf;
12604 uniform Input {
12605   uint input_value;
12606 } inbuf;
12607 uniform uint default_uniform;
12608 uniform sampler2D smplr;
12609 layout(binding=0) uniform atomic_uint ac;
12610 layout(r32ui) uniform highp readonly uimage2D image;
12611 
12612 void main(void)
12613 {
12614   outbuf.ubo_value = inbuf.input_value;
12615   outbuf.default_value = default_uniform;
12616   outbuf.sampler_value = uint(texture(smplr, vec2(0.5, 0.5)).x * 255.0);
12617   outbuf.ac_value = atomicCounterIncrement(ac);
12618   outbuf.image_value = imageLoad(image, ivec2(0, 0)).x;
12619 }
12620 )";
12621     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
12622     EXPECT_GL_NO_ERROR();
12623 
12624     glUseProgram(program);
12625 
12626     unsigned int inputData = 89u;
12627     GLBuffer inputBuffer;
12628     glBindBuffer(GL_UNIFORM_BUFFER, inputBuffer);
12629     glBufferData(GL_UNIFORM_BUFFER, sizeof(inputData), &inputData, GL_STATIC_DRAW);
12630     GLuint inputBufferIndex = glGetUniformBlockIndex(program, "Input");
12631     ASSERT_NE(inputBufferIndex, GL_INVALID_INDEX);
12632     glUniformBlockBinding(program, inputBufferIndex, 0);
12633     glBindBufferBase(GL_UNIFORM_BUFFER, 0, inputBuffer);
12634 
12635     unsigned int outputInitData[5] = {0x12345678u, 0x09ABCDEFu, 0x56789ABCu, 0x0DEF1234u,
12636                                       0x13579BDFu};
12637     GLBuffer outputBuffer;
12638     glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
12639     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), outputInitData, GL_STATIC_DRAW);
12640     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
12641     EXPECT_GL_NO_ERROR();
12642 
12643     unsigned int uniformData = 456u;
12644     GLint uniformLocation    = glGetUniformLocation(program, "default_uniform");
12645     ASSERT_NE(uniformLocation, -1);
12646     glUniform1ui(uniformLocation, uniformData);
12647 
12648     unsigned int acData = 2u;
12649     GLBuffer atomicCounterBuffer;
12650     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
12651     glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(acData), &acData, GL_STATIC_DRAW);
12652     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
12653     EXPECT_GL_NO_ERROR();
12654 
12655     unsigned int imageData = 33u;
12656     GLTexture image;
12657     glBindTexture(GL_TEXTURE_2D, image);
12658     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
12659     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &imageData);
12660     glBindImageTexture(0, image, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
12661     EXPECT_GL_NO_ERROR();
12662 
12663     GLColor textureData(127, 18, 189, 211);
12664     GLTexture texture;
12665     glBindTexture(GL_TEXTURE_2D, texture);
12666     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &textureData);
12667     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12668     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12669     ASSERT_GL_NO_ERROR();
12670 
12671     glDispatchCompute(1, 1, 1);
12672     EXPECT_GL_NO_ERROR();
12673 
12674     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
12675 
12676     // read back
12677     const GLuint *ptr = reinterpret_cast<const GLuint *>(
12678         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
12679     EXPECT_EQ(ptr[0], inputData);
12680     EXPECT_EQ(ptr[1], uniformData);
12681     EXPECT_NEAR(ptr[2], textureData.R, 1.0);
12682     EXPECT_EQ(ptr[3], acData);
12683     EXPECT_EQ(ptr[4], imageData);
12684 
12685     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
12686 }
12687 
12688 // Test that sending mixture of resources to functions works.
TEST_P(GLSLTest_ES31,MixOfResourcesAsFunctionArgs)12689 TEST_P(GLSLTest_ES31, MixOfResourcesAsFunctionArgs)
12690 {
12691     // http://anglebug.com/42264082
12692     ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
12693 
12694     // anglebug.com/42262476 - no sampler array params on Android
12695     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
12696 
12697     constexpr char kComputeShader[] = R"(#version 310 es
12698 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
12699 
12700 layout(binding = 1, std430) buffer Output {
12701   uint success;
12702 } outbuf;
12703 
12704 uniform uint initialAcValue;
12705 uniform sampler2D smplr[2][3];
12706 layout(binding=0) uniform atomic_uint ac;
12707 
12708 bool sampler1DAndAtomicCounter(uvec3 sExpect, in sampler2D s[3], in atomic_uint a, uint aExpect)
12709 {
12710     uvec3 sResult = uvec3(uint(texture(s[0], vec2(0.5, 0.5)).x * 255.0),
12711                           uint(texture(s[1], vec2(0.5, 0.5)).x * 255.0),
12712                           uint(texture(s[2], vec2(0.5, 0.5)).x * 255.0));
12713     uint aResult = atomicCounterIncrement(a);
12714 
12715     return sExpect == sResult && aExpect == aResult;
12716 }
12717 
12718 bool sampler2DAndAtomicCounter(in sampler2D s[2][3], uint aInitial, in atomic_uint a)
12719 {
12720     bool success = true;
12721     success = sampler1DAndAtomicCounter(uvec3(0, 127, 255), s[0], a, aInitial) && success;
12722     success = sampler1DAndAtomicCounter(uvec3(31, 63, 191), s[1], a, aInitial + 1u) && success;
12723     return success;
12724 }
12725 
12726 void main(void)
12727 {
12728     outbuf.success = uint(sampler2DAndAtomicCounter(smplr, initialAcValue, ac));
12729 }
12730 )";
12731     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
12732     EXPECT_GL_NO_ERROR();
12733 
12734     glUseProgram(program);
12735 
12736     unsigned int outputInitData = 0x12345678u;
12737     GLBuffer outputBuffer;
12738     glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
12739     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
12740     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
12741     EXPECT_GL_NO_ERROR();
12742 
12743     unsigned int acData   = 2u;
12744     GLint uniformLocation = glGetUniformLocation(program, "initialAcValue");
12745     ASSERT_NE(uniformLocation, -1);
12746     glUniform1ui(uniformLocation, acData);
12747 
12748     GLBuffer atomicCounterBuffer;
12749     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
12750     glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(acData), &acData, GL_STATIC_DRAW);
12751     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
12752     EXPECT_GL_NO_ERROR();
12753 
12754     const std::array<GLColor, 6> kTextureData = {
12755         GLColor(0, 0, 0, 0),  GLColor(127, 0, 0, 0), GLColor(255, 0, 0, 0),
12756         GLColor(31, 0, 0, 0), GLColor(63, 0, 0, 0),  GLColor(191, 0, 0, 0),
12757     };
12758     GLTexture textures[2][3];
12759 
12760     for (int dim1 = 0; dim1 < 2; ++dim1)
12761     {
12762         for (int dim2 = 0; dim2 < 3; ++dim2)
12763         {
12764             int textureUnit = dim1 * 3 + dim2;
12765             glActiveTexture(GL_TEXTURE0 + textureUnit);
12766             glBindTexture(GL_TEXTURE_2D, textures[dim1][dim2]);
12767             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
12768                          &kTextureData[textureUnit]);
12769             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12770             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12771 
12772             std::stringstream uniformName;
12773             uniformName << "smplr[" << dim1 << "][" << dim2 << "]";
12774             GLint samplerLocation = glGetUniformLocation(program, uniformName.str().c_str());
12775             EXPECT_NE(samplerLocation, -1);
12776             glUniform1i(samplerLocation, textureUnit);
12777         }
12778     }
12779     ASSERT_GL_NO_ERROR();
12780 
12781     glDispatchCompute(1, 1, 1);
12782     EXPECT_GL_NO_ERROR();
12783 
12784     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
12785 
12786     // read back
12787     const GLuint *ptr = reinterpret_cast<const GLuint *>(
12788         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
12789     EXPECT_EQ(ptr[0], 1u);
12790 
12791     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
12792 }
12793 
12794 // Test that array of array of samplers used as function parameter with an index that has a
12795 // side-effect works.
TEST_P(GLSLTest_ES31,ArrayOfArrayOfSamplerAsFunctionParameterIndexedWithSideEffect)12796 TEST_P(GLSLTest_ES31, ArrayOfArrayOfSamplerAsFunctionParameterIndexedWithSideEffect)
12797 {
12798     // http://anglebug.com/42264082
12799     ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
12800 
12801     // anglebug.com/42262476 - no sampler array params on Android
12802     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
12803 
12804     // Skip if EXT_gpu_shader5 is not enabled.
12805     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
12806 
12807     constexpr char kComputeShader[] = R"(#version 310 es
12808 #extension GL_EXT_gpu_shader5 : require
12809 
12810 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
12811 
12812 layout(binding = 1, std430) buffer Output {
12813   uint success;
12814 } outbuf;
12815 
12816 uniform sampler2D smplr[2][3];
12817 layout(binding=0) uniform atomic_uint ac;
12818 
12819 bool sampler1DAndAtomicCounter(uvec3 sExpect, in sampler2D s[3], in atomic_uint a, uint aExpect)
12820 {
12821     uvec3 sResult = uvec3(uint(texture(s[0], vec2(0.5, 0.5)).x * 255.0),
12822                           uint(texture(s[1], vec2(0.5, 0.5)).x * 255.0),
12823                           uint(texture(s[2], vec2(0.5, 0.5)).x * 255.0));
12824     uint aResult = atomicCounter(a);
12825 
12826     return sExpect == sResult && aExpect == aResult;
12827 }
12828 
12829 bool sampler2DAndAtomicCounter(in sampler2D s[2][3], uint aInitial, in atomic_uint a)
12830 {
12831     bool success = true;
12832     success = sampler1DAndAtomicCounter(uvec3(0, 127, 255),
12833                     s[atomicCounterIncrement(ac)], a, aInitial + 1u) && success;
12834     success = sampler1DAndAtomicCounter(uvec3(31, 63, 191),
12835                     s[atomicCounterIncrement(ac)], a, aInitial + 2u) && success;
12836     return success;
12837 }
12838 
12839 void main(void)
12840 {
12841     outbuf.success = uint(sampler2DAndAtomicCounter(smplr, 0u, ac));
12842 }
12843 )";
12844     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
12845     EXPECT_GL_NO_ERROR();
12846 
12847     glUseProgram(program);
12848 
12849     unsigned int outputInitData = 0x12345678u;
12850     GLBuffer outputBuffer;
12851     glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
12852     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
12853     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
12854     EXPECT_GL_NO_ERROR();
12855 
12856     unsigned int acData = 0u;
12857     GLBuffer atomicCounterBuffer;
12858     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
12859     glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(acData), &acData, GL_STATIC_DRAW);
12860     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
12861     EXPECT_GL_NO_ERROR();
12862 
12863     const std::array<GLColor, 6> kTextureData = {
12864         GLColor(0, 0, 0, 0),  GLColor(127, 0, 0, 0), GLColor(255, 0, 0, 0),
12865         GLColor(31, 0, 0, 0), GLColor(63, 0, 0, 0),  GLColor(191, 0, 0, 0),
12866     };
12867     GLTexture textures[2][3];
12868 
12869     for (int dim1 = 0; dim1 < 2; ++dim1)
12870     {
12871         for (int dim2 = 0; dim2 < 3; ++dim2)
12872         {
12873             int textureUnit = dim1 * 3 + dim2;
12874             glActiveTexture(GL_TEXTURE0 + textureUnit);
12875             glBindTexture(GL_TEXTURE_2D, textures[dim1][dim2]);
12876             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
12877                          &kTextureData[textureUnit]);
12878             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12879             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12880 
12881             std::stringstream uniformName;
12882             uniformName << "smplr[" << dim1 << "][" << dim2 << "]";
12883             GLint samplerLocation = glGetUniformLocation(program, uniformName.str().c_str());
12884             EXPECT_NE(samplerLocation, -1);
12885             glUniform1i(samplerLocation, textureUnit);
12886         }
12887     }
12888     ASSERT_GL_NO_ERROR();
12889 
12890     glDispatchCompute(1, 1, 1);
12891     EXPECT_GL_NO_ERROR();
12892 
12893     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
12894 
12895     // read back
12896     const GLuint *ptr = reinterpret_cast<const GLuint *>(
12897         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
12898     EXPECT_EQ(ptr[0], 1u);
12899 
12900     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
12901 }
12902 
testArrayOfArrayOfSamplerDynamicIndex(const APIExtensionVersion usedExtension)12903 void GLSLTest_ES31::testArrayOfArrayOfSamplerDynamicIndex(const APIExtensionVersion usedExtension)
12904 {
12905     ASSERT(usedExtension == APIExtensionVersion::EXT || usedExtension == APIExtensionVersion::OES);
12906 
12907     int maxTextureImageUnits = 0;
12908     glGetIntegerv(GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
12909     ANGLE_SKIP_TEST_IF(maxTextureImageUnits < 24);
12910 
12911     // anglebug.com/42262476 - no sampler array params on Android
12912     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
12913 
12914     // http://anglebug.com/42264082
12915     ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
12916 
12917     std::string computeShader;
12918     constexpr char kGLSLVersion[]  = R"(#version 310 es
12919 )";
12920     constexpr char kGPUShaderEXT[] = R"(#extension GL_EXT_gpu_shader5 : require
12921 )";
12922     constexpr char kGPUShaderOES[] = R"(#extension GL_OES_gpu_shader5 : require
12923 )";
12924 
12925     computeShader.append(kGLSLVersion);
12926     if (usedExtension == APIExtensionVersion::EXT)
12927     {
12928         computeShader.append(kGPUShaderEXT);
12929     }
12930     else
12931     {
12932         computeShader.append(kGPUShaderOES);
12933     }
12934 
12935     constexpr char kComputeShaderBody[] = R"(
12936 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
12937 
12938 layout(binding = 1, std430) buffer Output {
12939 uint success;
12940 } outbuf;
12941 
12942 uniform sampler2D smplr[2][3][4];
12943 layout(binding=0) uniform atomic_uint ac;
12944 
12945 bool sampler1DAndAtomicCounter(uvec4 sExpect, in sampler2D s[4], in atomic_uint a, uint aExpect)
12946 {
12947 uvec4 sResult = uvec4(uint(texture(s[0], vec2(0.5, 0.5)).x * 255.0),
12948                       uint(texture(s[1], vec2(0.5, 0.5)).x * 255.0),
12949                       uint(texture(s[2], vec2(0.5, 0.5)).x * 255.0),
12950                       uint(texture(s[3], vec2(0.5, 0.5)).x * 255.0));
12951 uint aResult = atomicCounter(a);
12952 
12953 return sExpect == sResult && aExpect == aResult;
12954 }
12955 
12956 bool sampler3DAndAtomicCounter(in sampler2D s[2][3][4], uint aInitial, in atomic_uint a)
12957 {
12958 bool success = true;
12959 // [0][0]
12960 success = sampler1DAndAtomicCounter(uvec4(0, 8, 16, 24),
12961                 s[atomicCounterIncrement(ac)][0], a, aInitial + 1u) && success;
12962 // [1][0]
12963 success = sampler1DAndAtomicCounter(uvec4(96, 104, 112, 120),
12964                 s[atomicCounterIncrement(ac)][0], a, aInitial + 2u) && success;
12965 // [0][1]
12966 success = sampler1DAndAtomicCounter(uvec4(32, 40, 48, 56),
12967                 s[0][atomicCounterIncrement(ac) - 1u], a, aInitial + 3u) && success;
12968 // [0][2]
12969 success = sampler1DAndAtomicCounter(uvec4(64, 72, 80, 88),
12970                 s[0][atomicCounterIncrement(ac) - 1u], a, aInitial + 4u) && success;
12971 // [1][1]
12972 success = sampler1DAndAtomicCounter(uvec4(128, 136, 144, 152),
12973                 s[1][atomicCounterIncrement(ac) - 3u], a, aInitial + 5u) && success;
12974 // [1][2]
12975 uint acValue = atomicCounterIncrement(ac);  // Returns 5
12976 success = sampler1DAndAtomicCounter(uvec4(160, 168, 176, 184),
12977                 s[acValue - 4u][atomicCounterIncrement(ac) - 4u], a, aInitial + 7u) && success;
12978 
12979 return success;
12980 }
12981 
12982 void main(void)
12983 {
12984 outbuf.success = uint(sampler3DAndAtomicCounter(smplr, 0u, ac));
12985 }
12986 )";
12987     computeShader.append(kComputeShaderBody);
12988 
12989     ANGLE_GL_COMPUTE_PROGRAM(program, computeShader.c_str());
12990     EXPECT_GL_NO_ERROR();
12991 
12992     glUseProgram(program);
12993 
12994     unsigned int outputInitData = 0x12345678u;
12995     GLBuffer outputBuffer;
12996     glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
12997     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
12998     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
12999     EXPECT_GL_NO_ERROR();
13000 
13001     unsigned int acData = 0u;
13002     GLBuffer atomicCounterBuffer;
13003     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
13004     glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(acData), &acData, GL_STATIC_DRAW);
13005     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
13006     EXPECT_GL_NO_ERROR();
13007 
13008     const std::array<GLColor, 24> kTextureData = {
13009         GLColor(0, 0, 0, 0),   GLColor(8, 0, 0, 0),   GLColor(16, 0, 0, 0),  GLColor(24, 0, 0, 0),
13010         GLColor(32, 0, 0, 0),  GLColor(40, 0, 0, 0),  GLColor(48, 0, 0, 0),  GLColor(56, 0, 0, 0),
13011         GLColor(64, 0, 0, 0),  GLColor(72, 0, 0, 0),  GLColor(80, 0, 0, 0),  GLColor(88, 0, 0, 0),
13012         GLColor(96, 0, 0, 0),  GLColor(104, 0, 0, 0), GLColor(112, 0, 0, 0), GLColor(120, 0, 0, 0),
13013         GLColor(128, 0, 0, 0), GLColor(136, 0, 0, 0), GLColor(144, 0, 0, 0), GLColor(152, 0, 0, 0),
13014         GLColor(160, 0, 0, 0), GLColor(168, 0, 0, 0), GLColor(176, 0, 0, 0), GLColor(184, 0, 0, 0),
13015     };
13016     GLTexture textures[2][3][4];
13017 
13018     for (int dim1 = 0; dim1 < 2; ++dim1)
13019     {
13020         for (int dim2 = 0; dim2 < 3; ++dim2)
13021         {
13022             for (int dim3 = 0; dim3 < 4; ++dim3)
13023             {
13024                 int textureUnit = (dim1 * 3 + dim2) * 4 + dim3;
13025                 glActiveTexture(GL_TEXTURE0 + textureUnit);
13026                 glBindTexture(GL_TEXTURE_2D, textures[dim1][dim2][dim3]);
13027                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
13028                              &kTextureData[textureUnit]);
13029                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
13030                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
13031 
13032                 std::stringstream uniformName;
13033                 uniformName << "smplr[" << dim1 << "][" << dim2 << "][" << dim3 << "]";
13034                 GLint samplerLocation = glGetUniformLocation(program, uniformName.str().c_str());
13035                 EXPECT_NE(samplerLocation, -1);
13036                 glUniform1i(samplerLocation, textureUnit);
13037             }
13038         }
13039     }
13040     ASSERT_GL_NO_ERROR();
13041 
13042     glDispatchCompute(1, 1, 1);
13043     EXPECT_GL_NO_ERROR();
13044 
13045     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
13046 
13047     // read back
13048     const GLuint *ptr = reinterpret_cast<const GLuint *>(
13049         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
13050     EXPECT_EQ(ptr[0], 1u);
13051 
13052     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
13053 }
13054 
13055 // Test that array of array of samplers can be indexed correctly with dynamic indices.
TEST_P(GLSLTest_ES31,ArrayOfArrayOfSamplerDynamicIndexEXT)13056 TEST_P(GLSLTest_ES31, ArrayOfArrayOfSamplerDynamicIndexEXT)
13057 {
13058     // Skip if EXT_gpu_shader5 is not enabled.
13059     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
13060     testArrayOfArrayOfSamplerDynamicIndex(APIExtensionVersion::EXT);
13061 }
13062 
13063 // Test that array of array of samplers can be indexed correctly with dynamic indices.
TEST_P(GLSLTest_ES31,ArrayOfArrayOfSamplerDynamicIndexOES)13064 TEST_P(GLSLTest_ES31, ArrayOfArrayOfSamplerDynamicIndexOES)
13065 {
13066     // Skip if OES_gpu_shader5 is not enabled.
13067     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_gpu_shader5"));
13068     testArrayOfArrayOfSamplerDynamicIndex(APIExtensionVersion::OES);
13069 }
13070 
13071 // Test that array of array of samplers is handled correctly with the comma operator.
TEST_P(GLSLTest,ArrayOfArrayOfSamplerVsComma)13072 TEST_P(GLSLTest, ArrayOfArrayOfSamplerVsComma)
13073 {
13074     int maxTextureImageUnits = 0;
13075     glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
13076 
13077     ANGLE_SKIP_TEST_IF(maxTextureImageUnits < 6);
13078 
13079     constexpr char kVS[] = R"(uniform struct {
13080   sampler2D s1, s2[3];
13081 } s[2];
13082 
13083 void main()
13084 {
13085     ++gl_Position, s[1].s1;
13086 })";
13087     ANGLE_GL_PROGRAM(program, kVS, essl1_shaders::fs::Red());
13088     EXPECT_GL_NO_ERROR();
13089 }
13090 
13091 // Test that array of array of samplers can be indexed correctly with dynamic indices.  Uses
13092 // samplers in structs.
TEST_P(GLSLTest_ES31,ArrayOfArrayOfSamplerInStructDynamicIndex)13093 TEST_P(GLSLTest_ES31, ArrayOfArrayOfSamplerInStructDynamicIndex)
13094 {
13095     // Skip if EXT_gpu_shader5 is not enabled.
13096     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
13097 
13098     int maxTextureImageUnits = 0;
13099     glGetIntegerv(GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
13100     ANGLE_SKIP_TEST_IF(maxTextureImageUnits < 24);
13101 
13102     // http://anglebug.com/42263641
13103     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
13104 
13105     // anglebug.com/42262476 - no sampler array params on Android
13106     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
13107 
13108     // http://anglebug.com/42264082
13109     ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsOpenGL());
13110 
13111     constexpr char kComputeShader[] = R"(#version 310 es
13112 #extension GL_EXT_gpu_shader5 : require
13113 
13114 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
13115 
13116 layout(binding = 1, std430) buffer Output {
13117   uint success;
13118 } outbuf;
13119 
13120 struct I
13121 {
13122     uint index;
13123 };
13124 
13125 struct S
13126 {
13127     sampler2D smplr[4];
13128     I nested;
13129 };
13130 
13131 struct T
13132 {
13133     S nested[3];
13134     uint tIndex;
13135 };
13136 
13137 uniform T u[2];
13138 
13139 uint getValue(in sampler2D s)
13140 {
13141     return uint(texture(s, vec2(0.5, 0.5)).x * 255.0);
13142 }
13143 
13144 bool sampler1DTest(uvec4 sExpect, in sampler2D s[4])
13145 {
13146     uvec4 sResult = uvec4(getValue(s[0]), getValue(s[1]),
13147                           getValue(s[2]), getValue(s[3]));
13148 
13149     return sExpect == sResult;
13150 }
13151 
13152 bool samplerTest(T t, uint N)
13153 {
13154     // u[N].tIndex == 0 + N*4
13155     // u[N].nested[0].nested.index == 1 + N*4
13156     // u[N].nested[1].nested.index == 2 + N*4
13157     // u[N].nested[2].nested.index == 3 + N*4
13158 
13159     uvec4 colorOffset = N * 3u * 4u * uvec4(8);
13160 
13161     bool success = true;
13162     // [N][0]
13163     success = sampler1DTest(uvec4(0, 8, 16, 24) + colorOffset,
13164                     t.nested[t.nested[0].nested.index - t.tIndex - 1u].smplr) && success;
13165     // [N][1]
13166     success = sampler1DTest(uvec4(32, 40, 48, 56) + colorOffset,
13167                     t.nested[t.nested[1].nested.index - t.tIndex - 1u].smplr) && success;
13168     // [N][2]
13169     success = sampler1DTest(uvec4(64, 72, 80, 88) + colorOffset,
13170                     t.nested[t.nested[2].nested.index - t.tIndex - 1u].smplr) && success;
13171 
13172     return success;
13173 }
13174 
13175 bool uniformTest(T t, uint N)
13176 {
13177     // Also verify that expressions that involve structs-with-samplers are correct when not
13178     // referecing the sampler.
13179 
13180     bool success = true;
13181     success = (t.nested[0].nested.index - t.tIndex == 1u) && success;
13182     success = (t.nested[1].nested.index - t.tIndex == 2u) && success;
13183     success = (t.nested[2].nested.index - t.tIndex == 3u) && success;
13184 
13185     success = (t.nested[t.nested[0].nested.index - t.tIndex - 1u].nested.index - t.tIndex == 1u)
13186                 && success;
13187     success = (t.nested[t.nested[0].nested.index - t.tIndex     ].nested.index - t.tIndex == 2u)
13188                 && success;
13189     success = (t.nested[t.nested[0].nested.index - t.tIndex + 1u].nested.index - t.tIndex == 3u)
13190                 && success;
13191 
13192     success = (t.nested[
13193                           t.nested[
13194                                      t.nested[2].nested.index - t.tIndex - 1u  // 2
13195                                   ].nested.index - t.tIndex - 2u               // 1
13196                        ].nested.index - t.tIndex                               // 2
13197                 == 2u) && success;
13198 
13199     return success;
13200 }
13201 
13202 void main(void)
13203 {
13204     bool success = samplerTest(u[0], 0u) && samplerTest(u[1], 1u)
13205                     && uniformTest(u[0], 0u) && uniformTest(u[1], 1u);
13206     outbuf.success = uint(success);
13207 }
13208 )";
13209     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
13210     EXPECT_GL_NO_ERROR();
13211 
13212     glUseProgram(program);
13213 
13214     unsigned int outputInitData = 0x12345678u;
13215     GLBuffer outputBuffer;
13216     glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
13217     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
13218     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
13219     EXPECT_GL_NO_ERROR();
13220 
13221     const std::array<GLColor, 24> kTextureData = {
13222         GLColor(0, 0, 0, 0),   GLColor(8, 0, 0, 0),   GLColor(16, 0, 0, 0),  GLColor(24, 0, 0, 0),
13223         GLColor(32, 0, 0, 0),  GLColor(40, 0, 0, 0),  GLColor(48, 0, 0, 0),  GLColor(56, 0, 0, 0),
13224         GLColor(64, 0, 0, 0),  GLColor(72, 0, 0, 0),  GLColor(80, 0, 0, 0),  GLColor(88, 0, 0, 0),
13225         GLColor(96, 0, 0, 0),  GLColor(104, 0, 0, 0), GLColor(112, 0, 0, 0), GLColor(120, 0, 0, 0),
13226         GLColor(128, 0, 0, 0), GLColor(136, 0, 0, 0), GLColor(144, 0, 0, 0), GLColor(152, 0, 0, 0),
13227         GLColor(160, 0, 0, 0), GLColor(168, 0, 0, 0), GLColor(176, 0, 0, 0), GLColor(184, 0, 0, 0),
13228     };
13229     GLTexture textures[2][3][4];
13230 
13231     for (int dim1 = 0; dim1 < 2; ++dim1)
13232     {
13233         for (int dim2 = 0; dim2 < 3; ++dim2)
13234         {
13235             for (int dim3 = 0; dim3 < 4; ++dim3)
13236             {
13237                 int textureUnit = (dim1 * 3 + dim2) * 4 + dim3;
13238                 glActiveTexture(GL_TEXTURE0 + textureUnit);
13239                 glBindTexture(GL_TEXTURE_2D, textures[dim1][dim2][dim3]);
13240                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
13241                              &kTextureData[textureUnit]);
13242                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
13243                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
13244 
13245                 std::stringstream uniformName;
13246                 uniformName << "u[" << dim1 << "].nested[" << dim2 << "].smplr[" << dim3 << "]";
13247                 GLint samplerLocation = glGetUniformLocation(program, uniformName.str().c_str());
13248                 EXPECT_NE(samplerLocation, -1);
13249                 glUniform1i(samplerLocation, textureUnit);
13250             }
13251 
13252             std::stringstream uniformName;
13253             uniformName << "u[" << dim1 << "].nested[" << dim2 << "].nested.index";
13254             GLint nestedIndexLocation = glGetUniformLocation(program, uniformName.str().c_str());
13255             EXPECT_NE(nestedIndexLocation, -1);
13256             glUniform1ui(nestedIndexLocation, dim1 * 4 + dim2 + 1);
13257         }
13258 
13259         std::stringstream uniformName;
13260         uniformName << "u[" << dim1 << "].tIndex";
13261         GLint indexLocation = glGetUniformLocation(program, uniformName.str().c_str());
13262         EXPECT_NE(indexLocation, -1);
13263         glUniform1ui(indexLocation, dim1 * 4);
13264     }
13265     ASSERT_GL_NO_ERROR();
13266 
13267     glDispatchCompute(1, 1, 1);
13268     EXPECT_GL_NO_ERROR();
13269 
13270     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
13271 
13272     // read back
13273     const GLuint *ptr = reinterpret_cast<const GLuint *>(
13274         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
13275     EXPECT_EQ(ptr[0], 1u);
13276 
13277     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
13278 }
13279 
13280 // Test that array of array of samplers work when indexed with an expression that's derived from an
13281 // array of array of samplers.
TEST_P(GLSLTest_ES31,ArrayOfArrayOfSamplerIndexedWithArrayOfArrayOfSamplers)13282 TEST_P(GLSLTest_ES31, ArrayOfArrayOfSamplerIndexedWithArrayOfArrayOfSamplers)
13283 {
13284     // Skip if EXT_gpu_shader5 is not enabled.
13285     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
13286 
13287     // anglebug.com/42262476 - no sampler array params on Android
13288     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
13289 
13290     constexpr char kComputeShader[] = R"(#version 310 es
13291 #extension GL_EXT_gpu_shader5 : require
13292 
13293 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
13294 
13295 layout(binding = 1, std430) buffer Output {
13296   uint success;
13297 } outbuf;
13298 
13299 uniform sampler2D smplr[2][3];
13300 
13301 uint getValue(in sampler2D s)
13302 {
13303     return uint(texture(s, vec2(0.5, 0.5)).x * 255.0);
13304 }
13305 
13306 bool runTest(in sampler2D s[2][3])
13307 {
13308     // s[0][0] should contain 2
13309     // s[0][1] should contain 0
13310     // s[0][2] should contain 1
13311     // s[1][0] should contain 1
13312     // s[1][1] should contain 2
13313     // s[1][2] should contain 0
13314 
13315     uint result = getValue(
13316                        s[
13317                            getValue(
13318                                 s[
13319                                     getValue(s[0][1])   // 0
13320                                 ][
13321                                     getValue(s[0][0])   // 2
13322                                 ]
13323                            )                      // s[0][2] -> 1
13324                        ][
13325                            getValue(
13326                                 s[
13327                                     getValue(s[1][0])   // 1
13328                                 ][
13329                                     getValue(s[1][1])   // 2
13330                                 ]
13331                            )                      // s[1][2] -> 0
13332                        ]
13333                   );                      // s[1][0] -> 1
13334 
13335     return result == 1u;
13336 }
13337 
13338 void main(void)
13339 {
13340     outbuf.success = uint(runTest(smplr));
13341 }
13342 )";
13343     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
13344     EXPECT_GL_NO_ERROR();
13345 
13346     glUseProgram(program);
13347 
13348     unsigned int outputInitData = 0x12345678u;
13349     GLBuffer outputBuffer;
13350     glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
13351     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(outputInitData), &outputInitData, GL_STATIC_DRAW);
13352     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outputBuffer);
13353     EXPECT_GL_NO_ERROR();
13354 
13355     const std::array<GLColor, 6> kTextureData = {
13356         GLColor(2, 0, 0, 0), GLColor(0, 0, 0, 0), GLColor(1, 0, 0, 0),
13357         GLColor(1, 0, 0, 0), GLColor(2, 0, 0, 0), GLColor(0, 0, 0, 0),
13358     };
13359     GLTexture textures[2][3];
13360 
13361     for (int dim1 = 0; dim1 < 2; ++dim1)
13362     {
13363         for (int dim2 = 0; dim2 < 3; ++dim2)
13364         {
13365             int textureUnit = dim1 * 3 + dim2;
13366             glActiveTexture(GL_TEXTURE0 + textureUnit);
13367             glBindTexture(GL_TEXTURE_2D, textures[dim1][dim2]);
13368             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
13369                          &kTextureData[textureUnit]);
13370             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
13371             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
13372 
13373             std::stringstream uniformName;
13374             uniformName << "smplr[" << dim1 << "][" << dim2 << "]";
13375             GLint samplerLocation = glGetUniformLocation(program, uniformName.str().c_str());
13376             EXPECT_NE(samplerLocation, -1);
13377             glUniform1i(samplerLocation, textureUnit);
13378         }
13379     }
13380     ASSERT_GL_NO_ERROR();
13381 
13382     glDispatchCompute(1, 1, 1);
13383     EXPECT_GL_NO_ERROR();
13384 
13385     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
13386 
13387     // read back
13388     const GLuint *ptr = reinterpret_cast<const GLuint *>(
13389         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(outputInitData), GL_MAP_READ_BIT));
13390     EXPECT_EQ(ptr[0], 1u);
13391 
13392     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
13393 }
13394 
13395 // Test that multiple nested assignments are handled correctly.
TEST_P(GLSLTest_ES31,MixedRowAndColumnMajorMatrices_WriteSideEffect)13396 TEST_P(GLSLTest_ES31, MixedRowAndColumnMajorMatrices_WriteSideEffect)
13397 {
13398     // http://anglebug.com/42262475
13399     ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGL());
13400 
13401     // Fails on windows AMD on GL: http://anglebug.com/42262482
13402     ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL() && IsAMD());
13403     // http://anglebug.com/42263924
13404     ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
13405 
13406     // Fails on D3D due to mistranslation: http://anglebug.com/42262486
13407     ANGLE_SKIP_TEST_IF(IsD3D11());
13408 
13409     constexpr char kCS[] = R"(#version 310 es
13410 precision highp float;
13411 layout(local_size_x=1) in;
13412 
13413 layout(std140, column_major) uniform Ubo
13414 {
13415     mat4 m1;
13416     layout(row_major) mat4 m2;
13417 } ubo;
13418 
13419 layout(std140, row_major, binding = 0) buffer Ssbo
13420 {
13421     layout(column_major) mat4 m1;
13422     mat4 m2;
13423 } ssbo;
13424 
13425 layout(std140, binding = 1) buffer Result
13426 {
13427     uint success;
13428 } resultOut;
13429 
13430 void main()
13431 {
13432     bool result = true;
13433 
13434     // Only assign to SSBO from a single invocation.
13435     if (gl_GlobalInvocationID.x == 0u)
13436     {
13437         if ((ssbo.m2 = ssbo.m1 = ubo.m1) != ubo.m2)
13438         {
13439             result = false;
13440         }
13441 
13442         resultOut.success = uint(result);
13443     }
13444 })";
13445 
13446     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
13447     EXPECT_GL_NO_ERROR();
13448 
13449     constexpr size_t kMatrixCount                                     = 2;
13450     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
13451         {4, 4},
13452         {4, 4},
13453     };
13454     constexpr bool kMatrixIsColMajor[kMatrixCount] = {
13455         true,
13456         false,
13457     };
13458 
13459     float data[kMatrixCount * 4 * 4]  = {};
13460     float zeros[kMatrixCount * 4 * 4] = {};
13461 
13462     const uint32_t size =
13463         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
13464 
13465     GLBuffer ubo, ssbo;
13466 
13467     InitBuffer(program, "Ubo", ubo, 0, data, size, true);
13468     InitBuffer(program, "Ssbo", ssbo, 0, zeros, size, false);
13469     EXPECT_GL_NO_ERROR();
13470 
13471     GLBuffer outputBuffer;
13472     CreateOutputBuffer(&outputBuffer, 1);
13473 
13474     glUseProgram(program);
13475     glDispatchCompute(1, 1, 1);
13476     EXPECT_GL_NO_ERROR();
13477     EXPECT_TRUE(VerifySuccess(outputBuffer));
13478 
13479     EXPECT_TRUE(VerifyBuffer(ssbo, data, size));
13480 }
13481 
13482 // Test that assignments to array of array of matrices are handled correctly.
TEST_P(GLSLTest_ES31,MixedRowAndColumnMajorMatrices_WriteArrayOfArray)13483 TEST_P(GLSLTest_ES31, MixedRowAndColumnMajorMatrices_WriteArrayOfArray)
13484 {
13485     // Fails on windows AMD on GL: http://anglebug.com/42262482
13486     ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL() && IsAMD());
13487     // http://anglebug.com/42263924
13488     ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
13489 
13490     // Fails on D3D due to mistranslation: http://anglebug.com/42262486
13491     ANGLE_SKIP_TEST_IF(IsD3D11());
13492 
13493     // Fails compiling shader on Android/Vulkan.  http://anglebug.com/42262919
13494     ANGLE_SKIP_TEST_IF(IsAndroid() && IsVulkan());
13495 
13496     // Fails on ARM on Vulkan.  http://anglebug.com/42263107
13497     ANGLE_SKIP_TEST_IF(IsARM() && IsVulkan());
13498 
13499     constexpr char kCS[] = R"(#version 310 es
13500 precision highp float;
13501 layout(local_size_x=1) in;
13502 
13503 layout(std140, column_major) uniform Ubo
13504 {
13505     mat4 m1;
13506     layout(row_major) mat4 m2[2][3];
13507 } ubo;
13508 
13509 layout(std140, row_major, binding = 0) buffer Ssbo
13510 {
13511     layout(column_major) mat4 m1;
13512     mat4 m2[2][3];
13513 } ssbo;
13514 
13515 layout(std140, binding = 1) buffer Result
13516 {
13517     uint success;
13518 } resultOut;
13519 
13520 void main()
13521 {
13522     bool result = true;
13523 
13524     // Only assign to SSBO from a single invocation.
13525     if (gl_GlobalInvocationID.x == 0u)
13526     {
13527         ssbo.m1 = ubo.m1;
13528         ssbo.m2 = ubo.m2;
13529 
13530         resultOut.success = uint(result);
13531     }
13532 })";
13533 
13534     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
13535     EXPECT_GL_NO_ERROR();
13536 
13537     constexpr size_t kMatrixCount                                     = 7;
13538     constexpr std::pair<uint32_t, uint32_t> kMatrixDims[kMatrixCount] = {
13539         {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 4},
13540     };
13541     constexpr bool kMatrixIsColMajor[kMatrixCount] = {
13542         true, false, false, false, false, false, false,
13543     };
13544 
13545     float data[kMatrixCount * 4 * 4]  = {};
13546     float zeros[kMatrixCount * 4 * 4] = {};
13547 
13548     const uint32_t size =
13549         FillBuffer(kMatrixDims, kMatrixIsColMajor, kMatrixCount, data, false, false);
13550 
13551     GLBuffer ubo, ssbo;
13552 
13553     InitBuffer(program, "Ubo", ubo, 0, data, size, true);
13554     InitBuffer(program, "Ssbo", ssbo, 0, zeros, size, false);
13555     EXPECT_GL_NO_ERROR();
13556 
13557     GLBuffer outputBuffer;
13558     CreateOutputBuffer(&outputBuffer, 1);
13559 
13560     glUseProgram(program);
13561     glDispatchCompute(1, 1, 1);
13562     EXPECT_GL_NO_ERROR();
13563     EXPECT_TRUE(VerifySuccess(outputBuffer));
13564 
13565     EXPECT_TRUE(VerifyBuffer(ssbo, data, size));
13566 }
13567 
13568 // Verify that types used differently (in different block storages, differently qualified etc) work
13569 // when copied around.
TEST_P(GLSLTest_ES31,TypesUsedInDifferentBlockStorages)13570 TEST_P(GLSLTest_ES31, TypesUsedInDifferentBlockStorages)
13571 {
13572     constexpr char kCS[] = R"(#version 310 es
13573 precision highp float;
13574 layout(local_size_x=1) in;
13575 
13576 struct Inner
13577 {
13578     mat3x2 m;
13579     float f[3];
13580     uvec2 u[2][4];
13581     ivec3 i;
13582     mat2x3 m2[3][2];
13583 };
13584 
13585 struct Outer
13586 {
13587     Inner i[2];
13588 };
13589 
13590 layout(std140, column_major) uniform Ubo140c
13591 {
13592     mat2 m;
13593     layout(row_major) Outer o;
13594 } ubo140cIn;
13595 
13596 layout(std430, row_major, binding = 0) buffer Ubo430r
13597 {
13598     mat2 m;
13599     layout(column_major) Outer o;
13600 } ubo430rIn;
13601 
13602 layout(std140, column_major, binding = 1) buffer Ssbo140c
13603 {
13604     layout(row_major) mat2 m[2];
13605     Outer o;
13606     layout(row_major) Inner i;
13607 } ssbo140cOut;
13608 
13609 layout(std430, row_major, binding = 2) buffer Ssbo430r
13610 {
13611     layout(column_major) mat2 m[2];
13612     Outer o;
13613     layout(column_major) Inner i;
13614 } ssbo430rOut;
13615 
13616 void writeArgToStd140(uvec2 u[2][4], int innerIndex)
13617 {
13618     ssbo140cOut.o.i[innerIndex].u = u;
13619 }
13620 
13621 void writeBlockArgToStd140(Inner i, int innerIndex)
13622 {
13623     ssbo140cOut.o.i[innerIndex] = i;
13624 }
13625 
13626 mat2x3[3][2] readFromStd140(int innerIndex)
13627 {
13628     return ubo140cIn.o.i[0].m2;
13629 }
13630 
13631 Inner readBlockFromStd430(int innerIndex)
13632 {
13633     return ubo430rIn.o.i[innerIndex];
13634 }
13635 
13636 void copyFromStd140(out Inner i)
13637 {
13638     i = ubo140cIn.o.i[1];
13639 }
13640 
13641 void main(){
13642     // Directly copy from one layout to another.
13643     ssbo140cOut.m[0] = ubo140cIn.m;
13644     ssbo140cOut.m[1] = ubo430rIn.m;
13645     ssbo140cOut.o.i[0].m = ubo140cIn.o.i[0].m;
13646     ssbo140cOut.o.i[0].f = ubo140cIn.o.i[0].f;
13647     ssbo140cOut.o.i[0].i = ubo140cIn.o.i[0].i;
13648 
13649     // Read from block and pass to function.
13650     writeArgToStd140(ubo140cIn.o.i[0].u, 0);
13651     writeBlockArgToStd140(ubo430rIn.o.i[0], 1);
13652 
13653     // Have function return value read from block.
13654     ssbo140cOut.o.i[0].m2 = readFromStd140(0);
13655 
13656     // Have function fill in value as out parameter.
13657     copyFromStd140(ssbo140cOut.i);
13658 
13659     // Initialize local variable.
13660     mat2 mStd140 = ubo140cIn.m;
13661 
13662     // Copy to variable, through multiple assignments.
13663     mat2 mStd430, temp;
13664     mStd430 = temp = ubo430rIn.m;
13665 
13666     // Copy from local variable
13667     ssbo430rOut.m[0] = mStd140;
13668     ssbo430rOut.m[1] = mStd430;
13669 
13670     // Construct from struct.
13671     Inner iStd140 = ubo140cIn.o.i[1];
13672     Outer oStd140 = Outer(Inner[2](iStd140, ubo430rIn.o.i[1]));
13673 
13674     // Copy struct from local variable.
13675     ssbo430rOut.o = oStd140;
13676 
13677     // Construct from arrays
13678     Inner iStd430 = Inner(ubo430rIn.o.i[1].m,
13679                           ubo430rIn.o.i[1].f,
13680                           ubo430rIn.o.i[1].u,
13681                           ubo430rIn.o.i[1].i,
13682                           ubo430rIn.o.i[1].m2);
13683     ssbo430rOut.i = iStd430;
13684 })";
13685 
13686     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
13687     EXPECT_GL_NO_ERROR();
13688 
13689     // Test data, laid out with padding (0) based on std140/std430 rules.
13690     // clang-format off
13691     const std::vector<float> ubo140cData = {
13692         // m (mat2, column-major)
13693         1, 2, 0, 0,     3, 4, 0, 0,
13694 
13695         // o.i[0].m (mat3x2, row-major)
13696         5, 7, 9, 0,     6, 8, 10, 0,
13697         // o.i[0].f (float[3])
13698         12, 0, 0, 0,    13, 0, 0, 0,    14, 0, 0, 0,
13699         // o.i[0].u (uvec2[2][4])
13700         15, 16, 0, 0,   17, 18, 0, 0,   19, 20, 0, 0,   21, 22, 0, 0,
13701         23, 24, 0, 0,   25, 26, 0, 0,   27, 28, 0, 0,   29, 30, 0, 0,
13702         // o.i[0].i (ivec3)
13703         31, 32, 33, 0,
13704         // o.i[0].m2 (mat2x3[3][2], row-major)
13705         34, 37, 0, 0,   35, 38, 0, 0,   36, 39, 0, 0,
13706         40, 43, 0, 0,   41, 44, 0, 0,   42, 45, 0, 0,
13707         46, 49, 0, 0,   47, 50, 0, 0,   48, 51, 0, 0,
13708         52, 55, 0, 0,   53, 56, 0, 0,   54, 57, 0, 0,
13709         58, 61, 0, 0,   59, 62, 0, 0,   60, 63, 0, 0,
13710         64, 67, 0, 0,   65, 68, 0, 0,   66, 69, 0, 0,
13711 
13712         // o.i[1].m (mat3x2, row-major)
13713         70, 72, 74, 0,     71, 73, 75, 0,
13714         // o.i[1].f (float[3])
13715         77, 0, 0, 0,    78, 0, 0, 0,    79, 0, 0, 0,
13716         // o.i[1].u (uvec2[2][4])
13717         80, 81, 0, 0,   82, 83, 0, 0,   84, 85, 0, 0,   86, 87, 0, 0,
13718         88, 89, 0, 0,   90, 91, 0, 0,   92, 93, 0, 0,   94, 95, 0, 0,
13719         // o.i[1].i (ivec3)
13720         96, 97, 98, 0,
13721         // o.i[1].m2 (mat2x3[3][2], row-major)
13722          99, 102, 0, 0,  100, 103, 0, 0,   101, 104, 0, 0,
13723         105, 108, 0, 0,  106, 109, 0, 0,   107, 110, 0, 0,
13724         111, 114, 0, 0,  112, 115, 0, 0,   113, 116, 0, 0,
13725         117, 120, 0, 0,  118, 121, 0, 0,   119, 122, 0, 0,
13726         123, 126, 0, 0,  124, 127, 0, 0,   125, 128, 0, 0,
13727         129, 132, 0, 0,  130, 133, 0, 0,   131, 134, 0, 0,
13728     };
13729     const std::vector<float> ubo430rData = {
13730         // m (mat2, row-major)
13731         135, 137,         136, 138,
13732 
13733         // o.i[0].m (mat3x2, column-major)
13734         139, 140,         141, 142,         143, 144,
13735         // o.i[0].f (float[3])
13736         146, 147, 148, 0,
13737         // o.i[0].u (uvec2[2][4])
13738         149, 150,         151, 152,         153, 154,         155, 156,
13739         157, 158,         159, 160,         161, 162,         163, 164, 0, 0,
13740         // o.i[0].i (ivec3)
13741         165, 166, 167, 0,
13742         // o.i[0].m2 (mat2x3[3][2], column-major)
13743         168, 169, 170, 0,   171, 172, 173, 0,
13744         174, 175, 176, 0,   177, 178, 179, 0,
13745         180, 181, 182, 0,   183, 184, 185, 0,
13746         186, 187, 188, 0,   189, 190, 191, 0,
13747         192, 193, 194, 0,   195, 196, 197, 0,
13748         198, 199, 200, 0,   201, 202, 203, 0,
13749 
13750         // o.i[1].m (mat3x2, column-major)
13751         204, 205,         206, 207,         208, 209,
13752         // o.i[1].f (float[3])
13753         211, 212, 213, 0,
13754         // o.i[1].u (uvec2[2][4])
13755         214, 215,         216, 217,         218, 219,         220, 221,
13756         222, 223,         224, 225,         226, 227,         228, 229, 0, 0,
13757         // o.i[1].i (ivec3)
13758         230, 231, 232, 0,
13759         // o.i[1].m2 (mat2x3[3][2], column-major)
13760         233, 234, 235, 0,   236, 237, 238, 0,
13761         239, 240, 241, 0,   242, 243, 244, 0,
13762         245, 246, 247, 0,   248, 249, 250, 0,
13763         251, 252, 253, 0,   254, 255, 256, 0,
13764         257, 258, 259, 0,   260, 261, 262, 0,
13765         263, 264, 265, 0,   266, 267, 268, 0,
13766     };
13767     const std::vector<float> ssbo140cExpect = {
13768         // m (mat2[2], row-major), m[0] copied from ubo140cIn.m, m[1] from ubo430rIn.m
13769         1, 3, 0, 0,     2, 4, 0, 0,
13770         135, 137, 0, 0, 136, 138, 0, 0,
13771 
13772         // o.i[0].m (mat3x2, column-major), copied from ubo140cIn.o.i[0].m
13773         5, 6, 0, 0,     7, 8, 0, 0,     9, 10, 0, 0,
13774         // o.i[0].f (float[3]), copied from ubo140cIn.o.i[0].f
13775         12, 0, 0, 0,    13, 0, 0, 0,    14, 0, 0, 0,
13776         // o.i[0].u (uvec2[2][4]), copied from ubo140cIn.o.i[0].u
13777         15, 16, 0, 0,   17, 18, 0, 0,   19, 20, 0, 0,   21, 22, 0, 0,
13778         23, 24, 0, 0,   25, 26, 0, 0,   27, 28, 0, 0,   29, 30, 0, 0,
13779         // o.i[0].i (ivec3), copied from ubo140cIn.o.i[0].i
13780         31, 32, 33, 0,
13781         // o.i[0].m2 (mat2x3[3][2], column-major), copied from ubo140cIn.o.i[0].m2
13782         34, 35, 36, 0,  37, 38, 39, 0,
13783         40, 41, 42, 0,  43, 44, 45, 0,
13784         46, 47, 48, 0,  49, 50, 51, 0,
13785         52, 53, 54, 0,  55, 56, 57, 0,
13786         58, 59, 60, 0,  61, 62, 63, 0,
13787         64, 65, 66, 0,  67, 68, 69, 0,
13788 
13789         // o.i[1].m (mat3x2, column-major), copied from ubo430rIn.o.i[0].m
13790         139, 140, 0, 0,   141, 142, 0, 0,   143, 144, 0, 0,
13791         // o.i[1].f (float[3]), copied from ubo430rIn.o.i[0].f
13792         146, 0, 0, 0,     147, 0, 0, 0,     148, 0, 0, 0,
13793         // o.i[1].u (uvec2[2][4]), copied from ubo430rIn.o.i[0].u
13794         149, 150, 0, 0,   151, 152, 0, 0,   153, 154, 0, 0,   155, 156, 0, 0,
13795         157, 158, 0, 0,   159, 160, 0, 0,   161, 162, 0, 0,   163, 164, 0, 0,
13796         // o.i[1].i (ivec3), copied from ubo430rIn.o.i[0].i
13797         165, 166, 167, 0,
13798         // o.i[1].m2 (mat2x3[3][2], column-major), copied from ubo430rIn.o.i[0].m2
13799         168, 169, 170, 0,   171, 172, 173, 0,
13800         174, 175, 176, 0,   177, 178, 179, 0,
13801         180, 181, 182, 0,   183, 184, 185, 0,
13802         186, 187, 188, 0,   189, 190, 191, 0,
13803         192, 193, 194, 0,   195, 196, 197, 0,
13804         198, 199, 200, 0,   201, 202, 203, 0,
13805 
13806         // i.m (mat3x2, row-major), copied from ubo140cIn.o.i[1].m
13807         70, 72, 74, 0,     71, 73, 75, 0,
13808         // i.f (float[3]), copied from ubo140cIn.o.i[1].f
13809         77, 0, 0, 0,    78, 0, 0, 0,    79, 0, 0, 0,
13810         // i.u (uvec2[2][4]), copied from ubo430rIn.o.i[1].u
13811         80, 81, 0, 0,   82, 83, 0, 0,   84, 85, 0, 0,   86, 87, 0, 0,
13812         88, 89, 0, 0,   90, 91, 0, 0,   92, 93, 0, 0,   94, 95, 0, 0,
13813         // i.i (ivec3), copied from ubo140cIn.o.i[1].i
13814         96, 97, 98, 0,
13815         // i.m2 (mat2x3[3][2], row-major), copied from ubo140cIn.o.i[1].m2
13816          99, 102, 0, 0,  100, 103, 0, 0,   101, 104, 0, 0,
13817         105, 108, 0, 0,  106, 109, 0, 0,   107, 110, 0, 0,
13818         111, 114, 0, 0,  112, 115, 0, 0,   113, 116, 0, 0,
13819         117, 120, 0, 0,  118, 121, 0, 0,   119, 122, 0, 0,
13820         123, 126, 0, 0,  124, 127, 0, 0,   125, 128, 0, 0,
13821         129, 132, 0, 0,  130, 133, 0, 0,   131, 134, 0, 0,
13822     };
13823     const std::vector<float> ssbo430rExpect = {
13824         // m (mat2[2], column-major), m[0] copied from ubo140cIn.m, m[1] from ubo430rIn.m
13825         1, 2,           3, 4,
13826         135, 136,       137, 138,
13827 
13828         // o.i[0].m (mat3x2, row-major), copied from ubo140cIn.o.i[1].m
13829         70, 72, 74, 0,  71, 73, 75, 0,
13830         // o.i[0].f (float[3]), copied from ubo140cIn.o.i[1].f
13831         77, 78, 79, 0,
13832         // o.i[0].u (uvec2[2][4]), copied from ubo140cIn.o.i[1].u
13833         80, 81,         82, 83,         84, 85,         86, 87,
13834         88, 89,         90, 91,         92, 93,         94, 95,
13835         // o.i[0].i (ivec3), copied from ubo140cIn.o.i[1].i
13836         96, 97, 98, 0,
13837         // o.i[0].m2 (mat2x3[3][2], row-major), copied from ubo140cIn.o.i[1].m2
13838          99, 102,        100, 103,         101, 104,
13839         105, 108,        106, 109,         107, 110,
13840         111, 114,        112, 115,         113, 116,
13841         117, 120,        118, 121,         119, 122,
13842         123, 126,        124, 127,         125, 128,
13843         129, 132,        130, 133,         131, 134,
13844 
13845         // o.i[1].m (mat3x2, row-major), copied from ubo430rIn.o.i[1].m
13846         204, 206, 208, 0,  205, 207, 209, 0,
13847         // o.i[1].f (float[3]), copied from ubo430rIn.o.i[1].f
13848         211, 212, 213, 0,
13849         // o.i[1].u (uvec2[2][4]), copied from ubo430rIn.o.i[1].u
13850         214, 215,         216, 217,         218, 219,         220, 221,
13851         222, 223,         224, 225,         226, 227,         228, 229,
13852         // o.i[1].i (ivec3), copied from ubo430rIn.o.i[1].i
13853         230, 231, 232, 0,
13854         // o.i[1].m2 (mat2x3[3][2], row-major), copied from ubo430rIn.o.i[1].m2
13855         233, 236,         234, 237,         235, 238,
13856         239, 242,         240, 243,         241, 244,
13857         245, 248,         246, 249,         247, 250,
13858         251, 254,         252, 255,         253, 256,
13859         257, 260,         258, 261,         259, 262,
13860         263, 266,         264, 267,         265, 268,
13861 
13862         // i.m (mat3x2, column-major), copied from ubo430rIn.o.i[1].m
13863         204, 205,          206, 207,         208, 209,
13864         // i.f (float[3]), copied from ubo430rIn.o.i[1].f
13865         211, 212, 213, 0,
13866         // i.u (uvec2[2][4]), copied from ubo430rIn.o.i[1].u
13867         214, 215,         216, 217,         218, 219,         220, 221,
13868         222, 223,         224, 225,         226, 227,         228, 229, 0, 0,
13869         // i.i (ivec3), copied from ubo430rIn.o.i[1].i
13870         230, 231, 232, 0,
13871         // i.m2 (mat2x3[3][2], column-major), copied from ubo430rIn.o.i[1].m2
13872         233, 234, 235, 0,   236, 237, 238, 0,
13873         239, 240, 241, 0,   242, 243, 244, 0,
13874         245, 246, 247, 0,   248, 249, 250, 0,
13875         251, 252, 253, 0,   254, 255, 256, 0,
13876         257, 258, 259, 0,   260, 261, 262, 0,
13877         263, 264, 265, 0,   266, 267, 268, 0,
13878     };
13879     const std::vector<float> zeros(std::max(ssbo140cExpect.size(), ssbo430rExpect.size()), 0);
13880     // clang-format on
13881 
13882     GLBuffer uboStd140ColMajor, uboStd430RowMajor;
13883     GLBuffer ssboStd140ColMajor, ssboStd430RowMajor;
13884 
13885     InitBuffer(program, "Ubo140c", uboStd140ColMajor, 0, ubo140cData.data(),
13886                static_cast<uint32_t>(ubo140cData.size()), true);
13887     InitBuffer(program, "Ubo430r", uboStd430RowMajor, 0, ubo430rData.data(),
13888                static_cast<uint32_t>(ubo430rData.size()), false);
13889     InitBuffer(program, "Ssbo140c", ssboStd140ColMajor, 1, zeros.data(),
13890                static_cast<uint32_t>(ssbo140cExpect.size()), false);
13891     InitBuffer(program, "Ssbo430r", ssboStd430RowMajor, 2, zeros.data(),
13892                static_cast<uint32_t>(ssbo430rExpect.size()), false);
13893     EXPECT_GL_NO_ERROR();
13894 
13895     glUseProgram(program);
13896     glDispatchCompute(1, 1, 1);
13897     EXPECT_GL_NO_ERROR();
13898 
13899     EXPECT_TRUE(VerifyBuffer(ssboStd140ColMajor, ssbo140cExpect.data(),
13900                              static_cast<uint32_t>(ssbo140cExpect.size())));
13901     EXPECT_TRUE(VerifyBuffer(ssboStd430RowMajor, ssbo430rExpect.data(),
13902                              static_cast<uint32_t>(ssbo430rExpect.size())));
13903 }
13904 
13905 // Verify that bool in interface blocks work.
TEST_P(GLSLTest_ES31,BoolInInterfaceBlocks)13906 TEST_P(GLSLTest_ES31, BoolInInterfaceBlocks)
13907 {
13908     constexpr char kCS[] = R"(#version 310 es
13909 precision highp float;
13910 layout(local_size_x=1) in;
13911 
13912 struct Inner
13913 {
13914     bool b;
13915     bvec2 b2;
13916     bvec3 b3;
13917     bvec4 b4;
13918     bool ba[5];
13919     bvec2 b2a[2][3];
13920 };
13921 
13922 struct Outer
13923 {
13924     Inner i[2];
13925 };
13926 
13927 layout(std140) uniform Ubo140
13928 {
13929     Outer o;
13930 };
13931 
13932 layout(std430, binding = 0) buffer Ubo430
13933 {
13934     Outer o;
13935 } ubo430In;
13936 
13937 layout(std140, binding = 1) buffer Ssbo140
13938 {
13939     bool valid;
13940     Inner i;
13941 } ssbo140Out;
13942 
13943 layout(std430, binding = 2) buffer Ssbo430
13944 {
13945     bool valid;
13946     Inner i;
13947 };
13948 
13949 void writeArgToStd430(bool ba[5])
13950 {
13951     i.ba = ba;
13952 }
13953 
13954 bool[5] readFromStd430(uint innerIndex)
13955 {
13956     return ubo430In.o.i[innerIndex].ba;
13957 }
13958 
13959 void copyFromStd430(out bvec2 b2a[2][3])
13960 {
13961     b2a = ubo430In.o.i[0].b2a;
13962 }
13963 
13964 bool destroyContent(inout Inner iOut)
13965 {
13966     iOut.b = true;
13967     iOut.b2 = bvec2(true);
13968     iOut.b3 = bvec3(true);
13969     iOut.b4 = bvec4(true);
13970     iOut.ba = bool[5](true, true, true, true, true);
13971     bvec2 true3[3] = bvec2[3](iOut.b2, iOut.b2, iOut.b2);
13972     iOut.b2a = bvec2[2][3](true3, true3);
13973     return true;
13974 }
13975 
13976 void main(){
13977     // Directly copy from one layout to another.
13978     i.b = o.i[0].b;
13979     i.b2 = o.i[0].b2;
13980     i.b2a = o.i[0].b2a;
13981 
13982     // Copy to temp with swizzle.
13983     bvec4 t1 = o.i[0].b3.yxzy;
13984     bvec4 t2 = o.i[0].b4.xxyy;
13985     bvec4 t3 = o.i[0].b4.zzww;
13986 
13987     // Copy from temp with swizzle.
13988     i.b3 = t1.ywz;
13989     i.b4.yz = bvec2(t2.z, t3.y);
13990     i.b4.wx = bvec2(t3.w, t2.x);
13991 
13992     // Copy by passing argument to function.
13993     writeArgToStd430(o.i[0].ba);
13994 
13995     // Copy by return value.
13996     ssbo140Out.i.ba = readFromStd430(0u);
13997 
13998     // Copy by out parameter.
13999     copyFromStd430(ssbo140Out.i.b2a);
14000 
14001     // Logical operations
14002     uvec4 t4 = ubo430In.o.i[0].b ? uvec4(0) : uvec4(1);
14003     ssbo140Out.i.b = all(equal(t4, uvec4(1))) && (ubo430In.o.i[0].b ? false : true);
14004     ssbo140Out.i.b2 = not(ubo430In.o.i[0].b2);
14005     ssbo140Out.i.b3 = bvec3(all(ubo430In.o.i[0].b3), any(ubo430In.o.i[0].b3), any(ubo430In.o.i[0].b3.yx));
14006     ssbo140Out.i.b4 = equal(ubo430In.o.i[0].b4, bvec4(true, false, true, false));
14007 
14008     ssbo140Out.valid = true;
14009     ssbo140Out.valid = ssbo140Out.valid && all(equal(bvec3(o.i[1].b, o.i[1].b2), o.i[1].b3));
14010     ssbo140Out.valid = ssbo140Out.valid &&
14011             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])));
14012     ssbo140Out.valid = ssbo140Out.valid && uint(o.i[1].ba[4]) == 1u;
14013     for (int x = 0; x < o.i[1].b2a.length(); ++x)
14014     {
14015         for (int y = 0; y < o.i[1].b2a[x].length(); ++y)
14016         {
14017             ssbo140Out.valid = ssbo140Out.valid && all(equal(uvec2(o.i[1].b2a[x][y]), uvec2(x % 2, y % 2)));
14018         }
14019     }
14020 
14021     valid = o.i[1] == ubo430In.o.i[1];
14022 
14023     // Make sure short-circuiting behavior is correct.
14024     bool falseVar = !valid && destroyContent(i);
14025     if (falseVar && destroyContent(ssbo140Out.i))
14026     {
14027         valid = false;
14028     }
14029 
14030     if (valid || o.i[uint((i.ba = bool[5](true, true, true, true, true))[1])].b)
14031     {
14032     }
14033     else
14034     {
14035         ssbo140Out.valid = false;
14036     }
14037 })";
14038 
14039     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
14040     EXPECT_GL_NO_ERROR();
14041 
14042     // Test data, laid out with padding (0) based on std140/std430 rules.
14043     // clang-format off
14044     const std::vector<uint32_t> ubo140Data = {
14045         // o.i[0].b (bool)
14046         true, 0,
14047         // o.i[0].b2 (bvec2)
14048         true, false,
14049         // o.i[0].b3 (bvec3)
14050         true, true, false, 0,
14051         // o.i[0].b4 (bvec4)
14052         false, true, false, true,
14053         // o.i[0].ba (bool[5])
14054         true, 0, 0, 0,
14055         false, 0, 0, 0,
14056         false, 0, 0, 0,
14057         true, 0, 0, 0,
14058         true, 0, 0, 0,
14059         // o.i[0].b2a (bool[2][3])
14060         false, true, 0, 0,  true, true, 0, 0,    true, false, 0, 0,
14061         true, false, 0, 0,  false, false, 0, 0,  true, true, 0, 0,
14062 
14063         // o.i[1].b (bool)
14064         false, 0,
14065         // o.i[1].b2 (bvec2)
14066         true, true,
14067         // o.i[1].b3 (bvec3), expected to be equal to (b, b2)
14068         false, true, true, 0,
14069         // o.i[1].b4 (bvec4)
14070         true, false, true, true,
14071         // o.i[1].ba (bool[5]), expected to be equal to (not(b4), 1)
14072         false, 0, 0, 0,
14073         true, 0, 0, 0,
14074         false, 0, 0, 0,
14075         false, 0, 0, 0,
14076         true, 0, 0, 0,
14077         // o.i[1].b2a (bvec2[2][3]), [x][y] expected to equal (x%2,y%2)
14078         false, false, 0, 0,  false, true, 0, 0,  false, false, 0, 0,
14079         true, false, 0, 0,   true, true, 0, 0,   true, false, 0, 0,
14080     };
14081     const std::vector<uint32_t> ubo430Data = {
14082         // o.i[0].b (bool)
14083         false, 0,
14084         // o.i[0].b2 (bvec2)
14085         true, true,
14086         // o.i[0].b3 (bvec3)
14087         false, false, true, 0,
14088         // o.i[0].b4 (bvec4)
14089         true, false, true, true,
14090         // o.i[0].ba (bool[5])
14091         false, false, false, true, false, 0,
14092         // o.i[0].b2a (bool[2][3])
14093         true, false,  true, false,  true, true,
14094         false, true,  true, true,   false, false, 0, 0,
14095 
14096         // o.i[1] expected to be equal to ubo140In.o.i[1]
14097         // o.i[1].b (bool)
14098         false, 0,
14099         // o.i[1].b2 (bvec2)
14100         true, true,
14101         // o.i[1].b3 (bvec3)
14102         false, true, true, 0,
14103         // o.i[1].b4 (bvec4)
14104         true, false, true, true,
14105         // o.i[1].ba (bool[5])
14106         false, true, false, false, true, 0,
14107         // o.i[1].b2a (bvec2[2][3])
14108         false, false,  false, true,  false, false,
14109         true, false,   true, true,   true, false,
14110     };
14111     const std::vector<uint32_t> ssbo140Expect = {
14112         // valid, expected to be true
14113         true, 0, 0, 0,
14114 
14115         // i.b (bool), ubo430In.o.i[0].b ? false : true
14116         true, 0,
14117         // i.b2 (bvec2), not(ubo430In.o.i[0].b2)
14118         false, false,
14119         // i.b3 (bvec3), all(ubo430In.o.i[0].b3), any(...b3), any(...b3.yx)
14120         false, true, false, 0,
14121         // i.b4 (bvec4), ubo430In.o.i[0].b4 == (true, false, true, false)
14122         true, true, true, false,
14123         // i.ba (bool[5]), copied from ubo430In.o.i[0].ba
14124         false, 0, 0, 0,
14125         false, 0, 0, 0,
14126         false, 0, 0, 0,
14127         true, 0, 0, 0,
14128         false, 0, 0, 0,
14129         // i.b2a (bool[2][3]), copied from ubo430In.o.i[0].b2a
14130         true, false, 0, 0,  true, false, 0, 0,   true, true, 0, 0,
14131         false, true, 0, 0,  true, true, 0, 0,    false, false, 0, 0,
14132     };
14133     const std::vector<uint32_t> ssbo430Expect = {
14134         // valid, expected to be true
14135         true, 0, 0, 0,
14136 
14137         // o.i[0].b (bool), copied from (Ubo140::)o.i[0].b
14138         true, 0,
14139         // o.i[0].b2 (bvec2), copied from (Ubo140::)o.i[0].b2
14140         true, false,
14141         // o.i[0].b3 (bvec3), copied from (Ubo140::)o.i[0].b3
14142         true, true, false, 0,
14143         // o.i[0].b4 (bvec4), copied from (Ubo140::)o.i[0].b4
14144         false, true, false, true,
14145         // o.i[0].ba (bool[5]), copied from (Ubo140::)o.i[0].ba
14146         true, false, false, true, true, 0,
14147         // o.i[0].b2a (bool[2][3]), copied from (Ubo140::)o.i[0].b2a
14148         false, true,  true, true,    true, false,
14149         true, false,  false, false,  true, true, 0, 0,
14150     };
14151     const std::vector<uint32_t> zeros(std::max(ssbo140Expect.size(), ssbo430Expect.size()), 0);
14152     // clang-format on
14153 
14154     GLBuffer uboStd140, uboStd430;
14155     GLBuffer ssboStd140, ssboStd430;
14156 
14157     InitBuffer(program, "Ubo140", uboStd140, 0, ubo140Data.data(),
14158                static_cast<uint32_t>(ubo140Data.size()), true);
14159     InitBuffer(program, "Ubo430", uboStd430, 0, ubo430Data.data(),
14160                static_cast<uint32_t>(ubo430Data.size()), false);
14161     InitBuffer(program, "Ssbo140", ssboStd140, 1, zeros.data(),
14162                static_cast<uint32_t>(ssbo140Expect.size()), false);
14163     InitBuffer(program, "Ssbo430", ssboStd430, 2, zeros.data(),
14164                static_cast<uint32_t>(ssbo430Expect.size()), false);
14165     EXPECT_GL_NO_ERROR();
14166 
14167     glUseProgram(program);
14168     glDispatchCompute(1, 1, 1);
14169     EXPECT_GL_NO_ERROR();
14170 
14171     EXPECT_TRUE(VerifyBuffer(ssboStd140, ssbo140Expect.data(),
14172                              static_cast<uint32_t>(ssbo140Expect.size())));
14173     EXPECT_TRUE(VerifyBuffer(ssboStd430, ssbo430Expect.data(),
14174                              static_cast<uint32_t>(ssbo430Expect.size())));
14175 }
14176 
14177 // Verify that ternary operator works when the operands are matrices used in different block
14178 // storage.
TEST_P(GLSLTest_ES31,TernaryOnMatricesInDifferentBlockStorages)14179 TEST_P(GLSLTest_ES31, TernaryOnMatricesInDifferentBlockStorages)
14180 {
14181     constexpr char kCS[] = R"(#version 310 es
14182 precision highp float;
14183 layout(local_size_x=1) in;
14184 
14185 layout(std140, column_major) uniform Ubo140c
14186 {
14187     uint u;
14188     layout(row_major) mat3x2 m;
14189 } ubo140cIn;
14190 
14191 layout(std430, row_major, binding = 0) buffer Ubo430r
14192 {
14193     uint u;
14194     layout(column_major) mat3x2 m;
14195 } ubo430rIn;
14196 
14197 layout(std140, column_major, binding = 1) buffer Ssbo140c
14198 {
14199     uint u;
14200     mat3x2 m;
14201 } ssbo140cIn;
14202 
14203 layout(std430, row_major, binding = 2) buffer Ssbo430r
14204 {
14205     mat3x2 m1;
14206     mat3x2 m2;
14207 } ssbo430rOut;
14208 
14209 void main(){
14210     ssbo430rOut.m1 = ubo140cIn.u > ubo430rIn.u ? ubo140cIn.m : ubo430rIn.m;
14211     ssbo430rOut.m2 = ssbo140cIn.u > ubo140cIn.u ? ssbo140cIn.m : ubo140cIn.m;
14212 
14213     mat3x2 m = mat3x2(0);
14214 
14215     ssbo430rOut.m1 = ubo140cIn.u == 0u ? m : ssbo430rOut.m1;
14216 })";
14217 
14218     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
14219     EXPECT_GL_NO_ERROR();
14220 
14221     // Test data, laid out with padding (0) based on std140/std430 rules.
14222     // clang-format off
14223     const std::vector<float> ubo140cData = {
14224         // u (uint)
14225         1, 0, 0, 0,
14226 
14227         // m (mat3x2, row-major)
14228         5, 7, 9, 0,     6, 8, 10, 0,
14229     };
14230     const std::vector<float> ubo430rData = {
14231         // u (uint)
14232         135, 0,
14233 
14234         // m (mat3x2, column-major)
14235         139, 140,         141, 142,         143, 144,
14236     };
14237     const std::vector<float> ssbo140cData = {
14238         // u (uint)
14239         204, 0, 0, 0,
14240 
14241         // m (mat3x2, column-major)
14242         205, 206, 0, 0,  207, 208, 0, 0,  209, 210, 0, 0,
14243     };
14244     const std::vector<float> ssbo430rExpect = {
14245         // m1 (mat3x2, row-major), copied from ubo430rIn.m
14246         139, 141, 143, 0,  140, 142, 144, 0,
14247 
14248         // m2 (mat3x2, row-major), copied from ssbo140cIn.m
14249         205, 207, 209, 0,  206, 208, 210, 0,
14250     };
14251     const std::vector<float> zeros(ssbo430rExpect.size(), 0);
14252     // clang-format on
14253 
14254     GLBuffer uboStd140ColMajor, uboStd430RowMajor;
14255     GLBuffer ssboStd140ColMajor, ssboStd430RowMajor;
14256 
14257     InitBuffer(program, "Ubo140c", uboStd140ColMajor, 0, ubo140cData.data(),
14258                static_cast<uint32_t>(ubo140cData.size()), true);
14259     InitBuffer(program, "Ubo430r", uboStd430RowMajor, 0, ubo430rData.data(),
14260                static_cast<uint32_t>(ubo430rData.size()), false);
14261     InitBuffer(program, "Ssbo140c", ssboStd140ColMajor, 1, ssbo140cData.data(),
14262                static_cast<uint32_t>(ssbo140cData.size()), false);
14263     InitBuffer(program, "Ssbo430r", ssboStd430RowMajor, 2, zeros.data(),
14264                static_cast<uint32_t>(ssbo430rExpect.size()), false);
14265     EXPECT_GL_NO_ERROR();
14266 
14267     glUseProgram(program);
14268     glDispatchCompute(1, 1, 1);
14269     EXPECT_GL_NO_ERROR();
14270 
14271     EXPECT_TRUE(VerifyBuffer(ssboStd430RowMajor, ssbo430rExpect.data(),
14272                              static_cast<uint32_t>(ssbo430rExpect.size())));
14273 }
14274 
14275 // Verify that ternary operator works when the operands are structs used in different block
14276 // storage.
TEST_P(GLSLTest_ES31,TernaryOnStructsInDifferentBlockStorages)14277 TEST_P(GLSLTest_ES31, TernaryOnStructsInDifferentBlockStorages)
14278 {
14279     constexpr char kCS[] = R"(#version 310 es
14280 precision highp float;
14281 layout(local_size_x=1) in;
14282 
14283 struct S
14284 {
14285     mat3x2 m[2];
14286 };
14287 
14288 layout(std140, column_major) uniform Ubo140c
14289 {
14290     uint u;
14291     layout(row_major) S s;
14292 } ubo140cIn;
14293 
14294 layout(std430, row_major, binding = 0) buffer Ubo430r
14295 {
14296     uint u;
14297     layout(column_major) S s;
14298 } ubo430rIn;
14299 
14300 layout(std140, column_major, binding = 1) buffer Ssbo140c
14301 {
14302     uint u;
14303     S s;
14304 } ssbo140cIn;
14305 
14306 layout(std430, row_major, binding = 2) buffer Ssbo430r
14307 {
14308     S s1;
14309     S s2;
14310 } ssbo430rOut;
14311 
14312 void main(){
14313     ssbo430rOut.s1 = ubo140cIn.u > ubo430rIn.u ? ubo140cIn.s : ubo430rIn.s;
14314     ssbo430rOut.s2 = ssbo140cIn.u > ubo140cIn.u ? ssbo140cIn.s : ubo140cIn.s;
14315 
14316     S s;
14317     s.m[0] = mat3x2(0);
14318     s.m[1] = mat3x2(0);
14319 
14320     ssbo430rOut.s1 = ubo140cIn.u == 0u ? s : ssbo430rOut.s1;
14321 })";
14322 
14323     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
14324     EXPECT_GL_NO_ERROR();
14325 
14326     // Test data, laid out with padding (0) based on std140/std430 rules.
14327     // clang-format off
14328     const std::vector<float> ubo140cData = {
14329         // u (uint)
14330         1, 0, 0, 0,
14331 
14332         // s.m[0] (mat3x2, row-major)
14333         5, 7, 9, 0,     6, 8, 10, 0,
14334         // s.m[1] (mat3x2, row-major)
14335         25, 27, 29, 0,  26, 28, 30, 0,
14336     };
14337     const std::vector<float> ubo430rData = {
14338         // u (uint)
14339         135, 0,
14340 
14341         // s.m[0] (mat3x2, column-major)
14342         139, 140,         141, 142,         143, 144,
14343         // s.m[1] (mat3x2, column-major)
14344         189, 190,         191, 192,         193, 194,
14345     };
14346     const std::vector<float> ssbo140cData = {
14347         // u (uint)
14348         204, 0, 0, 0,
14349 
14350         // s.m[0] (mat3x2, column-major)
14351         205, 206, 0, 0,  207, 208, 0, 0,  209, 210, 0, 0,
14352         // s.m[1] (mat3x2, column-major)
14353         245, 246, 0, 0,  247, 248, 0, 0,  249, 250, 0, 0,
14354     };
14355     const std::vector<float> ssbo430rExpect = {
14356         // s1.m[0] (mat3x2, row-major), copied from ubo430rIn.s.m[0]
14357         139, 141, 143, 0,  140, 142, 144, 0,
14358         // s1.m[1] (mat3x2, row-major), copied from ubo430rIn.s.m[0]
14359         189, 191, 193, 0,  190, 192, 194, 0,
14360 
14361         // s2.m[0] (mat3x2, row-major), copied from ssbo140cIn.m
14362         205, 207, 209, 0,  206, 208, 210, 0,
14363         // s2.m[1] (mat3x2, row-major), copied from ssbo140cIn.m
14364         245, 247, 249, 0,  246, 248, 250, 0,
14365     };
14366     const std::vector<float> zeros(ssbo430rExpect.size(), 0);
14367     // clang-format on
14368 
14369     GLBuffer uboStd140ColMajor, uboStd430RowMajor;
14370     GLBuffer ssboStd140ColMajor, ssboStd430RowMajor;
14371 
14372     InitBuffer(program, "Ubo140c", uboStd140ColMajor, 0, ubo140cData.data(),
14373                static_cast<uint32_t>(ubo140cData.size()), true);
14374     InitBuffer(program, "Ubo430r", uboStd430RowMajor, 0, ubo430rData.data(),
14375                static_cast<uint32_t>(ubo430rData.size()), false);
14376     InitBuffer(program, "Ssbo140c", ssboStd140ColMajor, 1, ssbo140cData.data(),
14377                static_cast<uint32_t>(ssbo140cData.size()), false);
14378     InitBuffer(program, "Ssbo430r", ssboStd430RowMajor, 2, zeros.data(),
14379                static_cast<uint32_t>(ssbo430rExpect.size()), false);
14380     EXPECT_GL_NO_ERROR();
14381 
14382     glUseProgram(program);
14383     glDispatchCompute(1, 1, 1);
14384     EXPECT_GL_NO_ERROR();
14385 
14386     EXPECT_TRUE(VerifyBuffer(ssboStd430RowMajor, ssbo430rExpect.data(),
14387                              static_cast<uint32_t>(ssbo430rExpect.size())));
14388 }
14389 
14390 // Verify that uint in interface block cast to bool works.
TEST_P(GLSLTest_ES3,UintCastToBoolFromInterfaceBlocks)14391 TEST_P(GLSLTest_ES3, UintCastToBoolFromInterfaceBlocks)
14392 {
14393     constexpr char kFS[] = R"(#version 300 es
14394 precision mediump float;
14395 
14396 uniform uvec4 uv4;
14397 uniform uvec2 uv2;
14398 uniform uint u1;
14399 uniform uint u2;
14400 
14401 out vec4 colorOut;
14402 
14403 void main()
14404 {
14405     bvec4 bv4 = bvec4(uv4);
14406     bvec2 bv2 = bvec2(uv2);
14407     bool b1 = bool(u1);
14408     bool b2 = bool(u2);
14409 
14410     vec4 vv4 = mix(vec4(0), vec4(0.4), bv4);
14411     vec2 vv2 = mix(vec2(0), vec2(0.7), bv2);
14412     float v1 = b1 ? 1.0 : 0.0;
14413     float v2 = b2 ? 0.0 : 1.0;
14414 
14415     colorOut = vec4(vv4.x - vv4.y + vv4.z + vv4.w,
14416                         (vv2.y - vv2.x) * 1.5,
14417                         v1,
14418                         v2);
14419 })";
14420 
14421     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
14422     EXPECT_GL_NO_ERROR();
14423 
14424     glUseProgram(program);
14425     GLint uv4 = glGetUniformLocation(program, "uv4");
14426     GLint uv2 = glGetUniformLocation(program, "uv2");
14427     GLint u1  = glGetUniformLocation(program, "u1");
14428     GLint u2  = glGetUniformLocation(program, "u2");
14429     ASSERT_NE(uv4, -1);
14430     ASSERT_NE(uv2, -1);
14431     ASSERT_NE(u1, -1);
14432     ASSERT_NE(u2, -1);
14433 
14434     glUniform4ui(uv4, 123, 0, 9, 8297312);
14435     glUniform2ui(uv2, 0, 90812);
14436     glUniform1ui(u1, 8979421);
14437     glUniform1ui(u2, 0);
14438 
14439     glClearColor(0, 0, 0, 0);
14440     glClear(GL_COLOR_BUFFER_BIT);
14441 
14442     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
14443     EXPECT_GL_NO_ERROR();
14444 
14445     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
14446 }
14447 
14448 // Test that the precise keyword is not reserved before ES3.1.
TEST_P(GLSLTest_ES3,PreciseNotReserved)14449 TEST_P(GLSLTest_ES3, PreciseNotReserved)
14450 {
14451     // Skip in ES3.1+ as the precise keyword is reserved/core.
14452     ANGLE_SKIP_TEST_IF(getClientMajorVersion() > 3 ||
14453                        (getClientMajorVersion() == 3 && getClientMinorVersion() >= 1));
14454 
14455     constexpr char kFS[] = R"(#version 300 es
14456 precision mediump float;
14457 in float precise;
14458 out vec4 my_FragColor;
14459 void main() { my_FragColor = vec4(precise, 0, 0, 1.0); })";
14460 
14461     constexpr char kVS[] = R"(#version 300 es
14462 in vec4 a_position;
14463 out float precise;
14464 void main() { precise = a_position.x; gl_Position = a_position; })";
14465 
14466     GLuint program = CompileProgram(kVS, kFS);
14467     EXPECT_NE(0u, program);
14468 }
14469 
14470 // Test that the precise keyword is reserved on ES3.0 without GL_EXT_gpu_shader5.
TEST_P(GLSLTest_ES31,PreciseReservedWithoutExtension)14471 TEST_P(GLSLTest_ES31, PreciseReservedWithoutExtension)
14472 {
14473     // Skip if EXT_gpu_shader5 is enabled.
14474     ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
14475     // Skip in ES3.2+ as the precise keyword is core.
14476     ANGLE_SKIP_TEST_IF(getClientMajorVersion() > 3 ||
14477                        (getClientMajorVersion() == 3 && getClientMinorVersion() >= 2));
14478 
14479     constexpr char kFS[] = R"(#version 310 es
14480 precision mediump float;
14481 in float v_varying;
14482 out vec4 my_FragColor;
14483 void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); })";
14484 
14485     constexpr char kVS[] = R"(#version 310 es
14486 in vec4 a_position;
14487 precise out float v_varying;
14488 void main() { v_varying = a_position.x; gl_Position = a_position; })";
14489 
14490     // Should fail, as precise is a reserved keyword when the extension is not enabled.
14491     GLuint program = CompileProgram(kVS, kFS);
14492     EXPECT_EQ(0u, program);
14493 }
14494 
14495 // Regression test for a bug with precise in combination with constructor, swizzle and dynamic
14496 // index.
TEST_P(GLSLTest_ES31,PreciseVsVectorConstructorSwizzleAndIndex)14497 TEST_P(GLSLTest_ES31, PreciseVsVectorConstructorSwizzleAndIndex)
14498 {
14499     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
14500 
14501     constexpr char kVS[] = R"(#version 310 es
14502 #extension GL_EXT_gpu_shader5 : require
14503 
14504 uniform highp float u;
14505 
14506 void main()
14507 {
14508     precise float p = vec4(u, u, u, u).xyz[int(u)];
14509     gl_Position = vec4(p);
14510 })";
14511 
14512     constexpr char kFS[] = R"(#version 310 es
14513 precision mediump float;
14514 out vec4 oColor;
14515 void main()
14516 {
14517     oColor = vec4(1.0);
14518 })";
14519 
14520     ANGLE_GL_PROGRAM(program, kVS, kFS);
14521 }
14522 
14523 // Regression test for a bug with precise in combination with matrix constructor and column index.
TEST_P(GLSLTest_ES31,PreciseVsMatrixConstructorAndIndex)14524 TEST_P(GLSLTest_ES31, PreciseVsMatrixConstructorAndIndex)
14525 {
14526     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
14527 
14528     constexpr char kVS[] = R"(#version 310 es
14529 #extension GL_EXT_gpu_shader5 : require
14530 
14531 uniform highp vec4 u;
14532 
14533 void main()
14534 {
14535     precise vec4 p = mat4(u,vec4(0),vec4(0),vec4(0))[0];
14536     gl_Position = p;
14537 })";
14538 
14539     constexpr char kFS[] = R"(#version 310 es
14540 precision mediump float;
14541 out vec4 oColor;
14542 void main()
14543 {
14544     oColor = vec4(1.0);
14545 })";
14546 
14547     ANGLE_GL_PROGRAM(program, kVS, kFS);
14548 }
14549 
14550 // Regression test for a bug with precise in combination with struct constructor and field
14551 // selection.
TEST_P(GLSLTest_ES31,PreciseVsStructConstructorAndFieldSelection)14552 TEST_P(GLSLTest_ES31, PreciseVsStructConstructorAndFieldSelection)
14553 {
14554     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
14555 
14556     constexpr char kVS[] = R"(#version 310 es
14557 #extension GL_EXT_gpu_shader5 : require
14558 
14559 struct S
14560 {
14561     float a;
14562     float b;
14563 };
14564 
14565 uniform highp float u;
14566 
14567 void main()
14568 {
14569     precise float p = S(u, u).b;
14570     gl_Position = vec4(p);
14571 })";
14572 
14573     constexpr char kFS[] = R"(#version 310 es
14574 precision mediump float;
14575 out vec4 oColor;
14576 void main()
14577 {
14578     oColor = vec4(1.0);
14579 })";
14580 
14581     ANGLE_GL_PROGRAM(program, kVS, kFS);
14582 }
14583 
14584 // Test that reusing the same variable name for different uses across stages links fine.  The SPIR-V
14585 // transformation should ignore all names for non-shader-interface variables and not get confused by
14586 // them.
TEST_P(GLSLTest_ES31,VariableNameReuseAcrossStages)14587 TEST_P(GLSLTest_ES31, VariableNameReuseAcrossStages)
14588 {
14589     constexpr char kVS[] = R"(#version 310 es
14590 precision mediump float;
14591 uniform highp vec4 a;
14592 in highp vec4 b;
14593 in highp vec4 c;
14594 in highp vec4 d;
14595 out highp vec4 e;
14596 
14597 vec4 f(vec4 a)
14598 {
14599     return a;
14600 }
14601 
14602 vec4 g(vec4 f)
14603 {
14604     return f + f;
14605 }
14606 
14607 void main() {
14608     e = f(b) + a;
14609     gl_Position = g(c) + f(d);
14610 }
14611 )";
14612 
14613     constexpr char kFS[] = R"(#version 310 es
14614 precision mediump float;
14615 in highp vec4 e;
14616 uniform sampler2D f;
14617 layout(rgba8) uniform highp readonly image2D g;
14618 uniform A
14619 {
14620     vec4 x;
14621 } c;
14622 layout(std140, binding=0) buffer B
14623 {
14624     vec4 x;
14625 } d[2];
14626 out vec4 col;
14627 
14628 vec4 h(vec4 c)
14629 {
14630     return texture(f, c.xy) + imageLoad(g, ivec2(c.zw));
14631 }
14632 
14633 vec4 i(vec4 x, vec4 y)
14634 {
14635     return vec4(x.xy, y.zw);
14636 }
14637 
14638 void main() {
14639     col = h(e) + i(c.x, d[0].x) + d[1].x;
14640 }
14641 )";
14642 
14643     GLuint program = CompileProgram(kVS, kFS);
14644     EXPECT_NE(0u, program);
14645 }
14646 
14647 // Test that reusing the same uniform variable name for different uses across stages links fine.
TEST_P(GLSLTest_ES31,UniformVariableNameReuseAcrossStages)14648 TEST_P(GLSLTest_ES31, UniformVariableNameReuseAcrossStages)
14649 {
14650     constexpr char kVS[] = R"(#version 310 es
14651 precision mediump float;
14652 in highp vec4 variableWithSameName;
14653 
14654 void main() {
14655     gl_Position = variableWithSameName;
14656 }
14657 )";
14658 
14659     constexpr char kFS[] = R"(#version 310 es
14660 precision mediump float;
14661 uniform vec4 variableWithSameName;
14662 out vec4 col;
14663 
14664 void main() {
14665     col = vec4(variableWithSameName);
14666 }
14667 )";
14668 
14669     GLuint program = CompileProgram(kVS, kFS);
14670     EXPECT_NE(0u, program);
14671 }
14672 
14673 // Verify that precision match validation of uniforms is performed only if they are statically used
TEST_P(GLSLTest_ES31,UniformPrecisionMatchValidation)14674 TEST_P(GLSLTest_ES31, UniformPrecisionMatchValidation)
14675 {
14676     // Nvidia driver bug: http://anglebug.com/42263793
14677     ANGLE_SKIP_TEST_IF(IsOpenGL() && IsWindows() && IsNVIDIA());
14678 
14679     constexpr char kVSUnused[] = R"(#version 300 es
14680 precision highp float;
14681 uniform highp vec4 positionIn;
14682 
14683 void main()
14684 {
14685     gl_Position = vec4(1, 0, 0, 1);
14686 })";
14687 
14688     constexpr char kVSStaticUse[] = R"(#version 300 es
14689 precision highp float;
14690 uniform highp vec4 positionIn;
14691 
14692 void main()
14693 {
14694     gl_Position = positionIn;
14695 })";
14696 
14697     constexpr char kFSUnused[] = R"(#version 300 es
14698 precision highp float;
14699 uniform highp vec4 positionIn;
14700 out vec4 my_FragColor;
14701 
14702 void main()
14703 {
14704     my_FragColor = vec4(1, 0, 0, 1);
14705 })";
14706 
14707     constexpr char kFSStaticUse[] = R"(#version 300 es
14708 precision highp float;
14709 uniform mediump vec4 positionIn;
14710 out vec4 my_FragColor;
14711 
14712 void main()
14713 {
14714     my_FragColor = vec4(1, 0, 0, positionIn.z);
14715 })";
14716 
14717     GLuint program = 0;
14718 
14719     program = CompileProgram(kVSUnused, kFSUnused);
14720     EXPECT_NE(0u, program);
14721 
14722     program = CompileProgram(kVSUnused, kFSStaticUse);
14723     EXPECT_NE(0u, program);
14724 
14725     program = CompileProgram(kVSStaticUse, kFSUnused);
14726     EXPECT_NE(0u, program);
14727 
14728     program = CompileProgram(kVSStaticUse, kFSStaticUse);
14729     EXPECT_EQ(0u, program);
14730 }
14731 
14732 // Validate that link fails when two instanceless interface blocks with different block names but
14733 // same field names are present.
TEST_P(GLSLTest_ES31,AmbiguousInstancelessInterfaceBlockFields)14734 TEST_P(GLSLTest_ES31, AmbiguousInstancelessInterfaceBlockFields)
14735 {
14736     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14737 
14738     constexpr char kVS[] = R"(#version 310 es
14739 in highp vec4 position;
14740 layout(binding = 0) buffer BlockA { mediump float a; };
14741 void main()
14742 {
14743     a = 0.0;
14744     gl_Position = position;
14745 })";
14746 
14747     constexpr char kFS[] = R"(#version 310 es
14748 precision mediump float;
14749 layout(location = 0) out mediump vec4 color;
14750 uniform BlockB { float a; };
14751 void main()
14752 {
14753     color = vec4(a, a, a, 1.0);
14754 })";
14755 
14756     GLuint program = CompileProgram(kVS, kFS);
14757     EXPECT_EQ(0u, program);
14758 }
14759 
14760 // Verify I/O block array locations
TEST_P(GLSLTest_ES31,IOBlockLocations)14761 TEST_P(GLSLTest_ES31, IOBlockLocations)
14762 {
14763     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
14764     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
14765 
14766     constexpr char kVS[] = R"(#version 310 es
14767 #extension GL_EXT_shader_io_blocks : require
14768 
14769 in highp vec4 position;
14770 
14771 layout(location = 0) out vec4 aOut;
14772 
14773 layout(location = 6) out VSBlock
14774 {
14775     vec4 b;     // location 6
14776     vec4 c;     // location 7
14777     layout(location = 1) vec4 d;
14778     vec4 e;     // location 2
14779     vec4 f[2];  // locations 3 and 4
14780 } blockOut;
14781 
14782 layout(location = 5) out vec4 gOut;
14783 
14784 void main()
14785 {
14786     aOut = vec4(0.03, 0.06, 0.09, 0.12);
14787     blockOut.b = vec4(0.15, 0.18, 0.21, 0.24);
14788     blockOut.c = vec4(0.27, 0.30, 0.33, 0.36);
14789     blockOut.d = vec4(0.39, 0.42, 0.45, 0.48);
14790     blockOut.e = vec4(0.51, 0.54, 0.57, 0.6);
14791     blockOut.f[0] = vec4(0.63, 0.66, 0.66, 0.69);
14792     blockOut.f[1] = vec4(0.72, 0.75, 0.78, 0.81);
14793     gOut = vec4(0.84, 0.87, 0.9, 0.93);
14794     gl_Position = position;
14795 })";
14796 
14797     constexpr char kGS[] = R"(#version 310 es
14798 #extension GL_EXT_geometry_shader : require
14799 layout (triangles) in;
14800 layout (triangle_strip, max_vertices = 3) out;
14801 
14802 // Input varyings
14803 layout(location = 0) in vec4 aIn[];
14804 
14805 layout(location = 6) in VSBlock
14806 {
14807     vec4 b;
14808     vec4 c;
14809     layout(location = 1) vec4 d;
14810     vec4 e;
14811     vec4 f[2];
14812 } blockIn[];
14813 
14814 layout(location = 5) in vec4 gIn[];
14815 
14816 // Output varyings
14817 layout(location = 1) out vec4 aOut;
14818 
14819 layout(location = 0) out GSBlock
14820 {
14821     vec4 b;     // location 0
14822     layout(location = 3) vec4 c;
14823     layout(location = 7) vec4 d;
14824     layout(location = 5) vec4 e[2];
14825     layout(location = 4) vec4 f;
14826 } blockOut;
14827 
14828 layout(location = 2) out vec4 gOut;
14829 
14830 void main()
14831 {
14832     int n;
14833     for (n = 0; n < gl_in.length(); n++)
14834     {
14835         gl_Position = gl_in[n].gl_Position;
14836 
14837         aOut = aIn[n];
14838         blockOut.b = blockIn[n].b;
14839         blockOut.c = blockIn[n].c;
14840         blockOut.d = blockIn[n].d;
14841         blockOut.e[0] = blockIn[n].e;
14842         blockOut.e[1] = blockIn[n].f[0];
14843         blockOut.f = blockIn[n].f[1];
14844         gOut = gIn[n];
14845 
14846         EmitVertex();
14847     }
14848     EndPrimitive();
14849 })";
14850 
14851     constexpr char kFS[] = R"(#version 310 es
14852 #extension GL_EXT_shader_io_blocks : require
14853 precision mediump float;
14854 
14855 layout(location = 0) out mediump vec4 color;
14856 
14857 layout(location = 1) in vec4 aIn;
14858 
14859 layout(location = 0) in GSBlock
14860 {
14861     vec4 b;
14862     layout(location = 3) vec4 c;
14863     layout(location = 7) vec4 d;
14864     layout(location = 5) vec4 e[2];
14865     layout(location = 4) vec4 f;
14866 } blockIn;
14867 
14868 layout(location = 2) in vec4 gIn;
14869 
14870 bool isEq(vec4 a, vec4 b) { return all(lessThan(abs(a-b), vec4(0.001))); }
14871 
14872 void main()
14873 {
14874     bool passR = isEq(aIn, vec4(0.03, 0.06, 0.09, 0.12));
14875     bool passG = isEq(blockIn.b, vec4(0.15, 0.18, 0.21, 0.24)) &&
14876                  isEq(blockIn.c, vec4(0.27, 0.30, 0.33, 0.36)) &&
14877                  isEq(blockIn.d, vec4(0.39, 0.42, 0.45, 0.48)) &&
14878                  isEq(blockIn.e[0], vec4(0.51, 0.54, 0.57, 0.6)) &&
14879                  isEq(blockIn.e[1], vec4(0.63, 0.66, 0.66, 0.69)) &&
14880                  isEq(blockIn.f, vec4(0.72, 0.75, 0.78, 0.81));
14881     bool passB = isEq(gIn, vec4(0.84, 0.87, 0.9, 0.93));
14882 
14883     color = vec4(passR, passG, passB, 1.0);
14884 })";
14885 
14886     ANGLE_GL_PROGRAM_WITH_GS(program, kVS, kGS, kFS);
14887     EXPECT_GL_NO_ERROR();
14888 
14889     GLTexture color;
14890     glBindTexture(GL_TEXTURE_2D, color);
14891     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
14892 
14893     GLFramebuffer fbo;
14894     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
14895     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
14896 
14897     drawQuad(program, "position", 0);
14898 
14899     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
14900 }
14901 
14902 // Test using builtins that can only be redefined with gl_PerVertex
TEST_P(GLSLTest_ES31,PerVertexRedefinition)14903 TEST_P(GLSLTest_ES31, PerVertexRedefinition)
14904 {
14905     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
14906     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_clip_cull_distance"));
14907 
14908     constexpr char kVS[] = R"(#version 310 es
14909 void main()
14910 {
14911     gl_Position = vec4(1.0, 0.0, 0.0, 1.0);
14912 })";
14913 
14914     constexpr char kGS[] = R"(#version 310 es
14915 #extension GL_EXT_geometry_shader : require
14916 #extension GL_EXT_clip_cull_distance : require
14917 
14918 layout(lines_adjacency, invocations = 3) in;
14919 layout(points, max_vertices = 16) out;
14920 
14921 out gl_PerVertex {
14922     vec4 gl_Position;
14923     float gl_ClipDistance[4];
14924     float gl_CullDistance[4];
14925 };
14926 
14927 void main()
14928 {
14929     for (int n = 0; n < 16; ++n)
14930     {
14931         gl_Position = vec4(n, 0.0, 0.0, 1.0);
14932         EmitVertex();
14933     }
14934 
14935     EndPrimitive();
14936 })";
14937 
14938     constexpr char kFS[] = R"(#version 310 es
14939 precision highp float;
14940 
14941 out vec4 result;
14942 
14943 void main()
14944 {
14945     result = vec4(1.0);
14946 })";
14947 
14948     ANGLE_GL_PROGRAM_WITH_GS(program, kVS, kGS, kFS);
14949     EXPECT_GL_NO_ERROR();
14950 }
14951 
14952 // Negative test using builtins that can only be used when redefining gl_PerVertex
TEST_P(GLSLTest_ES31,PerVertexNegativeTest)14953 TEST_P(GLSLTest_ES31, PerVertexNegativeTest)
14954 {
14955     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
14956     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_clip_cull_distance"));
14957 
14958     constexpr char kVS[] = R"(#version 310 es
14959 void main()
14960 {
14961     gl_Position = vec4(1.0, 0.0, 0.0, 1.0);
14962 })";
14963 
14964     constexpr char kGS[] = R"(#version 310 es
14965 #extension GL_EXT_geometry_shader : require
14966 #extension GL_EXT_clip_cull_distance : require
14967 
14968 layout(lines_adjacency, invocations = 3) in;
14969 layout(points, max_vertices = 16) out;
14970 
14971 vec4 gl_Position;
14972 float gl_ClipDistance[4];
14973 float gl_CullDistance[4];
14974 
14975 void main()
14976 {
14977     for (int n = 0; n < 16; ++n)
14978     {
14979         gl_Position = vec4(n, 0.0, 0.0, 1.0);
14980         EmitVertex();
14981     }
14982 
14983     EndPrimitive();
14984 })";
14985 
14986     constexpr char kFS[] = R"(#version 310 es
14987 precision highp float;
14988 
14989 out vec4 result;
14990 
14991 void main()
14992 {
14993     result = vec4(1.0);
14994 })";
14995 
14996     GLuint program = CompileProgramWithGS(kVS, kGS, kFS);
14997     EXPECT_EQ(0u, program);
14998     glDeleteProgram(program);
14999 }
15000 
15001 // Negative test using builtins that can only be used when redefining gl_PerVertex
15002 // but have the builtins in a differently named struct
TEST_P(GLSLTest_ES31,PerVertexRenamedNegativeTest)15003 TEST_P(GLSLTest_ES31, PerVertexRenamedNegativeTest)
15004 {
15005     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
15006     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_clip_cull_distance"));
15007 
15008     constexpr char kVS[] = R"(#version 310 es
15009 void main()
15010 {
15011     gl_Position = vec4(1.0, 0.0, 0.0, 1.0);
15012 })";
15013 
15014     constexpr char kGS[] = R"(#version 310 es
15015 #extension GL_EXT_geometry_shader : require
15016 #extension GL_EXT_clip_cull_distance : require
15017 
15018 layout(lines_adjacency, invocations = 3) in;
15019 layout(points, max_vertices = 16) out;
15020 
15021 out Block {
15022     vec4 gl_Position;
15023     float gl_ClipDistance[4];
15024     float gl_CullDistance[4];
15025 };
15026 
15027 void main()
15028 {
15029     for (int n = 0; n < 16; ++n)
15030     {
15031         gl_Position = vec4(n, 0.0, 0.0, 1.0);
15032         EmitVertex();
15033     }
15034 
15035     EndPrimitive();
15036 })";
15037 
15038     constexpr char kFS[] = R"(#version 310 es
15039 precision highp float;
15040 
15041 out vec4 result;
15042 
15043 void main()
15044 {
15045     result = vec4(1.0);
15046 })";
15047 
15048     GLuint program = CompileProgramWithGS(kVS, kGS, kFS);
15049     EXPECT_EQ(0u, program);
15050     glDeleteProgram(program);
15051 }
15052 
15053 // Test varying packing in presence of multiple I/O blocks
TEST_P(GLSLTest_ES31,MultipleIOBlocks)15054 TEST_P(GLSLTest_ES31, MultipleIOBlocks)
15055 {
15056     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
15057 
15058     constexpr char kVS[] = R"(#version 310 es
15059 #extension GL_EXT_shader_io_blocks : require
15060 
15061 in highp vec4 position;
15062 
15063 out VSBlock1
15064 {
15065     vec4 a;
15066     vec4 b[2];
15067 } blockOut1;
15068 
15069 out VSBlock2
15070 {
15071     vec4 c[2];
15072     vec4 d;
15073 } blockOut2;
15074 
15075 void main()
15076 {
15077     blockOut1.a = vec4(0.15, 0.18, 0.21, 0.24);
15078     blockOut1.b[0] = vec4(0.27, 0.30, 0.33, 0.36);
15079     blockOut1.b[1] = vec4(0.39, 0.42, 0.45, 0.48);
15080     blockOut2.c[0] = vec4(0.51, 0.54, 0.57, 0.6);
15081     blockOut2.c[1] = vec4(0.63, 0.66, 0.66, 0.69);
15082     blockOut2.d = vec4(0.72, 0.75, 0.78, 0.81);
15083     gl_Position = position;
15084 })";
15085 
15086     constexpr char kFS[] = R"(#version 310 es
15087 #extension GL_EXT_shader_io_blocks : require
15088 precision mediump float;
15089 
15090 layout(location = 0) out mediump vec4 color;
15091 
15092 in VSBlock1
15093 {
15094     vec4 a;
15095     vec4 b[2];
15096 } blockIn1;
15097 
15098 in VSBlock2
15099 {
15100     vec4 c[2];
15101     vec4 d;
15102 } blockIn2;
15103 
15104 bool isEq(vec4 a, vec4 b) { return all(lessThan(abs(a-b), vec4(0.001))); }
15105 
15106 void main()
15107 {
15108     bool passR = isEq(blockIn1.a, vec4(0.15, 0.18, 0.21, 0.24));
15109     bool passG = isEq(blockIn1.b[0], vec4(0.27, 0.30, 0.33, 0.36)) &&
15110                  isEq(blockIn1.b[1], vec4(0.39, 0.42, 0.45, 0.48));
15111     bool passB = isEq(blockIn2.c[0], vec4(0.51, 0.54, 0.57, 0.6)) &&
15112                  isEq(blockIn2.c[1], vec4(0.63, 0.66, 0.66, 0.69));
15113     bool passA = isEq(blockIn2.d, vec4(0.72, 0.75, 0.78, 0.81));
15114 
15115     color = vec4(passR, passG, passB, passA);
15116 })";
15117 
15118     ANGLE_GL_PROGRAM(program, kVS, kFS);
15119     EXPECT_GL_NO_ERROR();
15120 
15121     GLTexture color;
15122     glBindTexture(GL_TEXTURE_2D, color);
15123     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
15124 
15125     GLFramebuffer fbo;
15126     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
15127     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
15128 
15129     drawQuad(program, "position", 0);
15130 
15131     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
15132 }
15133 
15134 // Test varying packing in presence of I/O block arrays
TEST_P(GLSLTest_ES31,IOBlockArray)15135 TEST_P(GLSLTest_ES31, IOBlockArray)
15136 {
15137     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
15138 
15139     constexpr char kVS[] = R"(#version 310 es
15140 #extension GL_EXT_shader_io_blocks : require
15141 
15142 in highp vec4 position;
15143 
15144 out VSBlock1
15145 {
15146     vec4 b[2];
15147 } blockOut1[2];
15148 
15149 out VSBlock2
15150 {
15151     vec4 d;
15152 } blockOut2[3];
15153 
15154 void main()
15155 {
15156     blockOut1[0].b[0] = vec4(0.15, 0.18, 0.21, 0.24);
15157     blockOut1[0].b[1] = vec4(0.27, 0.30, 0.33, 0.36);
15158     blockOut1[1].b[0] = vec4(0.39, 0.42, 0.45, 0.48);
15159     blockOut1[1].b[1] = vec4(0.51, 0.54, 0.57, 0.6);
15160     blockOut2[0].d = vec4(0.63, 0.66, 0.66, 0.69);
15161     blockOut2[1].d = vec4(0.72, 0.75, 0.78, 0.81);
15162     blockOut2[2].d = vec4(0.84, 0.87, 0.9, 0.93);
15163     gl_Position = position;
15164 })";
15165 
15166     constexpr char kFS[] = R"(#version 310 es
15167 #extension GL_EXT_shader_io_blocks : require
15168 precision mediump float;
15169 
15170 layout(location = 0) out mediump vec4 color;
15171 
15172 in VSBlock1
15173 {
15174     vec4 b[2];
15175 } blockIn1[2];
15176 
15177 in VSBlock2
15178 {
15179     vec4 d;
15180 } blockIn2[3];
15181 
15182 bool isEq(vec4 a, vec4 b) { return all(lessThan(abs(a-b), vec4(0.001))); }
15183 
15184 void main()
15185 {
15186     bool passR = isEq(blockIn1[0].b[0], vec4(0.15, 0.18, 0.21, 0.24)) &&
15187                  isEq(blockIn1[0].b[1], vec4(0.27, 0.30, 0.33, 0.36));
15188     bool passG = isEq(blockIn1[1].b[0], vec4(0.39, 0.42, 0.45, 0.48)) &&
15189                  isEq(blockIn1[1].b[1], vec4(0.51, 0.54, 0.57, 0.6));
15190     bool passB = isEq(blockIn2[0].d, vec4(0.63, 0.66, 0.66, 0.69));
15191     bool passA = isEq(blockIn2[1].d, vec4(0.72, 0.75, 0.78, 0.81)) &&
15192                  isEq(blockIn2[2].d, vec4(0.84, 0.87, 0.9, 0.93));
15193 
15194     color = vec4(passR, passG, passB, passA);
15195 })";
15196 
15197     ANGLE_GL_PROGRAM(program, kVS, kFS);
15198     EXPECT_GL_NO_ERROR();
15199 
15200     GLTexture color;
15201     glBindTexture(GL_TEXTURE_2D, color);
15202     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
15203 
15204     GLFramebuffer fbo;
15205     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
15206     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
15207 
15208     drawQuad(program, "position", 0);
15209 
15210     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
15211 }
15212 
15213 // Validate that link fails with I/O block member name mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberNameMismatch)15214 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberNameMismatch)
15215 {
15216     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
15217 
15218     constexpr char kVS[] = R"(#version 310 es
15219 #extension GL_EXT_shader_io_blocks : require
15220 in highp vec4 position;
15221 out VSBlock { vec4 a; vec4 b[2]; } blockOut1;
15222 void main()
15223 {
15224     blockOut1.a = vec4(0);
15225     blockOut1.b[0] = vec4(0);
15226     blockOut1.b[1] = vec4(0);
15227     gl_Position = position;
15228 })";
15229 
15230     constexpr char kFS[] = R"(#version 310 es
15231 #extension GL_EXT_shader_io_blocks : require
15232 precision mediump float;
15233 layout(location = 0) out mediump vec4 color;
15234 in VSBlock { vec4 c; vec4 b[2]; } blockIn1;
15235 void main()
15236 {
15237     color = vec4(blockIn1.c.x, blockIn1.b[0].y, blockIn1.b[1].z, 1.0);
15238 })";
15239 
15240     GLuint program = CompileProgram(kVS, kFS);
15241     EXPECT_EQ(0u, program);
15242 }
15243 
15244 // Validate that link fails with I/O block member array size mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberArraySizeMismatch)15245 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberArraySizeMismatch)
15246 {
15247     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
15248 
15249     constexpr char kVS[] = R"(#version 310 es
15250 #extension GL_EXT_shader_io_blocks : require
15251 in highp vec4 position;
15252 out VSBlock { vec4 a; vec4 b[2]; } blockOut1;
15253 void main()
15254 {
15255     blockOut1.a = vec4(0);
15256     blockOut1.b[0] = vec4(0);
15257     blockOut1.b[1] = vec4(0);
15258     gl_Position = position;
15259 })";
15260 
15261     constexpr char kFS[] = R"(#version 310 es
15262 #extension GL_EXT_shader_io_blocks : require
15263 precision mediump float;
15264 layout(location = 0) out mediump vec4 color;
15265 in VSBlock { vec4 a; vec4 b[3]; } blockIn1;
15266 void main()
15267 {
15268     color = vec4(blockIn1.a.x, blockIn1.b[0].y, blockIn1.b[1].z, 1.0);
15269 })";
15270 
15271     GLuint program = CompileProgram(kVS, kFS);
15272     EXPECT_EQ(0u, program);
15273 }
15274 
15275 // Validate that link fails with I/O block member type mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberTypeMismatch)15276 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberTypeMismatch)
15277 {
15278     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
15279 
15280     constexpr char kVS[] = R"(#version 310 es
15281 #extension GL_EXT_shader_io_blocks : require
15282 in highp vec4 position;
15283 out VSBlock { vec4 a; vec4 b[2]; } blockOut1;
15284 void main()
15285 {
15286     blockOut1.a = vec4(0);
15287     blockOut1.b[0] = vec4(0);
15288     blockOut1.b[1] = vec4(0);
15289     gl_Position = position;
15290 })";
15291 
15292     constexpr char kFS[] = R"(#version 310 es
15293 #extension GL_EXT_shader_io_blocks : require
15294 precision mediump float;
15295 layout(location = 0) out mediump vec4 color;
15296 in VSBlock { vec3 a; vec4 b[2]; } blockIn1;
15297 void main()
15298 {
15299     color = vec4(blockIn1.a.x, blockIn1.b[0].y, blockIn1.b[1].z, 1.0);
15300 })";
15301 
15302     GLuint program = CompileProgram(kVS, kFS);
15303     EXPECT_EQ(0u, program);
15304 }
15305 
15306 // Validate that link fails with I/O block location mismatches
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkLocationMismatch)15307 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkLocationMismatch)
15308 {
15309     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
15310 
15311     constexpr char kVS[] = R"(#version 310 es
15312 #extension GL_EXT_shader_io_blocks : require
15313 in highp vec4 position;
15314 layout(location = 2) out VSBlock { vec4 a; vec4 b[2]; } blockOut1;
15315 void main()
15316 {
15317     blockOut1.a = vec4(0);
15318     blockOut1.b[0] = vec4(0);
15319     blockOut1.b[1] = vec4(0);
15320     gl_Position = position;
15321 })";
15322 
15323     constexpr char kFS[] = R"(#version 310 es
15324 #extension GL_EXT_shader_io_blocks : require
15325 precision mediump float;
15326 layout(location = 0) out mediump vec4 color;
15327 layout(location = 1) in VSBlock { vec4 a; vec4 b[2]; } blockIn1;
15328 void main()
15329 {
15330     color = vec4(blockIn1.a.x, blockIn1.b[0].y, blockIn1.b[1].z, 1.0);
15331 })";
15332 
15333     GLuint program = CompileProgram(kVS, kFS);
15334     EXPECT_EQ(0u, program);
15335 }
15336 
15337 // Validate that link fails with I/O block member location mismatches
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberLocationMismatch)15338 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberLocationMismatch)
15339 {
15340     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
15341 
15342     constexpr char kVS[] = R"(#version 310 es
15343 #extension GL_EXT_shader_io_blocks : require
15344 in highp vec4 position;
15345 out VSBlock { vec4 a; layout(location = 2) vec4 b[2]; } blockOut1;
15346 void main()
15347 {
15348     blockOut1.a = vec4(0);
15349     blockOut1.b[0] = vec4(0);
15350     blockOut1.b[1] = vec4(0);
15351     gl_Position = position;
15352 })";
15353 
15354     constexpr char kFS[] = R"(#version 310 es
15355 #extension GL_EXT_shader_io_blocks : require
15356 precision mediump float;
15357 layout(location = 0) out mediump vec4 color;
15358 in VSBlock { vec4 a; layout(location = 3) vec4 b[2]; } blockIn1;
15359 void main()
15360 {
15361     color = vec4(blockIn1.a.x, blockIn1.b[0].y, blockIn1.b[1].z, 1.0);
15362 })";
15363 
15364     GLuint program = CompileProgram(kVS, kFS);
15365     EXPECT_EQ(0u, program);
15366 }
15367 
15368 // Validate that link fails with I/O block member struct name mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberStructNameMismatch)15369 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberStructNameMismatch)
15370 {
15371     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
15372 
15373     constexpr char kVS[] = R"(#version 310 es
15374 #extension GL_EXT_shader_io_blocks : require
15375 in highp vec4 position;
15376 struct S1 { vec4 a; vec4 b[2]; };
15377 out VSBlock { S1 s; } blockOut1;
15378 void main()
15379 {
15380     blockOut1.s.a = vec4(0);
15381     blockOut1.s.b[0] = vec4(0);
15382     blockOut1.s.b[1] = vec4(0);
15383     gl_Position = position;
15384 })";
15385 
15386     constexpr char kFS[] = R"(#version 310 es
15387 #extension GL_EXT_shader_io_blocks : require
15388 precision mediump float;
15389 layout(location = 0) out mediump vec4 color;
15390 struct S2 { vec4 a; vec4 b[2]; };
15391 in VSBlock { S2 s; } blockIn1;
15392 void main()
15393 {
15394     color = vec4(blockIn1.s.a.x, blockIn1.s.b[0].y, blockIn1.s.b[1].z, 1.0);
15395 })";
15396 
15397     GLuint program = CompileProgram(kVS, kFS);
15398     EXPECT_EQ(0u, program);
15399 }
15400 
15401 // Validate that link fails with I/O block member struct member name mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberStructMemberNameMismatch)15402 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberStructMemberNameMismatch)
15403 {
15404     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
15405 
15406     constexpr char kVS[] = R"(#version 310 es
15407 #extension GL_EXT_shader_io_blocks : require
15408 in highp vec4 position;
15409 struct S { vec4 c; vec4 b[2]; };
15410 out VSBlock { S s; } blockOut1;
15411 void main()
15412 {
15413     blockOut1.s.c = vec4(0);
15414     blockOut1.s.b[0] = vec4(0);
15415     blockOut1.s.b[1] = vec4(0);
15416     gl_Position = position;
15417 })";
15418 
15419     constexpr char kFS[] = R"(#version 310 es
15420 #extension GL_EXT_shader_io_blocks : require
15421 precision mediump float;
15422 layout(location = 0) out mediump vec4 color;
15423 struct S { vec4 a; vec4 b[2]; };
15424 in VSBlock { S s; } blockIn1;
15425 void main()
15426 {
15427     color = vec4(blockIn1.s.a.x, blockIn1.s.b[0].y, blockIn1.s.b[1].z, 1.0);
15428 })";
15429 
15430     GLuint program = CompileProgram(kVS, kFS);
15431     EXPECT_EQ(0u, program);
15432 }
15433 
15434 // Validate that link fails with I/O block member struct member type mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberStructMemberTypeMismatch)15435 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberStructMemberTypeMismatch)
15436 {
15437     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
15438 
15439     constexpr char kVS[] = R"(#version 310 es
15440 #extension GL_EXT_shader_io_blocks : require
15441 in highp vec4 position;
15442 struct S { vec4 a; vec4 b[2]; };
15443 out VSBlock { S s; } blockOut1;
15444 void main()
15445 {
15446     blockOut1.s.a = vec4(0);
15447     blockOut1.s.b[0] = vec4(0);
15448     blockOut1.s.b[1] = vec4(0);
15449     gl_Position = position;
15450 })";
15451 
15452     constexpr char kFS[] = R"(#version 310 es
15453 #extension GL_EXT_shader_io_blocks : require
15454 precision mediump float;
15455 layout(location = 0) out mediump vec4 color;
15456 struct S { vec3 a; vec4 b[2]; };
15457 in VSBlock { S s; } blockIn1;
15458 void main()
15459 {
15460     color = vec4(blockIn1.s.a.x, blockIn1.s.b[0].y, blockIn1.s.b[1].z, 1.0);
15461 })";
15462 
15463     GLuint program = CompileProgram(kVS, kFS);
15464     EXPECT_EQ(0u, program);
15465 }
15466 
15467 // Validate that link fails with I/O block member struct member array size mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberStructMemberArraySizeMismatch)15468 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberStructMemberArraySizeMismatch)
15469 {
15470     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
15471 
15472     constexpr char kVS[] = R"(#version 310 es
15473 #extension GL_EXT_shader_io_blocks : require
15474 in highp vec4 position;
15475 struct S { vec4 a; vec4 b[3]; };
15476 out VSBlock { S s; } blockOut1;
15477 void main()
15478 {
15479     blockOut1.s.a = vec4(0);
15480     blockOut1.s.b[0] = vec4(0);
15481     blockOut1.s.b[1] = vec4(0);
15482     gl_Position = position;
15483 })";
15484 
15485     constexpr char kFS[] = R"(#version 310 es
15486 #extension GL_EXT_shader_io_blocks : require
15487 precision mediump float;
15488 layout(location = 0) out mediump vec4 color;
15489 struct S { vec4 a; vec4 b[2]; };
15490 in VSBlock { S s; } blockIn1;
15491 void main()
15492 {
15493     color = vec4(blockIn1.s.a.x, blockIn1.s.b[0].y, blockIn1.s.b[1].z, 1.0);
15494 })";
15495 
15496     GLuint program = CompileProgram(kVS, kFS);
15497     EXPECT_EQ(0u, program);
15498 }
15499 
15500 // Validate that link fails with I/O block member struct member count mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberStructMemberCountMismatch)15501 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberStructMemberCountMismatch)
15502 {
15503     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
15504 
15505     constexpr char kVS[] = R"(#version 310 es
15506 #extension GL_EXT_shader_io_blocks : require
15507 in highp vec4 position;
15508 struct S { vec4 a; vec4 b[2]; vec4 c; };
15509 out VSBlock { S s; } blockOut1;
15510 void main()
15511 {
15512     blockOut1.s.c = vec4(0);
15513     blockOut1.s.b[0] = vec4(0);
15514     blockOut1.s.b[1] = vec4(0);
15515     gl_Position = position;
15516 })";
15517 
15518     constexpr char kFS[] = R"(#version 310 es
15519 #extension GL_EXT_shader_io_blocks : require
15520 precision mediump float;
15521 layout(location = 0) out mediump vec4 color;
15522 struct S { vec4 a; vec4 b[2]; };
15523 in VSBlock { S s; } blockIn1;
15524 void main()
15525 {
15526     color = vec4(blockIn1.s.a.x, blockIn1.s.b[0].y, blockIn1.s.b[1].z, 1.0);
15527 })";
15528 
15529     GLuint program = CompileProgram(kVS, kFS);
15530     EXPECT_EQ(0u, program);
15531 }
15532 
15533 // Validate that link fails with I/O block member nested struct mismatches.
TEST_P(GLSLTest_ES31,NegativeIOBlocksLinkMemberNestedStructMismatch)15534 TEST_P(GLSLTest_ES31, NegativeIOBlocksLinkMemberNestedStructMismatch)
15535 {
15536     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
15537 
15538     constexpr char kVS[] = R"(#version 310 es
15539 #extension GL_EXT_shader_io_blocks : require
15540 in highp vec4 position;
15541 struct S1 { vec4 c; vec4 b[2]; };
15542 struct S2 { S1 s; };
15543 struct S3 { S2 s; };
15544 out VSBlock { S3 s; } blockOut1;
15545 void main()
15546 {
15547     blockOut1.s.s.s.c = vec4(0);
15548     blockOut1.s.s.s.b[0] = vec4(0);
15549     blockOut1.s.s.s.b[1] = vec4(0);
15550     gl_Position = position;
15551 })";
15552 
15553     constexpr char kFS[] = R"(#version 310 es
15554 #extension GL_EXT_shader_io_blocks : require
15555 precision mediump float;
15556 layout(location = 0) out mediump vec4 color;
15557 struct S1 { vec4 a; vec4 b[2]; };
15558 struct S2 { S1 s; };
15559 struct S3 { S2 s; };
15560 in VSBlock { S3 s; } blockIn1;
15561 void main()
15562 {
15563     color = vec4(blockIn1.s.s.s.a.x, blockIn1.s.s.s.b[0].y, blockIn1.s.s.s.b[1].z, 1.0);
15564 })";
15565 
15566     GLuint program = CompileProgram(kVS, kFS);
15567     EXPECT_EQ(0u, program);
15568 }
15569 
15570 // Test that separating declarators works with structs that have been separately defined.
TEST_P(GLSLTest_ES31,SeparateDeclaratorsOfStructType)15571 TEST_P(GLSLTest_ES31, SeparateDeclaratorsOfStructType)
15572 {
15573     constexpr char kVS[] = R"(#version 310 es
15574 precision highp float;
15575 
15576 struct S
15577 {
15578     mat4 a;
15579     mat4 b;
15580 };
15581 
15582 S s1 = S(mat4(1), mat4(2)), s2[2][3], s3[2] = S[2](S(mat4(0), mat4(3)), S(mat4(4), mat4(5)));
15583 
15584 void main() {
15585     S s4[2][3] = s2, s5 = s3[0], s6[2] = S[2](s1, s5), s7 = s5;
15586 
15587     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);
15588 })";
15589 
15590     GLuint shader = glCreateShader(GL_VERTEX_SHADER);
15591 
15592     const char *sourceArray[1] = {kVS};
15593     GLint lengths[1]           = {static_cast<GLint>(sizeof(kVS) - 1)};
15594     glShaderSource(shader, 1, sourceArray, lengths);
15595     glCompileShader(shader);
15596 
15597     GLint compileResult;
15598     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
15599     EXPECT_NE(compileResult, 0);
15600 }
15601 
15602 // Test that separating declarators works with structs that are simultaneously defined.
TEST_P(GLSLTest_ES31,SeparateDeclaratorsOfStructTypeBeingSpecified)15603 TEST_P(GLSLTest_ES31, SeparateDeclaratorsOfStructTypeBeingSpecified)
15604 {
15605     constexpr char kVS[] = R"(#version 310 es
15606 precision highp float;
15607 
15608 struct S
15609 {
15610     mat4 a;
15611     mat4 b;
15612 } s1 = S(mat4(1), mat4(2)), s2[2][3], s3[2] = S[2](S(mat4(0), mat4(3)), S(mat4(4), mat4(5)));
15613 
15614 void main() {
15615     struct T
15616     {
15617         mat4 a;
15618         mat4 b;
15619     } s4[2][3], s5 = T(s3[0].a, s3[0].b), s6[2] = T[2](T(s1.a, s1.b), s5), s7 = s5;
15620 
15621     float f1 = s3[1].a[0].x, f2 = s2[0][2].b[1].y;
15622 
15623     gl_Position = vec4(f1, f2, s4[1][0].a[2].z, s6[0].b[3].w);
15624 })";
15625 
15626     GLuint shader = glCreateShader(GL_VERTEX_SHADER);
15627 
15628     const char *sourceArray[1] = {kVS};
15629     GLint lengths[1]           = {static_cast<GLint>(sizeof(kVS) - 1)};
15630     glShaderSource(shader, 1, sourceArray, lengths);
15631     glCompileShader(shader);
15632 
15633     GLint compileResult;
15634     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
15635     EXPECT_NE(compileResult, 0);
15636 }
15637 
15638 // Test that separating declarators works with structs that are simultaneously defined and that are
15639 // nameless.
TEST_P(GLSLTest_ES31,SeparateDeclaratorsOfNamelessStructType)15640 TEST_P(GLSLTest_ES31, SeparateDeclaratorsOfNamelessStructType)
15641 {
15642     constexpr char kVS[] = R"(#version 310 es
15643 precision highp float;
15644 
15645 struct
15646 {
15647     mat4 a;
15648     mat4 b;
15649 } s1, s2[2][3], s3[2];
15650 
15651 void main() {
15652     struct
15653     {
15654         mat4 a;
15655         mat4 b;
15656     } s4[2][3], s5, s6[2], s7 = s5;
15657 
15658     float f1 = s1.a[0].x + s3[1].a[0].x, f2 = s2[0][2].b[1].y + s7.b[1].z;
15659 
15660     gl_Position = vec4(f1, f2, s4[1][0].a[2].z, s6[0].b[3].w);
15661 })";
15662 
15663     GLuint shader = glCreateShader(GL_VERTEX_SHADER);
15664 
15665     const char *sourceArray[1] = {kVS};
15666     GLint lengths[1]           = {static_cast<GLint>(sizeof(kVS) - 1)};
15667     glShaderSource(shader, 1, sourceArray, lengths);
15668     glCompileShader(shader);
15669 
15670     GLint compileResult;
15671     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
15672     EXPECT_NE(compileResult, 0);
15673 }
15674 
15675 // Test separation of struct declarations, case where separated struct is used as a member of
15676 // another struct.
TEST_P(GLSLTest,SeparateStructDeclaratorStructInStruct)15677 TEST_P(GLSLTest, SeparateStructDeclaratorStructInStruct)
15678 {
15679     const char kFragmentShader[] = R"(precision mediump float;
15680 uniform vec4 u;
15681 struct S1 { vec4 v; } a;
15682 void main()
15683 {
15684     struct S2 { S1 s1; } b;
15685     a.v = u;
15686     b.s1 = a;
15687     gl_FragColor = b.s1.v + vec4(0, 0, 0, 1);
15688 }
15689 )";
15690     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
15691     glUseProgram(program);
15692     GLint u = glGetUniformLocation(program, "u");
15693     glUniform4f(u, 0, 1, 0, 0);
15694     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
15695     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
15696 }
15697 
15698 // Regression test for transformation bug which separates struct declarations from uniform
15699 // declarations.  The bug was that the uniform variable usage in the initializer of a new
15700 // declaration (y below) was not being processed.
TEST_P(GLSLTest,UniformStructBug)15701 TEST_P(GLSLTest, UniformStructBug)
15702 {
15703     constexpr char kVS[] = R"(precision highp float;
15704 
15705 uniform struct Global
15706 {
15707     float x;
15708 } u_global;
15709 
15710 void main() {
15711   float y = u_global.x;
15712 
15713   gl_Position = vec4(y);
15714 })";
15715 
15716     GLuint shader = glCreateShader(GL_VERTEX_SHADER);
15717 
15718     const char *sourceArray[1] = {kVS};
15719     GLint lengths[1]           = {static_cast<GLint>(sizeof(kVS) - 1)};
15720     glShaderSource(shader, 1, sourceArray, lengths);
15721     glCompileShader(shader);
15722 
15723     GLint compileResult;
15724     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
15725     EXPECT_NE(compileResult, 0);
15726 }
15727 
15728 // Regression test for transformation bug which separates struct declarations from uniform
15729 // declarations.  The bug was that the arrayness of the declaration was not being applied to the
15730 // replaced uniform variable.
TEST_P(GLSLTest_ES31,UniformStructBug2)15731 TEST_P(GLSLTest_ES31, UniformStructBug2)
15732 {
15733     constexpr char kVS[] = R"(#version 310 es
15734 precision highp float;
15735 
15736 uniform struct Global
15737 {
15738     float x;
15739 } u_global[2][3];
15740 
15741 void main() {
15742   float y = u_global[0][0].x;
15743 
15744   gl_Position = vec4(y);
15745 })";
15746 
15747     GLuint shader = glCreateShader(GL_VERTEX_SHADER);
15748 
15749     const char *sourceArray[1] = {kVS};
15750     GLint lengths[1]           = {static_cast<GLint>(sizeof(kVS) - 1)};
15751     glShaderSource(shader, 1, sourceArray, lengths);
15752     glCompileShader(shader);
15753 
15754     GLint compileResult;
15755     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
15756     EXPECT_NE(compileResult, 0);
15757 }
15758 
15759 // Regression test based on fuzzer issue resulting in an AST validation failure.  Struct definition
15760 // was not found in the tree.  Tests that struct declaration in function return value is visible to
15761 // instantiations later on.
TEST_P(GLSLTest,MissingStructDeclarationBug)15762 TEST_P(GLSLTest, MissingStructDeclarationBug)
15763 {
15764     constexpr char kVS[] = R"(
15765 struct S
15766 {
15767     vec4 i;
15768 } p();
15769 void main()
15770 {
15771     S s;
15772 })";
15773 
15774     GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
15775     EXPECT_NE(0u, shader);
15776     glDeleteShader(shader);
15777 }
15778 
15779 // Regression test based on fuzzer issue resulting in an AST validation failure.  Struct definition
15780 // was not found in the tree.  Tests that struct declaration in function return value is visible to
15781 // other struct declarations.
TEST_P(GLSLTest,MissingStructDeclarationBug2)15782 TEST_P(GLSLTest, MissingStructDeclarationBug2)
15783 {
15784     constexpr char kVS[] = R"(
15785 struct T
15786 {
15787     vec4 I;
15788 } p();
15789 struct
15790 {
15791     T c;
15792 };
15793 void main()
15794 {
15795 })";
15796 
15797     GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
15798     EXPECT_NE(0u, shader);
15799     glDeleteShader(shader);
15800 }
15801 
15802 // Regression test for bug in HLSL code generation where the for loop init expression was expected
15803 // to always have an initializer.
TEST_P(GLSLTest,HandleExcessiveLoopBug)15804 TEST_P(GLSLTest, HandleExcessiveLoopBug)
15805 {
15806     constexpr char kVS[] = R"(void main(){for(int i;i>6;);})";
15807 
15808     GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
15809     EXPECT_NE(0u, shader);
15810     glDeleteShader(shader);
15811 }
15812 
15813 // Regression test for a validation bug in the translator where func(void, int) was accepted even
15814 // though it's illegal, and the function was callable as if the void parameter isn't there.
TEST_P(GLSLTest,NoParameterAfterVoid)15815 TEST_P(GLSLTest, NoParameterAfterVoid)
15816 {
15817     constexpr char kVS[] = R"(void f(void, int a){}
15818 void main(){f(1);})";
15819 
15820     GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
15821     EXPECT_EQ(0u, shader);
15822     glDeleteShader(shader);
15823 }
15824 
15825 // Similar to NoParameterAfterVoid, but tests func(void, void).
TEST_P(GLSLTest,NoParameterAfterVoid2)15826 TEST_P(GLSLTest, NoParameterAfterVoid2)
15827 {
15828     constexpr char kVS[] = R"(void f(void, void){}
15829 void main(){f();})";
15830 
15831     GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
15832     EXPECT_EQ(0u, shader);
15833     glDeleteShader(shader);
15834 }
15835 
15836 // Test that providing more components to a matrix constructor than necessary works.  Based on a
15837 // clusterfuzz test that caught an OOB array write in glslang.
TEST_P(GLSLTest,MatrixConstructor)15838 TEST_P(GLSLTest, MatrixConstructor)
15839 {
15840     constexpr char kVS[] = R"(attribute vec4 aPosition;
15841 varying vec4 vColor;
15842 void main()
15843 {
15844     gl_Position = aPosition;
15845     vec4 color = vec4(aPosition.xy, 0, 1);
15846     mat4 m4 = mat4(color, color.yzwx, color.zwx, color.zwxy, color.wxyz);
15847     vColor = m4[0];
15848 })";
15849 
15850     GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
15851     EXPECT_NE(0u, shader);
15852     glDeleteShader(shader);
15853 }
15854 
15855 // Test constructors without precision
TEST_P(GLSLTest,ConstructFromBoolVector)15856 TEST_P(GLSLTest, ConstructFromBoolVector)
15857 {
15858     constexpr char kFS[] = R"(precision mediump float;
15859 uniform float u;
15860 void main()
15861 {
15862     mat4 m = mat4(u);
15863     mat2(0, bvec3(m));
15864     gl_FragColor = vec4(m);
15865 })";
15866 
15867     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
15868     EXPECT_NE(0u, shader);
15869     glDeleteShader(shader);
15870 }
15871 
15872 // Test constructing vector from matrix
TEST_P(GLSLTest,VectorConstructorFromMatrix)15873 TEST_P(GLSLTest, VectorConstructorFromMatrix)
15874 {
15875     constexpr char kFS[] = R"(precision mediump float;
15876 uniform mat2 umat2;
15877 void main()
15878 {
15879     gl_FragColor = vec4(umat2);
15880 })";
15881 
15882     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
15883     EXPECT_NE(0u, shader);
15884     glDeleteShader(shader);
15885 }
15886 
15887 // Test constructing matrix from vectors
TEST_P(GLSLTest,MatrixConstructorFromVectors)15888 TEST_P(GLSLTest, MatrixConstructorFromVectors)
15889 {
15890     constexpr char kFS[] = R"(precision mediump float;
15891 uniform vec2 uvec2;
15892 void main()
15893 {
15894     mat2 m = mat2(uvec2, uvec2.yx);
15895     gl_FragColor = vec4(m * uvec2, uvec2);
15896 })";
15897 
15898     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
15899     glUseProgram(program);
15900 
15901     GLint uloc = glGetUniformLocation(program, "uvec2");
15902     ASSERT_NE(uloc, -1);
15903     glUniform2f(uloc, 0.5, 0.8);
15904 
15905     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
15906     EXPECT_GL_NO_ERROR();
15907 
15908     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(227, 204, 127, 204), 1);
15909 }
15910 
15911 // Test that constructing vector and matrix inside multiple declarations preserves the correct order
15912 // of operations.
TEST_P(GLSLTest,ConstructorinSequenceOperator)15913 TEST_P(GLSLTest, ConstructorinSequenceOperator)
15914 {
15915     constexpr char kFS[] = R"(precision mediump float;
15916 uniform vec2 u;
15917 void main()
15918 {
15919     vec2 v = u;
15920     mat2 m = (v[0] += 1.0, mat2(v, v[1], -v[0]));
15921     gl_FragColor = vec4(m[0], m[1]);
15922 })";
15923 
15924     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
15925     glUseProgram(program);
15926 
15927     GLint uloc = glGetUniformLocation(program, "u");
15928     ASSERT_NE(uloc, -1);
15929     glUniform2f(uloc, -0.5, 1.0);
15930 
15931     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
15932     EXPECT_GL_NO_ERROR();
15933 
15934     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(127, 255, 255, 0), 1);
15935 }
15936 
15937 // Test that constructing vectors inside multiple declarations preserves the correct order
15938 // of operations.
TEST_P(GLSLTest,VectorConstructorsInMultiDeclaration)15939 TEST_P(GLSLTest, VectorConstructorsInMultiDeclaration)
15940 {
15941     constexpr char kFS[] = R"(precision mediump float;
15942 uniform vec2 u;
15943 void main()
15944 {
15945     vec2 v = vec2(u[0]),
15946          w = mat2(v, v) * u;
15947     gl_FragColor = vec4(v, w);
15948 })";
15949 
15950     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
15951     glUseProgram(program);
15952 
15953     GLint uloc = glGetUniformLocation(program, "u");
15954     ASSERT_NE(uloc, -1);
15955     glUniform2f(uloc, 0.5, 0.8);
15956 
15957     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
15958     EXPECT_GL_NO_ERROR();
15959 
15960     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(127, 127, 166, 166), 1);
15961 }
15962 
15963 // Test complex constructor usage.
TEST_P(GLSLTest_ES3,ComplexConstructor)15964 TEST_P(GLSLTest_ES3, ComplexConstructor)
15965 {
15966     constexpr char kFS[] = R"(#version 300 es
15967 precision mediump float;
15968 uniform vec2 u; // = vec2(0.5, 0.8)
15969 uniform vec2 v; // = vec2(-0.2, 1.0)
15970 
15971 out vec4 color;
15972 
15973 bool f(mat2 m)
15974 {
15975     return m[0][0] > 0.;
15976 }
15977 
15978 bool isEqual(float a, float b)
15979 {
15980     return abs(a - b) < 0.01;
15981 }
15982 
15983 void main()
15984 {
15985     int shouldRemainZero = 0;
15986 
15987     // Test side effects inside constructor args after short-circuit
15988     if (u.x < 0. && f(mat2(shouldRemainZero += 1, u, v)))
15989     {
15990         shouldRemainZero += 2;
15991     }
15992 
15993     int shouldBecomeFive = 0;
15994 
15995     // Test directly nested constructors
15996     mat4x3 m = mat4x3(mat2(shouldBecomeFive += 5, v, u));
15997 
15998     // Test indirectly nested constructors
15999     mat2 m2 = mat2(f(mat2(u, v)), f(mat2(v, u)), f(mat2(f(mat2(1.)))), -1.);
16000 
16001     // Verify
16002     bool sideEffectsOk = shouldRemainZero == 0 && shouldBecomeFive == 5;
16003 
16004     bool mOk = isEqual(m[0][0], 5.) && isEqual(m[0][1], -0.2) && isEqual(m[0][2], 0.) &&
16005                isEqual(m[1][0], 1.) && isEqual(m[1][1], 0.5) && isEqual(m[1][2], 0.) &&
16006                isEqual(m[2][0], 0.) && isEqual(m[2][1], 0.) && isEqual(m[2][2], 1.) &&
16007                isEqual(m[3][0], 0.) && isEqual(m[3][1], 0.) && isEqual(m[3][2], 0.);
16008 
16009     bool m2Ok = isEqual(m2[0][0], 1.) && isEqual(m2[0][1], 0.) &&
16010                isEqual(m2[1][0], 1.) && isEqual(m2[1][1], -1.);
16011 
16012     color = vec4(sideEffectsOk ? 1 : 0, mOk ? 1 : 0, m2Ok ? 1 : 0, 1);
16013 })";
16014 
16015     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
16016     glUseProgram(program);
16017 
16018     GLint uloc = glGetUniformLocation(program, "u");
16019     GLint vloc = glGetUniformLocation(program, "v");
16020     ASSERT_NE(uloc, -1);
16021     ASSERT_NE(vloc, -1);
16022     glUniform2f(uloc, 0.5, 0.8);
16023     glUniform2f(vloc, -0.2, 1.0);
16024 
16025     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
16026     EXPECT_GL_NO_ERROR();
16027 
16028     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
16029 }
16030 
16031 // Test that scalar(nonScalar) constructors work.
TEST_P(GLSLTest_ES3,ScalarConstructor)16032 TEST_P(GLSLTest_ES3, ScalarConstructor)
16033 {
16034     constexpr char kFS[] = R"(#version 300 es
16035 precision mediump float;
16036 uniform vec4 u;
16037 out vec4 color;
16038 void main()
16039 {
16040     float f1 = float(u);
16041     mat3 m = mat3(u, u, u);
16042     int i = int(m);
16043     color = vec4(f1, float(i), 0, 1);
16044 })";
16045 
16046     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
16047     glUseProgram(program);
16048 
16049     GLint uloc = glGetUniformLocation(program, "u");
16050     ASSERT_NE(uloc, -1);
16051     glUniform4f(uloc, 1.0, 0.4, 0.2, 0.7);
16052 
16053     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
16054     EXPECT_GL_NO_ERROR();
16055 
16056     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
16057 }
16058 
16059 // Test that initializing global variables with non-constant values work
TEST_P(GLSLTest_ES3,InitGlobalNonConstant)16060 TEST_P(GLSLTest_ES3, InitGlobalNonConstant)
16061 {
16062     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_non_constant_global_initializers"));
16063 
16064     constexpr char kVS[] = R"(#version 300 es
16065 #extension GL_EXT_shader_non_constant_global_initializers : require
16066 uniform vec4 u;
16067 out vec4 color;
16068 
16069 vec4 global1 = u;
16070 vec4 global2 = u + vec4(1);
16071 vec4 global3 = global1 * global2;
16072 void main()
16073 {
16074     color = global3;
16075 })";
16076 
16077     GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
16078     EXPECT_NE(0u, shader);
16079     glDeleteShader(shader);
16080 }
16081 
16082 // Test that initializing global variables with complex constants work
TEST_P(GLSLTest_ES3,InitGlobalComplexConstant)16083 TEST_P(GLSLTest_ES3, InitGlobalComplexConstant)
16084 {
16085     constexpr char kFS[] = R"(#version 300 es
16086 precision highp float;
16087 out vec4 color;
16088 
16089 struct T
16090 {
16091     float f;
16092 };
16093 
16094 struct S
16095 {
16096     vec4 v;
16097     mat3x4 m[2];
16098     T t;
16099 };
16100 
16101 S s = S(
16102         vec4(0, 1, 2, 3),
16103         mat3x4[2](
16104                   mat3x4(
16105                          vec4(4, 5, 6, 7),
16106                          vec4(8, 9, 10, 11),
16107                          vec4(12, 13, 14, 15)
16108                   ),
16109                   mat3x4(
16110                          vec4(16, 17, 18, 19),
16111                          vec4(20, 21, 22, 23),
16112                          vec4(24, 25, 26, 27)
16113                   )
16114         ),
16115         T(28.0)
16116        );
16117 
16118 void main()
16119 {
16120     vec4 result = vec4(0, 1, 0, 1);
16121 
16122     if (s.v != vec4(0, 1, 2, 3))
16123         result = vec4(1, 0, 0, 0);
16124 
16125     for (int index = 0; index < 2; ++index)
16126     {
16127         for (int column = 0; column < 3; ++column)
16128         {
16129             int expect = index * 12 + column * 4 + 4;
16130             if (s.m[index][column] != vec4(expect, expect + 1, expect + 2, expect + 3))
16131                 result = vec4(float(index + 1) / 2.0, 0, float(column + 1) / 3.0, 1);
16132         }
16133     }
16134 
16135     if (s.t.f != 28.0)
16136         result = vec4(0, 0, 1, 0);
16137 
16138     color = result;
16139 })";
16140 
16141     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
16142 
16143     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
16144     EXPECT_GL_NO_ERROR();
16145 
16146     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
16147 }
16148 
16149 // Test that built-ins with out parameters work
TEST_P(GLSLTest_ES31,BuiltInsWithOutParameters)16150 TEST_P(GLSLTest_ES31, BuiltInsWithOutParameters)
16151 {
16152     constexpr char kFS[] = R"(#version 310 es
16153 precision highp float;
16154 precision highp int;
16155 
16156 out vec4 color;
16157 
16158 uniform float f;    // = 3.41
16159 uniform uvec4 u1;   // = 0xFEDCBA98, 0x13579BDF, 0xFEDCBA98, 0x13579BDF
16160 uniform uvec4 u2;   // = 0xECA86420, 0x12345678, 0x12345678, 0xECA86420
16161 
16162 struct S
16163 {
16164     float fvalue;
16165     int ivalues[2];
16166     uvec4 uvalues[3];
16167 };
16168 
16169 struct T
16170 {
16171     S s[2];
16172 };
16173 
16174 void main()
16175 {
16176     float integer;
16177     float fraction = modf(f, integer);
16178 
16179     T t;
16180 
16181     t.s[0].fvalue     = frexp(f, t.s[0].ivalues[0]);
16182     float significand = t.s[0].fvalue;
16183     int exponent      = t.s[0].ivalues[0];
16184 
16185     t.s[0].uvalues[0] = uaddCarry(u1, u2, t.s[0].uvalues[1].yxwz);
16186     uvec4 addResult   = t.s[0].uvalues[0];
16187     uvec4 addCarry    = t.s[0].uvalues[1].yxwz;
16188 
16189     t.s[0].uvalues[2].wx = usubBorrow(u1.wx, u2.wx, t.s[1].uvalues[0].wx);
16190     uvec2 subResult      = t.s[0].uvalues[2].wx;
16191     uvec2 subBorrow      = t.s[1].uvalues[0].wx;
16192 
16193     umulExtended(u1, u2, t.s[1].uvalues[1], t.s[1].uvalues[2]);
16194     uvec4 mulMsb = t.s[1].uvalues[1];
16195     uvec4 mulLsb = t.s[1].uvalues[2];
16196 
16197     ivec2 imulMsb, imulLsb;
16198     imulExtended(ivec2(u1.wz), ivec2(u2.wz), imulMsb.yx, imulLsb.yx);
16199 
16200     bool modfPassed = abs(fraction - 0.41) < 0.0001 && integer == 3.0;
16201     bool frexpPassed = abs(significand - 0.8525) < 0.0001 && exponent == 2;
16202     bool addPassed =
16203         addResult == uvec4(0xEB851EB8, 0x258BF257, 0x11111110, 0xFFFFFFFF) &&
16204         addCarry == uvec4(1, 0, 1, 0);
16205     bool subPassed = subResult == uvec2(0x26AF37BF, 0x12345678) && subBorrow == uvec2(1, 0);
16206     bool mulPassed =
16207         mulMsb == uvec4(0xEB9B208C, 0x01601D49, 0x121FA00A, 0x11E17CC0) &&
16208         mulLsb == uvec4(0xA83AB300, 0xD6B9FA88, 0x35068740, 0x822E97E0);
16209     bool imulPassed =
16210         imulMsb == ivec2(0xFFEB4992, 0xFE89E0E1) &&
16211         imulLsb == ivec2(0x35068740, 0x822E97E0);
16212 
16213     color = vec4(modfPassed ? 1 : 0,
16214                  frexpPassed ? 1 : 0,
16215                  (addPassed ? 0.4 : 0.0) + (subPassed ? 0.6 : 0.0),
16216                  (mulPassed ? 0.4 : 0.0) + (imulPassed ? 0.6 : 0.0));
16217 })";
16218 
16219     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
16220     glUseProgram(program);
16221 
16222     GLint floc  = glGetUniformLocation(program, "f");
16223     GLint u1loc = glGetUniformLocation(program, "u1");
16224     GLint u2loc = glGetUniformLocation(program, "u2");
16225     ASSERT_NE(floc, -1);
16226     ASSERT_NE(u1loc, -1);
16227     ASSERT_NE(u2loc, -1);
16228     glUniform1f(floc, 3.41);
16229     glUniform4ui(u1loc, 0xFEDCBA98u, 0x13579BDFu, 0xFEDCBA98u, 0x13579BDFu);
16230     glUniform4ui(u2loc, 0xECA86420u, 0x12345678u, 0x12345678u, 0xECA86420u);
16231 
16232     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
16233     EXPECT_GL_NO_ERROR();
16234 
16235     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
16236 }
16237 
16238 class GLSLTestLoops : public GLSLTest
16239 {
16240   protected:
runTest(const char * fs)16241     void runTest(const char *fs)
16242     {
16243         ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fs);
16244 
16245         drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
16246         EXPECT_GL_NO_ERROR();
16247 
16248         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
16249     }
16250 };
16251 
16252 // Test basic for loops
TEST_P(GLSLTestLoops,BasicFor)16253 TEST_P(GLSLTestLoops, BasicFor)
16254 {
16255     constexpr char kFS[] = R"(#version 300 es
16256 precision mediump float;
16257 out vec4 color;
16258 
16259 void main()
16260 {
16261     int result = 0;
16262     for (int i = 0; i < 10; ++i)
16263         for (int j = 0; j < 8; ++j)
16264         {
16265             for (int k = 0; k < 2; ++k, ++j) ++result;
16266             for (int k = 0; k < 3; ++k)      ++result;
16267             for (int k = 0; k < 0; ++k)      ++result;
16268         }
16269 
16270     color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16271 })";
16272 
16273     runTest(kFS);
16274 }
16275 
16276 // Test for loop without condition
TEST_P(GLSLTestLoops,ForNoCondition)16277 TEST_P(GLSLTestLoops, ForNoCondition)
16278 {
16279     constexpr char kFS[] = R"(#version 300 es
16280 precision mediump float;
16281 out vec4 color;
16282 
16283 void main()
16284 {
16285     int result = 0;
16286     for (int i = 0; i < 10; ++i)
16287         for (int j = 0; ; ++j)
16288         {
16289             for (int k = 0; k < 2; ++k, ++j) ++result;
16290             for (int k = 0; k < 3; ++k)      ++result;
16291             for (int k = 0; k < 0; ++k)      ++result;
16292 
16293             if (j >= 8)
16294                 break;
16295         }
16296 
16297     color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16298 })";
16299 
16300     runTest(kFS);
16301 }
16302 
16303 // Test for loop without init and expression
TEST_P(GLSLTestLoops,ForNoInitConditionOrExpression)16304 TEST_P(GLSLTestLoops, ForNoInitConditionOrExpression)
16305 {
16306     constexpr char kFS[] = R"(#version 300 es
16307 precision mediump float;
16308 out vec4 color;
16309 
16310 void main()
16311 {
16312     int result = 0;
16313     for (int i = 0; i < 10; ++i)
16314     {
16315         int j = 0;
16316         for (;;)
16317         {
16318             for (int k = 0; k < 2; ++k, ++j) ++result;
16319             for (int k = 0; k < 3; ++k)      ++result;
16320             for (int k = 0; k < 0; ++k)      ++result;
16321 
16322             if (j >= 8)
16323                 break;
16324             ++j;
16325         }
16326     }
16327 
16328     color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16329 })";
16330 
16331     runTest(kFS);
16332 }
16333 
16334 // Test for loop with continue
TEST_P(GLSLTestLoops,ForContinue)16335 TEST_P(GLSLTestLoops, ForContinue)
16336 {
16337     constexpr char kFS[] = R"(#version 300 es
16338 precision mediump float;
16339 out vec4 color;
16340 
16341 void main()
16342 {
16343     int result = 0;
16344     for (int i = 0; i < 10; ++i)
16345         for (int j = 0; j < 8; ++j)
16346         {
16347             for (int k = 0; k < 2; ++k, ++j) ++result;
16348             for (int k = 0; k < 3; ++k)      ++result;
16349             if (i > 3)
16350                 continue;
16351             for (int k = 0; k < 0; ++k)      ++result;
16352         }
16353 
16354     color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16355 })";
16356 
16357     runTest(kFS);
16358 }
16359 
16360 // Test for loop with continue at the end of block
TEST_P(GLSLTestLoops,ForUnconditionalContinue)16361 TEST_P(GLSLTestLoops, ForUnconditionalContinue)
16362 {
16363     constexpr char kFS[] = R"(#version 300 es
16364 precision mediump float;
16365 out vec4 color;
16366 
16367 void main()
16368 {
16369     int result = 0;
16370     for (int i = 0; i < 10; ++i)
16371         for (int j = 0; j < 8; ++j)
16372         {
16373             for (int k = 0; k < 2; ++k, ++j) ++result;
16374             for (int k = 0; k < 3; ++k)      ++result;
16375             for (int k = 0; k < 0; ++k)      ++result;
16376             continue;
16377         }
16378 
16379     color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16380 })";
16381 
16382     runTest(kFS);
16383 }
16384 
16385 // Test for loop with break at the end of block
TEST_P(GLSLTestLoops,ForUnconditionalBreak)16386 TEST_P(GLSLTestLoops, ForUnconditionalBreak)
16387 {
16388     constexpr char kFS[] = R"(#version 300 es
16389 precision mediump float;
16390 out vec4 color;
16391 
16392 void main()
16393 {
16394     int result = 0;
16395     for (int i = 0; i < 10; ++i)
16396         for (int j = 0; j < 8; ++j)
16397         {
16398             for (int k = 0; k < 2; ++k, ++j) ++result;
16399             for (int k = 0; k < 3; ++k)      ++result;
16400             for (int k = 0; k < 0; ++k)      ++result;
16401             break;
16402         }
16403 
16404     color = result == 50 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16405 })";
16406 
16407     runTest(kFS);
16408 }
16409 
16410 // Test for loop with break and continue
TEST_P(GLSLTestLoops,ForBreakContinue)16411 TEST_P(GLSLTestLoops, ForBreakContinue)
16412 {
16413     constexpr char kFS[] = R"(#version 300 es
16414 precision mediump float;
16415 out vec4 color;
16416 
16417 void main()
16418 {
16419     int result = 0;
16420     for (int i = 0; i < 10; ++i)
16421         for (int j = 0; j < 8; ++j)
16422         {
16423             if (j < 2) continue;
16424             if (j > 6) break;
16425             if (i < 3) continue;
16426             if (i > 8) break;
16427             ++result;
16428         }
16429 
16430     color = result == 30 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16431 })";
16432 
16433     runTest(kFS);
16434 }
16435 
16436 // Test basic while loops
TEST_P(GLSLTestLoops,BasicWhile)16437 TEST_P(GLSLTestLoops, BasicWhile)
16438 {
16439     constexpr char kFS[] = R"(#version 300 es
16440 precision mediump float;
16441 out vec4 color;
16442 
16443 void main()
16444 {
16445     int result = 0;
16446     int i = 0;
16447     while (i < 10)
16448     {
16449         int j = 0;
16450         while (j < 8)
16451         {
16452             int k = 0;
16453             while (k < 2) { ++result; ++k; ++j; }
16454             while (k < 5) { ++result; ++k; }
16455             while (k < 4) { ++result; }
16456             ++j;
16457         }
16458         ++i;
16459     }
16460 
16461     color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16462 })";
16463 
16464     runTest(kFS);
16465 }
16466 
16467 // Test while loops with continue
TEST_P(GLSLTestLoops,WhileContinue)16468 TEST_P(GLSLTestLoops, WhileContinue)
16469 {
16470     constexpr char kFS[] = R"(#version 300 es
16471 precision mediump float;
16472 out vec4 color;
16473 
16474 void main()
16475 {
16476     int result = 0;
16477     int i = 0;
16478     while (i < 10)
16479     {
16480         int j = 0;
16481         while (j < 8)
16482         {
16483             int k = 0;
16484             while (k < 2) { ++result; ++k; ++j; }
16485             while (k < 5) { ++result; ++k; }
16486             if (i > 3)
16487             {
16488                 ++j;
16489                 continue;
16490             }
16491             while (k < 4) { ++result; }
16492             ++j;
16493         }
16494         ++i;
16495     }
16496 
16497     color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16498 })";
16499 
16500     runTest(kFS);
16501 }
16502 
16503 // Test while loops with continue at the end of block
TEST_P(GLSLTestLoops,WhileUnconditionalContinue)16504 TEST_P(GLSLTestLoops, WhileUnconditionalContinue)
16505 {
16506     constexpr char kFS[] = R"(#version 300 es
16507 precision mediump float;
16508 out vec4 color;
16509 
16510 void main()
16511 {
16512     int result = 0;
16513     int i = 0;
16514     while (i < 10)
16515     {
16516         int j = 0;
16517         while (j < 8)
16518         {
16519             int k = 0;
16520             while (k < 2) { ++result; ++k; ++j; }
16521             while (k < 5) { ++result; ++k; }
16522             while (k < 4) { ++result; }
16523             ++j;
16524             continue;
16525         }
16526         ++i;
16527     }
16528 
16529     color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16530 })";
16531 
16532     runTest(kFS);
16533 }
16534 
16535 // Test while loops with break
TEST_P(GLSLTestLoops,WhileBreak)16536 TEST_P(GLSLTestLoops, WhileBreak)
16537 {
16538     constexpr char kFS[] = R"(#version 300 es
16539 precision mediump float;
16540 out vec4 color;
16541 
16542 void main()
16543 {
16544     int result = 0;
16545     int i = 0;
16546     while (i < 10)
16547     {
16548         int j = 0;
16549         while (true)
16550         {
16551             int k = 0;
16552             while (k < 2) { ++result; ++k; ++j; }
16553             while (k < 5) { ++result; ++k; }
16554             while (k < 4) { ++result; }
16555             ++j;
16556             if (j >= 8)
16557                 break;
16558         }
16559         ++i;
16560     }
16561 
16562     color = result == 150 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16563 })";
16564 
16565     runTest(kFS);
16566 }
16567 
16568 // Test while loops with continue at the end of block
TEST_P(GLSLTestLoops,WhileUnconditionalBreak)16569 TEST_P(GLSLTestLoops, WhileUnconditionalBreak)
16570 {
16571     constexpr char kFS[] = R"(#version 300 es
16572 precision mediump float;
16573 out vec4 color;
16574 
16575 void main()
16576 {
16577     int result = 0;
16578     int i = 0;
16579     while (i < 10)
16580     {
16581         int j = 0;
16582         while (j < 8)
16583         {
16584             int k = 0;
16585             while (k < 2) { ++result; ++k; ++j; }
16586             while (k < 5) { ++result; ++k; }
16587             while (k < 4) { ++result; }
16588             ++j;
16589             break;
16590         }
16591         ++i;
16592     }
16593 
16594     color = result == 50 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16595 })";
16596 
16597     runTest(kFS);
16598 }
16599 
16600 // Test basic do-while loops
TEST_P(GLSLTestLoops,BasicDoWhile)16601 TEST_P(GLSLTestLoops, BasicDoWhile)
16602 {
16603     constexpr char kFS[] = R"(#version 300 es
16604 precision mediump float;
16605 out vec4 color;
16606 
16607 void main()
16608 {
16609     int result = 0;
16610     int i = 0;
16611     do
16612     {
16613         int j = 0;
16614         do
16615         {
16616             int k = 0;
16617             do { ++result; ++k; ++j; } while (k < 2);
16618             do { ++result; ++k;      } while (k < 5);
16619             do { ++result;           } while (k < 3);
16620             ++j;
16621         } while (j < 8);
16622         ++i;
16623     } while (i < 10);
16624 
16625     color = result == 180 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16626 })";
16627 
16628     runTest(kFS);
16629 }
16630 
16631 // Test do-while loops with continue
TEST_P(GLSLTestLoops,DoWhileContinue)16632 TEST_P(GLSLTestLoops, DoWhileContinue)
16633 {
16634     constexpr char kFS[] = R"(#version 300 es
16635 precision mediump float;
16636 out vec4 color;
16637 
16638 void main()
16639 {
16640     int result = 0;
16641     int i = 0;
16642     do
16643     {
16644         int j = 0;
16645         do
16646         {
16647             int k = 0;
16648             do { ++result; ++k; ++j; } while (k < 2);
16649             if (i > 3)
16650             {
16651                 ++j;
16652                 continue;
16653             }
16654             do { ++result; ++k;      } while (k < 5);
16655             do { ++result;           } while (k < 3);
16656             ++j;
16657         } while (j < 8);
16658         ++i;
16659     } while (i < 10);
16660 
16661     color = result == 108 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16662 })";
16663 
16664     runTest(kFS);
16665 }
16666 
16667 // Test do-while loops with continue at the end of block
TEST_P(GLSLTestLoops,DoWhileUnconditionalContinue)16668 TEST_P(GLSLTestLoops, DoWhileUnconditionalContinue)
16669 {
16670     constexpr char kFS[] = R"(#version 300 es
16671 precision mediump float;
16672 out vec4 color;
16673 
16674 void main()
16675 {
16676     int result = 0;
16677     int i = 0;
16678     do
16679     {
16680         int j = 0;
16681         do
16682         {
16683             int k = 0;
16684             do { ++result; ++k; ++j; continue; } while (k < 2);
16685             do { ++result; ++k;      continue; } while (k < 5);
16686             do { ++result;           continue; } while (k < 3);
16687             ++j;
16688         } while (j < 8);
16689         ++i;
16690     } while (i < 10);
16691 
16692     color = result == 180 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16693 })";
16694 
16695     runTest(kFS);
16696 }
16697 
16698 // Test do-while loops with break
TEST_P(GLSLTestLoops,DoWhileBreak)16699 TEST_P(GLSLTestLoops, DoWhileBreak)
16700 {
16701     constexpr char kFS[] = R"(#version 300 es
16702 precision mediump float;
16703 out vec4 color;
16704 
16705 void main()
16706 {
16707     int result = 0;
16708     int i = 0;
16709     do
16710     {
16711         int j = 0;
16712         do
16713         {
16714             int k = 0;
16715             do { ++result; ++k; ++j; } while (k < 2);
16716             do { ++result; ++k;      } while (k < 5);
16717             do { ++result;           } while (k < 3);
16718             ++j;
16719             if (j >= 8)
16720                 break;
16721         } while (true);
16722         ++i;
16723     } while (i < 10);
16724 
16725     color = result == 180 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16726 })";
16727 
16728     runTest(kFS);
16729 }
16730 
16731 // Test do-while loops with break at the end of block
TEST_P(GLSLTestLoops,DoWhileUnconditionalBreak)16732 TEST_P(GLSLTestLoops, DoWhileUnconditionalBreak)
16733 {
16734     constexpr char kFS[] = R"(#version 300 es
16735 precision mediump float;
16736 out vec4 color;
16737 
16738 void main()
16739 {
16740     int result = 0;
16741     int i = 0;
16742     do
16743     {
16744         int j = 0;
16745         do
16746         {
16747             int k = 0;
16748             do { ++result; ++k; ++j; break; } while (k < 2);
16749             do { ++result; ++k;      break; } while (k < 5);
16750             do { ++result;           break; } while (k < 3);
16751             ++j;
16752         } while (j < 8);
16753         ++i;
16754     } while (i < 10);
16755 
16756     color = result == 120 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16757 })";
16758 
16759     runTest(kFS);
16760 }
16761 
16762 // Test for loop with continue inside switch.
TEST_P(GLSLTestLoops,ForContinueInSwitch)16763 TEST_P(GLSLTestLoops, ForContinueInSwitch)
16764 {
16765     constexpr char kFS[] = R"(#version 300 es
16766 precision mediump float;
16767 out vec4 color;
16768 
16769 void main()
16770 {
16771     int result = 0;
16772     for (int i = 0; i < 10; ++i)
16773         for (int j = 0; j < 8; ++j)
16774         {
16775             switch (j)
16776             {
16777                 case 2:
16778                 case 3:
16779                 case 4:
16780                     ++result;
16781                     // fallthrough
16782                 case 5:
16783                 case 6:
16784                     ++result;
16785                     break;
16786                 default:
16787                     continue;
16788             }
16789         }
16790 
16791     color = result == 80 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16792 })";
16793 
16794     runTest(kFS);
16795 }
16796 
16797 // Test while loop with continue inside switch
TEST_P(GLSLTestLoops,WhileContinueInSwitch)16798 TEST_P(GLSLTestLoops, WhileContinueInSwitch)
16799 {
16800     constexpr char kFS[] = R"(#version 300 es
16801 precision mediump float;
16802 out vec4 color;
16803 
16804 void main()
16805 {
16806     int result = 0;
16807     int i = 0;
16808     while (i < 10)
16809     {
16810         int j = 0;
16811         while (j < 8)
16812         {
16813             switch (j)
16814             {
16815                 case 2:
16816                 default:
16817                 case 3:
16818                 case 4:
16819                     ++j;
16820                     ++result;
16821                     continue;
16822                 case 0:
16823                 case 1:
16824                 case 7:
16825                     break;
16826             }
16827             ++j;
16828         }
16829         ++i;
16830     }
16831 
16832     color = result == 50 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16833 })";
16834 
16835     runTest(kFS);
16836 }
16837 
16838 // Test do-while loops with continue in switch
TEST_P(GLSLTestLoops,DoWhileContinueInSwitch)16839 TEST_P(GLSLTestLoops, DoWhileContinueInSwitch)
16840 {
16841     constexpr char kFS[] = R"(#version 300 es
16842 precision mediump float;
16843 out vec4 color;
16844 
16845 void main()
16846 {
16847     int result = 0;
16848     int i = 0;
16849     do
16850     {
16851         int j = 0;
16852         do
16853         {
16854             switch (j)
16855             {
16856                 case 0:
16857                     ++j;
16858                     continue;
16859                 default:
16860                 case 2:
16861                 case 3:
16862                 case 4:
16863                     ++j;
16864                     ++result;
16865                     if (j >= 2 && j <= 6)
16866                         break;
16867                     else
16868                         continue;
16869             }
16870             ++result;
16871         } while (j < 8);
16872         ++i;
16873     } while (i < 10);
16874 
16875     color = result == 120 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16876 })";
16877 
16878     runTest(kFS);
16879 }
16880 
16881 // Test prune-able loop with side effect in statements.
TEST_P(GLSLTestLoops,SideEffectsInPrunableFor)16882 TEST_P(GLSLTestLoops, SideEffectsInPrunableFor)
16883 {
16884     constexpr char kFS[] = R"(#version 300 es
16885 precision mediump float;
16886 out vec4 color;
16887 
16888 void main()
16889 {
16890     int a = 4;
16891     float b = 0.;
16892     for (int c = a++; (b += float(c) / 8.) < 0.; b += 0.3)
16893     {
16894         if (2 == 0);
16895     }
16896     int c = a - 4;
16897 
16898     // Expect c to be 1 and b to be 0.5
16899     color = c == 1 && abs(b - 0.5) < 0.001 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
16900 })";
16901 
16902     runTest(kFS);
16903 }
16904 
16905 // Test that precision is retained for constants (which are constant folded).  Adapted from a WebGL
16906 // test.
TEST_P(GLSLTest,ConstantFoldedConstantsRetainPrecision)16907 TEST_P(GLSLTest, ConstantFoldedConstantsRetainPrecision)
16908 {
16909     constexpr char kFS[] = R"(
16910 // It is assumed that uTest is set to 0. It's here to make the expression not constant.
16911 uniform mediump float uTest;
16912 void main() {
16913     // exact representation of 4096.5 requires 13 bits of relative precision.
16914     const highp float c = 4096.5;
16915     mediump float a = 0.0;
16916     // Below, addition should be evaluated at highp, since one of the operands has the highp qualifier.
16917     // Thus fract should also be evaluated at highp.
16918     // See OpenGL ES Shading Language spec section 4.5.2.
16919     // This should make the result 0.5, since highp provides at least 16 bits of relative precision.
16920     // (exceptions for operation precision are allowed for a small number of computationally
16921     // intensive built-in functions, but it is reasonable to think that fract is not one of those).
16922     // However, if fract() is incorrectly evaluated at minimum precision fulfilling mediump criteria,
16923     // or at IEEE half float precision, the result is 0.0.
16924     a = fract(c + uTest);
16925     // Multiply by 2.0 to make the color green.
16926     gl_FragColor = vec4(0.0, 2.0 * a, 0.0, 1.0);
16927 })";
16928 
16929     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
16930 
16931     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
16932     EXPECT_GL_NO_ERROR();
16933 
16934     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
16935 }
16936 
16937 // Test that vector and matrix scalarization does not affect rendering.
TEST_P(GLSLTest,VectorAndMatrixScalarizationDoesNotAffectRendering)16938 TEST_P(GLSLTest, VectorAndMatrixScalarizationDoesNotAffectRendering)
16939 {
16940     constexpr char kFS[] = R"(
16941 precision mediump float;
16942 
16943 varying vec2 v_texCoord;
16944 
16945 float a = 0.;
16946 #define A 0.
16947 
16948 #define r(a)    mat2( cos( a + vec4(0,-1.5708,1.5708,0) ) )
16949 vec2 c;
16950 #define f(U,a)  ( c = (U) * r(a) , sin(10.*c.x) )
16951 
16952 void main() {
16953     vec2 U = v_texCoord;
16954 
16955     gl_FragColor = U.y > .5
16956         ? vec4( f(U,a) , f(U*4.,a) , 0,1.0)   // top
16957         : vec4( f(U,A) , f(U*4.,A) , 0,1.0);  // bottom
16958 }
16959 
16960 )";
16961 
16962     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), kFS);
16963     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
16964 
16965     // Make sure we rendered something.
16966     EXPECT_PIXEL_NE(0, 0, 0, 0, 0, 0);
16967 
16968     // Comapare one line in top half to one line in bottom half.
16969     int compareWidth  = getWindowWidth();
16970     int compareHeight = getWindowHeight() / 4;
16971 
16972     ASSERT_GE(compareWidth, 2);
16973     ASSERT_GE(compareHeight, 2);
16974 
16975     GLubyte pixelValue[4];
16976     constexpr int tolerance = 12;
16977 
16978     for (int x = 0; x < compareWidth; ++x)
16979     {
16980         glReadPixels(x, compareHeight, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixelValue);
16981         EXPECT_PIXEL_NEAR(x, getWindowHeight() - compareHeight, pixelValue[0], pixelValue[1],
16982                           pixelValue[2], pixelValue[3], tolerance);
16983     }
16984     EXPECT_GL_NO_ERROR();
16985 }
16986 
16987 // Tests initializing a shader IO block using the shader translator option.
TEST_P(GLSLTest_ES31_InitShaderVariables,InitIOBlock)16988 TEST_P(GLSLTest_ES31_InitShaderVariables, InitIOBlock)
16989 {
16990     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
16991 
16992     const char kVS[] = R"(#version 310 es
16993 #extension GL_EXT_shader_io_blocks : require
16994 in vec4 position;
16995 out BlockType {
16996     vec4 blockMember;
16997 } BlockTypeOut;
16998 
16999 void main()
17000 {
17001     gl_Position = position;
17002 })";
17003 
17004     const char kFS[] = R"(#version 310 es
17005 #extension GL_EXT_shader_io_blocks : require
17006 precision mediump float;
17007 out vec4 colorOut;
17008 in BlockType {
17009     vec4 blockMember;
17010 } BlockTypeOut;
17011 
17012 void main()
17013 {
17014     if (BlockTypeOut.blockMember == vec4(0)) {
17015         colorOut = vec4(0, 1, 0, 1);
17016     } else {
17017         colorOut = vec4(1, 0, 0, 1);
17018     }
17019 })";
17020 
17021     ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
17022     drawQuad(testProgram, "position", 0.5f, 1.0f, true);
17023     ASSERT_GL_NO_ERROR();
17024     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
17025 }
17026 
17027 // Tests initializing a nameless shader IO block using the shader translator option.
TEST_P(GLSLTest_ES31_InitShaderVariables,InitIOBlockNameless)17028 TEST_P(GLSLTest_ES31_InitShaderVariables, InitIOBlockNameless)
17029 {
17030     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
17031 
17032     const char kVS[] = R"(#version 310 es
17033 #extension GL_EXT_shader_io_blocks : require
17034 in vec4 position;
17035 out BlockType {
17036     vec4 blockMember;
17037 };
17038 
17039 void main()
17040 {
17041     gl_Position = position;
17042 })";
17043 
17044     const char kFS[] = R"(#version 310 es
17045 #extension GL_EXT_shader_io_blocks : require
17046 precision mediump float;
17047 out vec4 colorOut;
17048 in BlockType {
17049     vec4 blockMember;
17050 };
17051 
17052 void main()
17053 {
17054     if (blockMember == vec4(0)) {
17055         colorOut = vec4(0, 1, 0, 1);
17056     } else {
17057         colorOut = vec4(1, 0, 0, 1);
17058     }
17059 })";
17060 
17061     ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
17062     drawQuad(testProgram, "position", 0.5f, 1.0f, true);
17063     ASSERT_GL_NO_ERROR();
17064     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
17065 }
17066 
17067 // Tests initializing a shader IO block with an array using the shader translator option.
TEST_P(GLSLTest_ES31_InitShaderVariables,InitIOBlockWithArray)17068 TEST_P(GLSLTest_ES31_InitShaderVariables, InitIOBlockWithArray)
17069 {
17070     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
17071 
17072     const char kVS[] = R"(#version 310 es
17073 #extension GL_EXT_shader_io_blocks : require
17074 in vec4 position;
17075 out BlockType {
17076     vec4 blockMember[2];
17077 } BlockTypeOut;
17078 
17079 void main()
17080 {
17081     gl_Position = position;
17082 })";
17083 
17084     const char kFS[] = R"(#version 310 es
17085 #extension GL_EXT_shader_io_blocks : require
17086 precision mediump float;
17087 out vec4 colorOut;
17088 in BlockType {
17089     vec4 blockMember[2];
17090 } BlockTypeOut;
17091 
17092 void main()
17093 {
17094     if (BlockTypeOut.blockMember[0] == vec4(0) &&
17095         BlockTypeOut.blockMember[1] == vec4(0)) {
17096         colorOut = vec4(0, 1, 0, 1);
17097     } else {
17098         colorOut = vec4(1, 0, 0, 1);
17099     }
17100 })";
17101 
17102     ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
17103     drawQuad(testProgram, "position", 0.5f, 1.0f, true);
17104     ASSERT_GL_NO_ERROR();
17105     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
17106 }
17107 
17108 // Tests initializing a shader IO block array using the shader translator option.
TEST_P(GLSLTest_ES31_InitShaderVariables,InitIOBlockArray)17109 TEST_P(GLSLTest_ES31_InitShaderVariables, InitIOBlockArray)
17110 {
17111     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
17112 
17113     const char kVS[] = R"(#version 310 es
17114 #extension GL_EXT_shader_io_blocks : require
17115 in vec4 position;
17116 out BlockType {
17117     vec4 blockMember;
17118 } BlockTypeOut[2];
17119 
17120 void main()
17121 {
17122     gl_Position = position;
17123 })";
17124 
17125     const char kFS[] = R"(#version 310 es
17126 #extension GL_EXT_shader_io_blocks : require
17127 precision mediump float;
17128 out vec4 colorOut;
17129 in BlockType {
17130     vec4 blockMember;
17131 } BlockTypeOut[2];
17132 
17133 void main()
17134 {
17135     if (BlockTypeOut[0].blockMember == vec4(0) &&
17136         BlockTypeOut[1].blockMember == vec4(0)) {
17137         colorOut = vec4(0, 1, 0, 1);
17138     } else {
17139         colorOut = vec4(1, 0, 0, 1);
17140     }
17141 })";
17142 
17143     ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
17144     drawQuad(testProgram, "position", 0.5f, 1.0f, true);
17145     ASSERT_GL_NO_ERROR();
17146     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
17147 }
17148 
17149 // Tests initializing a shader IO block with a struct using the shader translator option.
TEST_P(GLSLTest_ES31_InitShaderVariables,InitIOBlockWithStruct)17150 TEST_P(GLSLTest_ES31_InitShaderVariables, InitIOBlockWithStruct)
17151 {
17152     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
17153 
17154     const char kVS[] = R"(#version 310 es
17155 #extension GL_EXT_shader_io_blocks : require
17156 in vec4 position;
17157 struct s {
17158     float f;
17159     vec2 v;
17160 };
17161 out BlockType {
17162     s blockMember;
17163 } BlockTypeOut;
17164 
17165 void main()
17166 {
17167     gl_Position = position;
17168 })";
17169 
17170     const char kFS[] = R"(#version 310 es
17171 #extension GL_EXT_shader_io_blocks : require
17172 precision mediump float;
17173 out vec4 colorOut;
17174 struct s {
17175     float f;
17176     vec2 v;
17177 };
17178 in BlockType {
17179     s blockMember;
17180 } BlockTypeOut;
17181 
17182 void main()
17183 {
17184     if (BlockTypeOut.blockMember.f == 0.0 &&
17185         BlockTypeOut.blockMember.v == vec2(0)) {
17186         colorOut = vec4(0, 1, 0, 1);
17187     } else {
17188         colorOut = vec4(1, 0, 0, 1);
17189     }
17190 })";
17191 
17192     ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
17193     drawQuad(testProgram, "position", 0.5f, 1.0f, true);
17194     ASSERT_GL_NO_ERROR();
17195     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
17196 }
17197 
17198 // Tests initializing an IO block with a complicated set of types, using the shader translator.
TEST_P(GLSLTest_ES31_InitShaderVariables,InitIOBlockWithComplexTypes)17199 TEST_P(GLSLTest_ES31_InitShaderVariables, InitIOBlockWithComplexTypes)
17200 {
17201     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
17202 
17203     const char kVS[] = R"(#version 310 es
17204 #extension GL_EXT_shader_io_blocks : require
17205 in vec4 position;
17206 struct s {
17207     float f;
17208     vec2 v;
17209 };
17210 out BlockType {
17211     vec4 v;
17212     s s1;
17213     s s2[2];
17214 } BlockTypeOut;
17215 
17216 void main()
17217 {
17218     gl_Position = position;
17219 })";
17220 
17221     const char kFS[] = R"(#version 310 es
17222 #extension GL_EXT_shader_io_blocks : require
17223 precision mediump float;
17224 out vec4 colorOut;
17225 struct s {
17226     float f;
17227     vec2 v;
17228 };
17229 in BlockType {
17230     vec4 v;
17231     s s1;
17232     s s2[2];
17233 } BlockTypeOut;
17234 
17235 void main()
17236 {
17237     s sz = s(0.0, vec2(0));
17238     if (BlockTypeOut.v == vec4(0) &&
17239         BlockTypeOut.s1 == sz &&
17240         BlockTypeOut.s2[0] == sz &&
17241         BlockTypeOut.s2[1] == sz) {
17242         colorOut = vec4(0, 1, 0, 1);
17243     } else {
17244         colorOut = vec4(1, 0, 0, 1);
17245     }
17246 })";
17247 
17248     ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
17249     drawQuad(testProgram, "position", 0.5f, 1.0f, true);
17250     ASSERT_GL_NO_ERROR();
17251     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
17252 }
17253 
17254 // Tests an unsuccessful re-link using glBindAttribLocation.
TEST_P(GLSLTest_ES3,UnsuccessfulRelinkWithBindAttribLocation)17255 TEST_P(GLSLTest_ES3, UnsuccessfulRelinkWithBindAttribLocation)
17256 {
17257     // Make a simple program.
17258     ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
17259 
17260     // Install the executable.
17261     glUseProgram(testProgram);
17262 
17263     // Re-link with a bad XFB varying and a bound attrib location.
17264     const char *tfVaryings = "gl_FragColor";
17265     glTransformFeedbackVaryings(testProgram, 1, &tfVaryings, GL_SEPARATE_ATTRIBS);
17266     glBindAttribLocation(testProgram, 8, essl1_shaders::PositionAttrib());
17267     glLinkProgram(testProgram);
17268     GLint linkStatus = 999;
17269     glGetProgramiv(testProgram, GL_LINK_STATUS, &linkStatus);
17270     ASSERT_GL_NO_ERROR();
17271     ASSERT_EQ(linkStatus, GL_FALSE);
17272 
17273     // Under normal GL this is not an error.
17274     glDrawArrays(GL_TRIANGLES, 79, 16);
17275     EXPECT_GL_NO_ERROR();
17276 }
17277 
17278 // Regression test for an unsuccessful link with a varying followed by another link
TEST_P(GLSLTest_ES3,UnsuccessfulLinkFollowedByAnotherLink)17279 TEST_P(GLSLTest_ES3, UnsuccessfulLinkFollowedByAnotherLink)
17280 {
17281     // Make a simple program.
17282     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
17283 
17284     // Install the executable.
17285     glUseProgram(program);
17286 
17287     // Re-link with a bad XFB varying and a bound attrib location.
17288     const char *tfVaryings = "gl_FragColor";
17289     glTransformFeedbackVaryings(program, 1, &tfVaryings, GL_SEPARATE_ATTRIBS);
17290     glBindAttribLocation(program, 8, essl1_shaders::PositionAttrib());
17291     glLinkProgram(program);
17292     GLint linkStatus = 999;
17293     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
17294     ASSERT_GL_NO_ERROR();
17295     // Link expected to fail on the first program
17296     ASSERT_EQ(linkStatus, GL_FALSE);
17297 
17298     // Another program with the same shaders but without the varying is expected to link
17299     ANGLE_GL_PROGRAM(anotherProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
17300     ASSERT_NE(program, anotherProgram);
17301     glUseProgram(anotherProgram);
17302     glLinkProgram(anotherProgram);
17303     ASSERT_GL_NO_ERROR();
17304     ASSERT_NE(CheckLinkStatusAndReturnProgram(anotherProgram, true), 0u);
17305 }
17306 
17307 // Tests an unsuccessful re-link using glBindAttribLocation under WebGL.
TEST_P(WebGL2GLSLTest,UnsuccessfulRelinkWithBindAttribLocation)17308 TEST_P(WebGL2GLSLTest, UnsuccessfulRelinkWithBindAttribLocation)
17309 {
17310     // Make a simple program.
17311     ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
17312 
17313     // Install the executable.
17314     glUseProgram(testProgram);
17315 
17316     // Re-link with a bad XFB varying and a bound attrib location.
17317     const char *tfVaryings = "gl_FragColor";
17318     glTransformFeedbackVaryings(testProgram, 1, &tfVaryings, GL_SEPARATE_ATTRIBS);
17319     glBindAttribLocation(testProgram, 8, essl1_shaders::PositionAttrib());
17320     glLinkProgram(testProgram);
17321     GLint linkStatus = 999;
17322     glGetProgramiv(testProgram, GL_LINK_STATUS, &linkStatus);
17323     ASSERT_GL_NO_ERROR();
17324     ASSERT_EQ(linkStatus, GL_FALSE);
17325 
17326     // Under WebGL this is an error.
17327     glDrawArrays(GL_TRIANGLES, 79, 16);
17328     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
17329 }
17330 
17331 // Covers a HLSL compiler bug.
TEST_P(GLSLTest_ES3,ComplexCrossExpression)17332 TEST_P(GLSLTest_ES3, ComplexCrossExpression)
17333 {
17334     constexpr char kFS[] = R"(#version 300 es
17335 precision mediump float;
17336 vec3 a = vec3(0.0);
17337 out vec4 color;
17338 void main()
17339 {
17340     cross(max(vec3(0.0), reflect(dot(a, vec3(0.0)), 0.0)), vec3(0.0));
17341 })";
17342 
17343     ANGLE_GL_PROGRAM(testProgram, essl3_shaders::vs::Simple(), kFS);
17344     drawQuad(testProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
17345     ASSERT_GL_NO_ERROR();
17346 }
17347 
17348 // Regression test for a crash in SPIR-V output when faced with an array of struct constant.
TEST_P(GLSLTest_ES3,ArrayOfStructConstantBug)17349 TEST_P(GLSLTest_ES3, ArrayOfStructConstantBug)
17350 {
17351     constexpr char kFS[] = R"(#version 300 es
17352 struct S {
17353     int foo;
17354 };
17355 void main() {
17356     S a[3];
17357     a = S[3](S(0), S(1), S(2));
17358 })";
17359 
17360     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
17361 
17362     const char *sourceArray[1] = {kFS};
17363     GLint lengths[1]           = {static_cast<GLint>(sizeof(kFS) - 1)};
17364     glShaderSource(shader, 1, sourceArray, lengths);
17365     glCompileShader(shader);
17366 
17367     GLint compileResult;
17368     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
17369     EXPECT_NE(compileResult, 0);
17370 }
17371 
17372 // Regression test for a bug in SPIR-V output where float+matrix was mishandled.
TEST_P(GLSLTest_ES3,FloatPlusMatrix)17373 TEST_P(GLSLTest_ES3, FloatPlusMatrix)
17374 {
17375     constexpr char kFS[] = R"(#version 300 es
17376 
17377 precision mediump float;
17378 
17379 layout(location=0) out vec4 color;
17380 
17381 uniform float f;
17382 
17383 void main()
17384 {
17385     mat3x2 m = f + mat3x2(0);
17386     color = vec4(m[0][0]);
17387 })";
17388 
17389     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
17390 
17391     const char *sourceArray[1] = {kFS};
17392     GLint lengths[1]           = {static_cast<GLint>(sizeof(kFS) - 1)};
17393     glShaderSource(shader, 1, sourceArray, lengths);
17394     glCompileShader(shader);
17395 
17396     GLint compileResult;
17397     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
17398     EXPECT_NE(compileResult, 0);
17399 }
17400 
17401 // Regression test for a bug in SPIR-V output where a transformation creates float(constant) without
17402 // folding it into a TIntermConstantUnion.  This transformation is clamping non-constant indices in
17403 // WebGL.  The |false ? i : 5| as index caused the transformation to consider this a non-constant
17404 // index.
TEST_P(WebGL2GLSLTest,IndexClampConstantIndexBug)17405 TEST_P(WebGL2GLSLTest, IndexClampConstantIndexBug)
17406 {
17407     constexpr char kFS[] = R"(#version 300 es
17408 precision highp float;
17409 
17410 layout(location=0) out float f;
17411 
17412 uniform int i;
17413 
17414 void main()
17415 {
17416     float data[10];
17417     f = data[false ? i : 5];
17418 })";
17419 
17420     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
17421 
17422     const char *sourceArray[1] = {kFS};
17423     GLint lengths[1]           = {static_cast<GLint>(sizeof(kFS) - 1)};
17424     glShaderSource(shader, 1, sourceArray, lengths);
17425     glCompileShader(shader);
17426 
17427     GLint compileResult;
17428     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
17429     EXPECT_NE(compileResult, 0);
17430 }
17431 
17432 // Test robustness of out-of-bounds lod in texelFetch
TEST_P(WebGL2GLSLTest,TexelFetchLodOutOfBounds)17433 TEST_P(WebGL2GLSLTest, TexelFetchLodOutOfBounds)
17434 {
17435     constexpr char kVS[] = R"(#version 300 es
17436 in vec4 vertexPosition;
17437 void main() {
17438     gl_Position = vertexPosition;
17439 })";
17440 
17441     constexpr char kFS[] = R"(#version 300 es
17442 precision highp float;
17443 uniform highp sampler2DArray textureArray;
17444 uniform int textureLod;
17445 out vec4 fragColor;
17446 void main() {
17447     fragColor = texelFetch(textureArray, ivec3(gl_FragCoord.xy, 0), textureLod);
17448 })";
17449 
17450     ANGLE_GL_PROGRAM(program, kVS, kFS);
17451     glUseProgram(program);
17452     const GLint lodLoc = glGetUniformLocation(program, "textureLod");
17453     EXPECT_NE(lodLoc, -1);
17454     const GLint textureLoc = glGetUniformLocation(program, "textureArray");
17455     EXPECT_NE(textureLoc, -1);
17456 
17457     const GLint attribLocation = glGetAttribLocation(program, "vertexPosition");
17458     GLBuffer buffer;
17459     glBindBuffer(GL_ARRAY_BUFFER, buffer);
17460     constexpr float vertices[12] = {
17461         -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1,
17462     };
17463     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
17464     glEnableVertexAttribArray(attribLocation);
17465     glVertexAttribPointer(attribLocation, 2, GL_FLOAT, false, 0, 0);
17466 
17467     GLTexture texture;
17468     glBindTexture(GL_TEXTURE_2D_ARRAY, texture);
17469     glTexStorage3D(GL_TEXTURE_2D_ARRAY, 5, GL_RGBA8, 16, 16, 3);
17470     glUniform1i(textureLoc, 0);
17471 
17472     // Test LOD too large
17473     glUniform1i(lodLoc, 0x7FFF);
17474     glDrawArrays(GL_TRIANGLES, 0, 6);
17475 
17476     // Test LOD negative
17477     glUniform1i(lodLoc, -1);
17478     glDrawArrays(GL_TRIANGLES, 0, 6);
17479 }
17480 
17481 // Test that framebuffer fetch transforms gl_LastFragData in the presence of gl_FragCoord without
17482 // failing validation (adapted from a Chromium test, see anglebug.com/42265427)
TEST_P(GLSLTest,FramebufferFetchWithLastFragData)17483 TEST_P(GLSLTest, FramebufferFetchWithLastFragData)
17484 {
17485     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch"));
17486 
17487     constexpr char kFS[] = R"(#version 100
17488 
17489 #extension GL_EXT_shader_framebuffer_fetch : require
17490 varying mediump vec4 color;
17491 void main() {
17492     gl_FragColor = length(gl_FragCoord.xy) * gl_LastFragData[0];
17493 })";
17494 
17495     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
17496 
17497     const char *sourceArray[1] = {kFS};
17498     GLint lengths[1]           = {static_cast<GLint>(sizeof(kFS) - 1)};
17499     glShaderSource(shader, 1, sourceArray, lengths);
17500     glCompileShader(shader);
17501 
17502     GLint compileResult;
17503     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
17504     EXPECT_NE(compileResult, 0);
17505 }
17506 
17507 // Test that loop body ending in a branch doesn't fail compilation
TEST_P(GLSLTest,LoopBodyEndingInBranch1)17508 TEST_P(GLSLTest, LoopBodyEndingInBranch1)
17509 {
17510     constexpr char kFS[] = R"(void main(){for(int a,i;;gl_FragCoord)continue;})";
17511 
17512     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
17513 
17514     const char *sourceArray[1] = {kFS};
17515     GLint lengths[1]           = {static_cast<GLint>(sizeof(kFS) - 1)};
17516     glShaderSource(shader, 1, sourceArray, lengths);
17517     glCompileShader(shader);
17518 
17519     GLint compileResult;
17520     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
17521     EXPECT_NE(compileResult, 0);
17522 }
17523 
17524 // Test that loop body ending in a branch doesn't fail compilation
TEST_P(GLSLTest,LoopBodyEndingInBranch2)17525 TEST_P(GLSLTest, LoopBodyEndingInBranch2)
17526 {
17527     constexpr char kFS[] =
17528         R"(void main(){for(int a,i;bool(gl_FragCoord.x);gl_FragCoord){continue;}})";
17529 
17530     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
17531 
17532     const char *sourceArray[1] = {kFS};
17533     GLint lengths[1]           = {static_cast<GLint>(sizeof(kFS) - 1)};
17534     glShaderSource(shader, 1, sourceArray, lengths);
17535     glCompileShader(shader);
17536 
17537     GLint compileResult;
17538     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
17539     EXPECT_NE(compileResult, 0);
17540 }
17541 
17542 // Test that loop body ending in a branch doesn't fail compilation
TEST_P(GLSLTest,LoopBodyEndingInBranch3)17543 TEST_P(GLSLTest, LoopBodyEndingInBranch3)
17544 {
17545     constexpr char kFS[] = R"(void main(){for(int a,i;;gl_FragCoord){{continue;}}})";
17546 
17547     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
17548 
17549     const char *sourceArray[1] = {kFS};
17550     GLint lengths[1]           = {static_cast<GLint>(sizeof(kFS) - 1)};
17551     glShaderSource(shader, 1, sourceArray, lengths);
17552     glCompileShader(shader);
17553 
17554     GLint compileResult;
17555     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
17556     EXPECT_NE(compileResult, 0);
17557 }
17558 
17559 // Test that loop body ending in a branch doesn't fail compilation
TEST_P(GLSLTest,LoopBodyEndingInBranch4)17560 TEST_P(GLSLTest, LoopBodyEndingInBranch4)
17561 {
17562     constexpr char kFS[] = R"(void main(){for(int a,i;;gl_FragCoord){{continue;}{}{}{{}{}}}})";
17563 
17564     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
17565 
17566     const char *sourceArray[1] = {kFS};
17567     GLint lengths[1]           = {static_cast<GLint>(sizeof(kFS) - 1)};
17568     glShaderSource(shader, 1, sourceArray, lengths);
17569     glCompileShader(shader);
17570 
17571     GLint compileResult;
17572     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
17573     EXPECT_NE(compileResult, 0);
17574 }
17575 
17576 // Test that loop body ending in a branch doesn't fail compilation
TEST_P(GLSLTest,LoopBodyEndingInBranch5)17577 TEST_P(GLSLTest, LoopBodyEndingInBranch5)
17578 {
17579     constexpr char kFS[] = R"(void main(){while(bool(gl_FragCoord.x)){{continue;{}}{}}})";
17580 
17581     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
17582 
17583     const char *sourceArray[1] = {kFS};
17584     GLint lengths[1]           = {static_cast<GLint>(sizeof(kFS) - 1)};
17585     glShaderSource(shader, 1, sourceArray, lengths);
17586     glCompileShader(shader);
17587 
17588     GLint compileResult;
17589     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
17590     EXPECT_NE(compileResult, 0);
17591 }
17592 
17593 // Test that loop body ending in a branch doesn't fail compilation
TEST_P(GLSLTest,LoopBodyEndingInBranch6)17594 TEST_P(GLSLTest, LoopBodyEndingInBranch6)
17595 {
17596     constexpr char kFS[] = R"(void main(){do{{continue;{}}{}}while(bool(gl_FragCoord.x));})";
17597 
17598     GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
17599 
17600     const char *sourceArray[1] = {kFS};
17601     GLint lengths[1]           = {static_cast<GLint>(sizeof(kFS) - 1)};
17602     glShaderSource(shader, 1, sourceArray, lengths);
17603     glCompileShader(shader);
17604 
17605     GLint compileResult;
17606     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
17607     EXPECT_NE(compileResult, 0);
17608 }
17609 
17610 // Test that aliasing function out parameters work.  The GLSL spec says:
17611 //
17612 // > Because the function works with local copies of parameters, there are no issues regarding
17613 // > aliasing of variables within a function.
17614 //
17615 // In the test below, while the value of x is unknown after the function call, the result of the
17616 // function must deterministically be true.
TEST_P(GLSLTest,AliasingFunctionOutParams)17617 TEST_P(GLSLTest, AliasingFunctionOutParams)
17618 {
17619     constexpr char kFS[] = R"(precision highp float;
17620 
17621 const vec4 colorGreen = vec4(0.,1.,0.,1.);
17622 const vec4 colorRed   = vec4(1.,0.,0.,1.);
17623 
17624 bool outParametersAreDistinct(out float x, out float y) {
17625     x = 1.0;
17626     y = 2.0;
17627     return x == 1.0 && y == 2.0;
17628 }
17629 void main() {
17630     float x = 0.0;
17631     gl_FragColor = outParametersAreDistinct(x, x) ? colorGreen : colorRed;
17632 }
17633 )";
17634 
17635     ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), kFS);
17636     drawQuad(testProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
17637     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
17638     ASSERT_GL_NO_ERROR();
17639 }
17640 
17641 // Test that aliasing function out parameters work even when multiple params are aliased.
TEST_P(GLSLTest,AliasingFunctionOutParamsMultiple)17642 TEST_P(GLSLTest, AliasingFunctionOutParamsMultiple)
17643 {
17644     constexpr char kFS[] = R"(precision highp float;
17645 
17646 const vec4 colorGreen = vec4(0.,1.,0.,1.);
17647 const vec4 colorRed   = vec4(1.,0.,0.,1.);
17648 
17649 bool outParametersAreDistinct(out float x, out float y, out float z, out float a) {
17650     x = 1.0;
17651     y = 2.0;
17652     z = 3.0;
17653     a = 4.0;
17654     return x == 1.0 && y == 2.0 && z == 3.0 && a == 4.0;
17655 }
17656 void main() {
17657     float x = 0.0;
17658     float y = 0.0;
17659     gl_FragColor = outParametersAreDistinct(x, x, y, y) ? colorGreen : colorRed;
17660 }
17661 )";
17662 
17663     ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), kFS);
17664     drawQuad(testProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
17665     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
17666     ASSERT_GL_NO_ERROR();
17667 }
17668 
17669 // Test that aliasing function inout parameters work.
TEST_P(GLSLTest,AliasingFunctionInOutParams)17670 TEST_P(GLSLTest, AliasingFunctionInOutParams)
17671 {
17672     constexpr char kFS[] = R"(precision highp float;
17673 
17674 const vec4 colorGreen = vec4(0.,1.,0.,1.);
17675 const vec4 colorRed   = vec4(1.,0.,0.,1.);
17676 
17677 bool inoutParametersAreDistinct(inout float x, inout float y) {
17678     x = 1.0;
17679     y = 2.0;
17680     return x == 1.0 && y == 2.0;
17681 }
17682 void main() {
17683     float x = 0.0;
17684     gl_FragColor = inoutParametersAreDistinct(x, x) ? colorGreen : colorRed;
17685 }
17686 )";
17687 
17688     ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), kFS);
17689     drawQuad(testProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
17690     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
17691     ASSERT_GL_NO_ERROR();
17692 }
17693 
17694 // Test coverage of some matrix/scalar ops which Metal translation was missing.
TEST_P(GLSLTest,MatrixScalarOps)17695 TEST_P(GLSLTest, MatrixScalarOps)
17696 {
17697     constexpr char kFS[] = R"(precision highp float;
17698 void main() {
17699     float scalar = 0.5;
17700     mat3 matrix = mat3(vec3(0.1), vec3(0.1), vec3(0.1));
17701 
17702     mat3 m0 = scalar / matrix;
17703     mat3 m1 = scalar * matrix;
17704     mat3 m2 = scalar + matrix;
17705     mat3 m3 = scalar - matrix;
17706 
17707     gl_FragColor = vec4(m0[0][0], m1[0][0], m2[0][0], m3[0][0]);
17708 }
17709 )";
17710 
17711     ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), kFS);
17712     ASSERT_GL_NO_ERROR();
17713 
17714     drawQuad(testProgram, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
17715     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 13, 153, 102), 1.0);
17716     ASSERT_GL_NO_ERROR();
17717 }
17718 
17719 // Test coverage of some matrix ops which Metal translation was missing.
TEST_P(GLSLTest,MatrixNegate)17720 TEST_P(GLSLTest, MatrixNegate)
17721 {
17722     constexpr char kFS[] = R"(precision highp float;
17723 void main() {
17724     mat3 matrix = mat3(vec3(-0.1), vec3(-0.1), vec3(-0.1));
17725 
17726     mat3 m0 = -matrix;
17727 
17728     gl_FragColor = vec4(m0[0][0], 0, 0, 1);
17729 }
17730 )";
17731 
17732     ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), kFS);
17733     ASSERT_GL_NO_ERROR();
17734 
17735     drawQuad(testProgram, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
17736     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(26, 0, 0, 255), 1.0);
17737     ASSERT_GL_NO_ERROR();
17738 }
17739 
17740 // Test coverage of the mix(float, float, bool) overload which was missing in Metal translation
TEST_P(GLSLTest_ES3,MixFloatFloatBool)17741 TEST_P(GLSLTest_ES3, MixFloatFloatBool)
17742 {
17743     constexpr char kFS[] = R"(#version 300 es
17744 precision highp float;
17745 out vec4 fragColor;
17746 void main() {
17747     vec4 testData = vec4(0.0, 1.0, 0.5, 0.25);
17748     float scalar = mix(testData.x, testData.y, testData.x < 0.5);
17749     vec2 vector = mix(testData.xy, testData.xw, bvec2(testData.x < 0.5, testData.y < 0.5));
17750     fragColor = vec4(scalar, vector.x, vector.y, 1);
17751 }
17752 )";
17753 
17754     ANGLE_GL_PROGRAM(testProgram, essl3_shaders::vs::Simple(), kFS);
17755     ASSERT_GL_NO_ERROR();
17756 
17757     drawQuad(testProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
17758     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(255, 0, 255, 255));
17759     ASSERT_GL_NO_ERROR();
17760 }
17761 
17762 // Test coverage of the mix(uint, uint, bool) overload which was missing in D3D11 translation
TEST_P(GLSLTest_ES31,MixUintUintBool)17763 TEST_P(GLSLTest_ES31, MixUintUintBool)
17764 {
17765     constexpr char kFS[] = R"(#version 310 es
17766 precision highp float;
17767 out vec4 fragColor;
17768 void main() {
17769     uvec4 testData1 = uvec4(0, 1, 2, 3);
17770     uvec4 testData2 = uvec4(4, 5, 6, 7);
17771     uint scalar = mix(testData1.x, testData2.x, true);
17772     uvec4 vector = mix(testData1, testData2, bvec4(false, true, true, false));
17773     fragColor = vec4(scalar == 4u ? 1.0 : 0.0, vector == uvec4(0, 5, 6, 3) ? 1.0 : 0.0, 0.0, 1.0);
17774 }
17775 )";
17776 
17777     ANGLE_GL_PROGRAM(testProgram, essl31_shaders::vs::Simple(), kFS);
17778     ASSERT_GL_NO_ERROR();
17779 
17780     drawQuad(testProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
17781     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(255, 255, 0, 255));
17782     ASSERT_GL_NO_ERROR();
17783 }
17784 
17785 // Test coverage of the mix(int, int, bool) overload which was missing in D3D11 translation
TEST_P(GLSLTest_ES31,MixIntIntBool)17786 TEST_P(GLSLTest_ES31, MixIntIntBool)
17787 {
17788     constexpr char kFS[] = R"(#version 310 es
17789 precision highp float;
17790 out vec4 fragColor;
17791 void main() {
17792     ivec4 testData1 = ivec4(-4, -3, -2, -1);
17793     ivec4 testData2 = ivec4(4, 5, 6, 7);
17794     int scalar = mix(testData1.x, testData2.x, true);
17795     ivec4 vector = mix(testData1, testData2, bvec4(false, true, true, false));
17796     fragColor = vec4(scalar == 4 ? 1.0 : 0.0, vector == ivec4(-4, 5, 6, -1) ? 1.0 : 0.0, 0.0, 1.0);
17797 }
17798 )";
17799 
17800     ANGLE_GL_PROGRAM(testProgram, essl31_shaders::vs::Simple(), kFS);
17801     ASSERT_GL_NO_ERROR();
17802 
17803     drawQuad(testProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
17804     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(255, 255, 0, 255));
17805     ASSERT_GL_NO_ERROR();
17806 }
17807 
17808 // Test that aliasing function inout parameters work when more than one param is aliased.
TEST_P(GLSLTest,AliasingFunctionInOutParamsMultiple)17809 TEST_P(GLSLTest, AliasingFunctionInOutParamsMultiple)
17810 {
17811     constexpr char kFS[] = R"(precision highp float;
17812 
17813 const vec4 colorGreen = vec4(0.,1.,0.,1.);
17814 const vec4 colorRed   = vec4(1.,0.,0.,1.);
17815 
17816 bool inoutParametersAreDistinct(inout float x, inout float y, inout float z, inout float a) {
17817     x = 1.0;
17818     y = 2.0;
17819     z = 3.0;
17820     a = 4.0;
17821     return x == 1.0 && y == 2.0 && z == 3.0 && a == 4.0;
17822 }
17823 void main() {
17824     float x = 0.0;
17825     float y = 0.0;
17826     gl_FragColor = inoutParametersAreDistinct(x, x, y, y) ? colorGreen : colorRed;
17827 }
17828 )";
17829 
17830     ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), kFS);
17831     drawQuad(testProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
17832     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
17833     ASSERT_GL_NO_ERROR();
17834 }
17835 
17836 // Test that aliasing function out parameter with a global works.
TEST_P(GLSLTest,AliasingFunctionOutParamAndGlobal)17837 TEST_P(GLSLTest, AliasingFunctionOutParamAndGlobal)
17838 {
17839     constexpr char kFS[] = R"(precision highp float;
17840 
17841 const vec4 colorGreen = vec4(0.,1.,0.,1.);
17842 const vec4 colorRed   = vec4(1.,0.,0.,1.);
17843 
17844 float x = 1.0;
17845 bool outParametersAreDistinctFromGlobal(out float y) {
17846     y = 2.0;
17847     return x == 1.0 && y == 2.0;
17848 }
17849 void main() {
17850     gl_FragColor = outParametersAreDistinctFromGlobal(x) ? colorGreen : colorRed;
17851 }
17852 )";
17853 
17854     ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), kFS);
17855     drawQuad(testProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
17856     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
17857     ASSERT_GL_NO_ERROR();
17858 }
17859 
17860 // Make sure const sampler parameters work.
TEST_P(GLSLTest,ConstSamplerParameter)17861 TEST_P(GLSLTest, ConstSamplerParameter)
17862 {
17863     constexpr char kFS[] = R"(precision mediump float;
17864 uniform sampler2D samp;
17865 
17866 vec4 sampleConstSampler(const sampler2D s) {
17867     return texture2D(s, vec2(0));
17868 }
17869 
17870 void main() {
17871     gl_FragColor = sampleConstSampler(samp);
17872 }
17873 )";
17874     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
17875     glUseProgram(program);
17876     GLTexture texture;
17877     GLColor expected = MakeGLColor(32, 64, 96, 255);
17878     glBindTexture(GL_TEXTURE_2D, texture);
17879     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, expected.data());
17880     GLint u = glGetUniformLocation(program, "samp");
17881     EXPECT_NE(u, -1);
17882     glUniform1i(u, 0);
17883     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
17884     EXPECT_PIXEL_COLOR_EQ(0, 0, expected);
17885     ASSERT_GL_NO_ERROR();
17886 }
17887 
17888 // Make sure const sampler parameters work.
TEST_P(GLSLTest,ConstInSamplerParameter)17889 TEST_P(GLSLTest, ConstInSamplerParameter)
17890 {
17891     constexpr char kFS[] = R"(precision mediump float;
17892 uniform sampler2D u;
17893 vec4 sampleConstSampler(const in sampler2D s) {
17894     return texture2D(s, vec2(0));
17895 }
17896 void main() {
17897     gl_FragColor = sampleConstSampler(u);
17898 }
17899 )";
17900     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
17901     glUseProgram(program);
17902     GLTexture texture;
17903     GLColor expected = MakeGLColor(32, 64, 96, 255);
17904     glBindTexture(GL_TEXTURE_2D, texture);
17905     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, expected.data());
17906     GLint u = glGetUniformLocation(program, "u");
17907     EXPECT_NE(u, -1);
17908     glUniform1i(u, 0);
17909     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
17910     EXPECT_PIXEL_COLOR_EQ(0, 0, expected);
17911     ASSERT_GL_NO_ERROR();
17912 }
17913 
17914 // Make sure passing const sampler parameters to another function work.
TEST_P(GLSLTest,ConstSamplerParameterAsArgument)17915 TEST_P(GLSLTest, ConstSamplerParameterAsArgument)
17916 {
17917     constexpr char kFS[] = R"(precision mediump float;
17918 
17919 uniform sampler2D samp;
17920 
17921 vec4 sampleSampler(sampler2D s) {
17922     return texture2D(s, vec2(0));
17923 }
17924 
17925 vec4 sampleConstSampler(const sampler2D s) {
17926     return sampleSampler(s);
17927 }
17928 
17929 void main() {
17930     gl_FragColor = sampleConstSampler(samp);
17931 }
17932 )";
17933     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
17934     glUseProgram(program);
17935     GLTexture texture;
17936     GLColor expected = MakeGLColor(32, 64, 96, 255);
17937     glBindTexture(GL_TEXTURE_2D, texture);
17938     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, expected.data());
17939     GLint u = glGetUniformLocation(program, "samp");
17940     EXPECT_NE(u, -1);
17941     glUniform1i(u, 0);
17942     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
17943     EXPECT_PIXEL_COLOR_EQ(0, 0, expected);
17944     ASSERT_GL_NO_ERROR();
17945 }
17946 
17947 // Test for a driver bug with matrix multiplication in the tessellation control shader.
TEST_P(GLSLTest_ES31,TessellationControlShaderMatrixMultiplicationBug)17948 TEST_P(GLSLTest_ES31, TessellationControlShaderMatrixMultiplicationBug)
17949 {
17950     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
17951 
17952     constexpr char kTCS[] = R"(#version 310 es
17953 #extension GL_EXT_tessellation_shader : enable
17954 layout(vertices = 1) out;
17955 precision highp float;
17956 
17957 patch out mat4 x;
17958 
17959 void main()
17960 {
17961     x = mat4(
17962         0.53455, 0.47307, 0.34935, 0.28717,
17963         0.67195, 0.59992, 0.48213, 0.43678,
17964         0.76376, 0.6772, 0.55361, 0.5165,
17965         0.77996, 0.68862, 0.56187, 0.52611
17966     );
17967 
17968     const mat4 m = mat4(
17969         vec4( -1.0, 3.0,-3.0, 1.0),
17970         vec4(  3.0,-6.0, 3.0, 0.0),
17971         vec4( -3.0, 3.0, 0.0, 0.0),
17972         vec4(  1.0, 0.0, 0.0, 0.0)
17973     );
17974 
17975     x = m * x;
17976 
17977     gl_TessLevelInner[0u] = 1.;
17978     gl_TessLevelInner[1u] = 1.;
17979     gl_TessLevelOuter[0u] = 1.;
17980     gl_TessLevelOuter[1u] = 1.;
17981     gl_TessLevelOuter[2u] = 1.;
17982     gl_TessLevelOuter[3u] = 1.;
17983 })";
17984 
17985     constexpr char kTES[] = R"(#version 310 es
17986 #extension GL_EXT_tessellation_shader : enable
17987 layout(quads, cw, fractional_odd_spacing) in;
17988 precision highp float;
17989 
17990 patch in mat4 x;
17991 
17992 out mat4 x_fs;
17993 
17994 void main()
17995 {
17996     x_fs = x;
17997     gl_Position = vec4(gl_TessCoord.xy * 2. - 1., 0, 1);
17998 })";
17999 
18000     constexpr char kFS[] = R"(#version 310 es
18001 precision highp float;
18002 
18003 in mat4 x_fs;
18004 out vec4 color;
18005 
18006 void main()
18007 {
18008     // Note: on the failing driver, .w of every column has the same value as .x of the same column.
18009 
18010     const mat4 expect = mat4(
18011         0.12378, -0.18672, -0.18444, 0.53455,
18012         0.1182, -0.13728, -0.21609, 0.67195,
18013         0.12351, -0.11109, -0.25968, 0.76376,
18014         0.1264, -0.10623, -0.27402, 0.77996
18015     );
18016 
18017     color = vec4(all(lessThan(abs(x_fs[0] - expect[0]), vec4(0.01))),
18018                  all(lessThan(abs(x_fs[1] - expect[1]), vec4(0.01))),
18019                  all(lessThan(abs(x_fs[2] - expect[2]), vec4(0.01))),
18020                  all(lessThan(abs(x_fs[3] - expect[3]), vec4(0.01))));
18021 })";
18022 
18023     ANGLE_GL_PROGRAM_WITH_TESS(program, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
18024     drawPatches(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, GL_FALSE);
18025     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
18026     ASSERT_GL_NO_ERROR();
18027 }
18028 
18029 // Test for a driver bug with matrix copy in the tessellation control shader.
TEST_P(GLSLTest_ES31,TessellationControlShaderMatrixCopyBug)18030 TEST_P(GLSLTest_ES31, TessellationControlShaderMatrixCopyBug)
18031 {
18032     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
18033 
18034     constexpr char kTCS[] = R"(#version 310 es
18035 #extension GL_EXT_tessellation_shader : enable
18036 layout(vertices = 1) out;
18037 precision highp float;
18038 
18039 patch out mat4 x;
18040 patch out vec4 col0;
18041 
18042 void main()
18043 {
18044     // Note: if |x| is not an |out| varying, the test passes.
18045     x = mat4(
18046         0.53455, 0.47307, 0.34935, 0.28717,
18047         0.67195, 0.59992, 0.48213, 0.43678,
18048         0.76376, 0.6772, 0.55361, 0.5165,
18049         0.77996, 0.68862, 0.56187, 0.52611
18050     );
18051 
18052     const mat4 m = mat4(
18053         vec4( -1.0, 3.0,-3.0, 1.0),
18054         vec4(  3.0,-6.0, 3.0, 0.0),
18055         vec4( -3.0, 3.0, 0.0, 0.0),
18056         vec4(  1.0, 0.0, 0.0, 0.0)
18057     );
18058 
18059     mat4 temp = x;
18060 
18061     // Note: On the failing driver, commenting this line makes the test pass.
18062     // However, the output being tested is |temp|, assigned above, not |x|.
18063     x = m * x;
18064 
18065     col0 = temp[0];
18066 
18067     gl_TessLevelInner[0u] = 1.;
18068     gl_TessLevelInner[1u] = 1.;
18069     gl_TessLevelOuter[0u] = 1.;
18070     gl_TessLevelOuter[1u] = 1.;
18071     gl_TessLevelOuter[2u] = 1.;
18072     gl_TessLevelOuter[3u] = 1.;
18073 })";
18074 
18075     constexpr char kTES[] = R"(#version 310 es
18076 #extension GL_EXT_tessellation_shader : enable
18077 layout(quads, cw, fractional_odd_spacing) in;
18078 precision highp float;
18079 
18080 patch in vec4 col0;
18081 
18082 out vec4 col0_fs;
18083 
18084 void main()
18085 {
18086     col0_fs = col0;
18087     gl_Position = vec4(gl_TessCoord.xy * 2. - 1., 0, 1);
18088 })";
18089 
18090     constexpr char kFS[] = R"(#version 310 es
18091 precision highp float;
18092 
18093 in vec4 col0_fs;
18094 out vec4 color;
18095 
18096 void main()
18097 {
18098     // Note: on the failing driver, |col0| has the value of |m * x|, not |temp|.
18099     color = vec4(abs(col0_fs.x - 0.53455) < 0.01,
18100                 abs(col0_fs.y - 0.47307) < 0.01,
18101                 abs(col0_fs.z - 0.34935) < 0.01,
18102                 abs(col0_fs.w - 0.28717) < 0.01);
18103 })";
18104 
18105     ANGLE_GL_PROGRAM_WITH_TESS(program, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
18106     drawPatches(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, GL_FALSE);
18107     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
18108     ASSERT_GL_NO_ERROR();
18109 }
18110 
18111 // Tests the generation of HLSL functions with uint/int parameters that may be ambiguous.
TEST_P(GLSLTest_ES3,AmbiguousHLSLIntegerFunctionParameters)18112 TEST_P(GLSLTest_ES3, AmbiguousHLSLIntegerFunctionParameters)
18113 {
18114     const char kVS[] = R"(#version 300 es
18115 precision highp float;
18116 void main()
18117 {
18118     gl_Position = vec4(0, 0, 0, 0);
18119 })";
18120 
18121     const char kFS[] = R"(#version 300 es
18122 precision highp float;
18123 out vec4 color;
18124 void main()
18125 {
18126     // Ensure that both uint and int to float constructors are generated before the ambiguous usage.
18127     int i = int(gl_FragCoord.x);
18128     float f1 = float(i);
18129     color.r = f1;
18130 
18131     uint ui = uint(gl_FragCoord.x);
18132     float f2 = float(i);
18133     color.g = f2;
18134 
18135     // Ambiguous call
18136     float f3 = float(1u << (2u * ui));
18137     color.b = f3;
18138 })";
18139 
18140     ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
18141 }
18142 
18143 // Tests adding a struct definition inline in a shader.
18144 // Metal backend contains a pass that separates struct definition and declaration.
TEST_P(GLSLTest_ES3,StructInShader)18145 TEST_P(GLSLTest_ES3, StructInShader)
18146 {
18147     const char kVS[] = R"(#version 300 es
18148 precision highp float;
18149 void main(void)
18150 {
18151     struct structMain {
18152         float i;
18153     } testStruct;
18154 
18155     testStruct.i = 5.0 ;
18156     gl_Position = vec4(testStruct.i - 4.0, 0, 0, 1);
18157 })";
18158 
18159     const char kFS[] = R"(#version 300 es
18160 precision highp float;
18161 out vec4 color;
18162 void main()
18163 {
18164     color = vec4(0,1,0,0);
18165 })";
18166 
18167     ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
18168 }
18169 
18170 // Issue: A while loop's expression, and a branch
18171 // condition with EOpContinue were being deep
18172 // copied as part of monomorphize functions,
18173 // causing a crash, as they were not null-checked.
18174 // Tests transforming a function that will be monomorphized.
TEST_P(GLSLTest_ES3,MonomorphizeForAndContinue)18175 TEST_P(GLSLTest_ES3, MonomorphizeForAndContinue)
18176 {
18177 
18178     constexpr char kFS[] =
18179         R"(#version 300 es
18180 
18181         precision mediump float;
18182         out vec4 fragOut;
18183         struct aParam
18184         {
18185             sampler2D sampler;
18186         };
18187         uniform aParam theParam;
18188 
18189         float monomorphizedFunction(aParam a)
18190         {
18191             int i = 0;
18192             vec4 j = vec4(0);
18193             for(;;)
18194             {
18195                 if(i++ < 10)
18196                 {
18197                     j += texture(a.sampler, vec2(0.0f,0.0f));
18198                     continue;
18199                 }
18200                 break;
18201             }
18202             return j.a;
18203         }
18204         void main()
18205         {
18206             fragOut.a = monomorphizedFunction(theParam);
18207         }
18208 )";
18209     CompileShader(GL_FRAGMENT_SHADER, kFS);
18210     ASSERT_GL_NO_ERROR();
18211 }
18212 
18213 // Tests inout parameters with array references.
TEST_P(GLSLTest_ES3,InoutWithArrayRefs)18214 TEST_P(GLSLTest_ES3, InoutWithArrayRefs)
18215 {
18216     const char kVS[] = R"(#version 300 es
18217 precision highp float;
18218 void swap(inout float a, inout float b)
18219 {
18220     float tmp = a;
18221     a = b;
18222     b = tmp;
18223 }
18224 
18225 void main(void)
18226 {
18227     vec3 testVec = vec3(0.0, 1.0, 1.0);
18228     swap(testVec[0], testVec[1]);
18229     gl_Position = vec4(testVec[0], testVec[1], testVec[2], 1.0);
18230 })";
18231 
18232     const char kFS[] = R"(#version 300 es
18233 precision highp float;
18234 out vec4 color;
18235 void main()
18236 {
18237     color = vec4(0,1,0,0);
18238 })";
18239 
18240     ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
18241 }
18242 
18243 // Test that sample variables compile.
TEST_P(GLSLTest_ES3,SampleVariables)18244 TEST_P(GLSLTest_ES3, SampleVariables)
18245 {
18246     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_sample_variables"));
18247 
18248     const char kFS[] = R"(#version 300 es
18249 #extension GL_OES_sample_variables : require
18250 precision highp float;
18251 out vec4 color;
18252 void main()
18253 {
18254     gl_SampleMask[0] = gl_SampleMaskIn[0] & 0x55555555;
18255     color = vec4(gl_SamplePosition.yx, float(gl_SampleID), float(gl_MaxSamples + gl_NumSamples));
18256 })";
18257 
18258     ANGLE_GL_PROGRAM(testProgram, essl3_shaders::vs::Simple(), kFS);
18259 }
18260 
18261 // Test that shader caching maintains uniforms across compute shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheComputeWithUniform)18262 TEST_P(GLSLTest_ES31, ShaderCacheComputeWithUniform)
18263 {
18264     ANGLE_SKIP_TEST_IF(!IsVulkan());
18265     constexpr char kCS[] = R"(#version 310 es
18266 layout (local_size_x = 2, local_size_y = 3, local_size_z = 1) in;
18267 
18268 uniform uint inputs[6];
18269 
18270 layout (binding = 0, std430) buffer OutputBuffer {
18271     uint outputs[6];
18272 };
18273 
18274 void main() {
18275     outputs[gl_LocalInvocationIndex] = inputs[gl_LocalInvocationIndex];
18276 }
18277 )";
18278 
18279     ANGLE_GL_COMPUTE_PROGRAM(unusedProgram, kCS);
18280     ASSERT_GL_NO_ERROR();
18281     // Delete the shader and recompile to fetch from cache.
18282     glDeleteProgram(unusedProgram);
18283     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
18284     ASSERT_GL_NO_ERROR();
18285     glUseProgram(program);
18286 
18287     constexpr std::array<GLuint, 6> kInputUniform = {1, 2, 3, 4, 5, 6};
18288     for (int i = 0; i < static_cast<int>(kInputUniform.size()); ++i)
18289     {
18290         const std::string uniformName =
18291             std::string("inputs[") + std::to_string(i) + std::string("]");
18292         int inputLocation =
18293             glGetUniformLocation(program, static_cast<const GLchar *>(uniformName.c_str()));
18294         glUniform1ui(inputLocation, kInputUniform[i]);
18295         ASSERT_GL_NO_ERROR();
18296     }
18297 
18298     constexpr std::array<GLuint, 6> kOutputInitData = {0, 0, 0, 0, 0, 0};
18299     GLBuffer outputBuffer;
18300     glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
18301     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLuint) * kOutputInitData.size(),
18302                  kOutputInitData.data(), GL_STATIC_READ);
18303     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, outputBuffer);
18304 
18305     glDispatchCompute(1, 1, 1);
18306     glDeleteProgram(program);
18307     ASSERT_GL_NO_ERROR();
18308     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
18309 
18310     auto outputData = static_cast<const GLuint *>(glMapBufferRange(
18311         GL_SHADER_STORAGE_BUFFER, 0, sizeof(GLuint) * kOutputInitData.size(), GL_MAP_READ_BIT));
18312     for (int i = 0; i < static_cast<int>(kInputUniform.size()); ++i)
18313     {
18314         EXPECT_EQ(kInputUniform[i], outputData[i]);
18315     }
18316 }
18317 
18318 // Test that shader caching maintains uniform blocks across shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheComputeWithUniformBlocks)18319 TEST_P(GLSLTest_ES31, ShaderCacheComputeWithUniformBlocks)
18320 {
18321     ANGLE_SKIP_TEST_IF(!IsVulkan());
18322     constexpr char kCS[] = R"(#version 310 es
18323 layout (local_size_x = 2, local_size_y = 3, local_size_z = 1) in;
18324 
18325 layout (std140) uniform Input1 {
18326     uint input1;
18327 };
18328 
18329 layout (std140) uniform Input2 {
18330     uint input2;
18331 };
18332 
18333 layout (binding = 0, std430) buffer OutputBuffer {
18334     uint outputs[6];
18335 };
18336 
18337 void main() {
18338     if (gl_LocalInvocationIndex < uint(3))
18339     {
18340         outputs[gl_LocalInvocationIndex] = input1;
18341     }
18342     else
18343     {
18344         outputs[gl_LocalInvocationIndex] = input2;
18345     }
18346 }
18347 )";
18348 
18349     ANGLE_GL_COMPUTE_PROGRAM(unusedProgram, kCS);
18350     ASSERT_GL_NO_ERROR();
18351     // Delete the shader and recompile to fetch from cache.
18352     glDeleteProgram(unusedProgram);
18353     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
18354     ASSERT_GL_NO_ERROR();
18355     glUseProgram(program);
18356 
18357     constexpr GLuint kInput1Data = 1;
18358     GLBuffer input1;
18359     glBindBuffer(GL_UNIFORM_BUFFER, input1);
18360     glBufferData(GL_UNIFORM_BUFFER, sizeof(GLuint), &kInput1Data, GL_STATIC_COPY);
18361     const GLuint kInput1Index = glGetUniformBlockIndex(program, "Input1");
18362     glUniformBlockBinding(program, kInput1Index, 1);
18363     glBindBufferBase(GL_UNIFORM_BUFFER, 1, input1);
18364     glBindBuffer(GL_UNIFORM_BUFFER, 0);
18365     ASSERT_GL_NO_ERROR();
18366 
18367     constexpr GLuint kInput2Data = 2;
18368     GLBuffer input2;
18369     glBindBuffer(GL_UNIFORM_BUFFER, input2);
18370     glBufferData(GL_UNIFORM_BUFFER, sizeof(GLuint), &kInput2Data, GL_STATIC_COPY);
18371     const GLuint kInput2Index = glGetUniformBlockIndex(program, "Input2");
18372     glUniformBlockBinding(program, kInput2Index, 2);
18373     glBindBufferBase(GL_UNIFORM_BUFFER, 2, input2);
18374     glBindBuffer(GL_UNIFORM_BUFFER, 0);
18375     ASSERT_GL_NO_ERROR();
18376 
18377     constexpr std::array<GLuint, 6> kOutputInitData = {0, 0, 0, 0, 0, 0};
18378     GLBuffer outputBuffer;
18379     glBindBuffer(GL_SHADER_STORAGE_BUFFER, outputBuffer);
18380     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLuint) * kOutputInitData.size(),
18381                  kOutputInitData.data(), GL_STATIC_READ);
18382     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, outputBuffer);
18383     ASSERT_GL_NO_ERROR();
18384 
18385     glDispatchCompute(1, 1, 1);
18386     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
18387     glDeleteProgram(program);
18388     ASSERT_GL_NO_ERROR();
18389 
18390     auto outputData                       = static_cast<const GLuint *>(glMapBufferRange(
18391         GL_SHADER_STORAGE_BUFFER, 0, sizeof(GLuint) * kOutputInitData.size(), GL_MAP_READ_BIT));
18392     constexpr std::array<GLuint, 6> kWant = {kInput1Data, kInput1Data, kInput1Data,
18393                                              kInput2Data, kInput2Data, kInput2Data};
18394     for (int i = 0; i < static_cast<int>(kWant.size()); ++i)
18395     {
18396         EXPECT_EQ(kWant[i], outputData[i]);
18397     }
18398 }
18399 
18400 // Test that shader caching maintains uniforms across vertex shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheVertexWithUniform)18401 TEST_P(GLSLTest_ES31, ShaderCacheVertexWithUniform)
18402 {
18403     ANGLE_SKIP_TEST_IF(!IsVulkan());
18404     constexpr char kVS[] = R"(#version 310 es
18405 
18406 precision mediump float;
18407 
18408 layout (location = 0) in vec4 a_position;
18409 
18410 uniform float redInput;
18411 
18412 out float redValue;
18413 
18414 void main() {
18415     gl_Position = a_position;
18416     redValue = redInput;
18417 })";
18418 
18419     constexpr char kFS[] = R"(#version 310 es
18420 
18421 precision mediump float;
18422 
18423 in float redValue;
18424 
18425 out vec4 fragColor;
18426 
18427 void main()
18428 {
18429     fragColor = vec4(redValue, 0., 0., 1.);
18430 })";
18431 
18432     ANGLE_GL_PROGRAM(unusedProgram, kVS, kFS);
18433     ASSERT_GL_NO_ERROR();
18434     // Delete the shader and recompile to fetch from cache.
18435     glDeleteProgram(unusedProgram);
18436     ANGLE_GL_PROGRAM(program, kVS, kFS);
18437     ASSERT_GL_NO_ERROR();
18438     glUseProgram(program);
18439 
18440     constexpr GLfloat kRedValue = 1.0f;
18441     int redInputLocation        = glGetUniformLocation(program, "redInput");
18442     glUniform1f(redInputLocation, kRedValue);
18443     ASSERT_GL_NO_ERROR();
18444 
18445     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18446     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18447 }
18448 
18449 // Test that shader caching maintains uniform blocks across vertex shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheVertexWithUniformBlock)18450 TEST_P(GLSLTest_ES31, ShaderCacheVertexWithUniformBlock)
18451 {
18452     ANGLE_SKIP_TEST_IF(!IsVulkan());
18453     constexpr char kVS[] = R"(#version 310 es
18454 
18455 precision mediump float;
18456 
18457 layout (location = 0) in vec4 a_position;
18458 
18459 layout (std140) uniform Input {
18460     float redInput;
18461 };
18462 
18463 out float redValue;
18464 
18465 void main() {
18466     gl_Position = a_position;
18467     redValue = redInput;
18468 })";
18469 
18470     constexpr char kFS[] = R"(#version 310 es
18471 
18472 precision mediump float;
18473 
18474 in float redValue;
18475 
18476 out vec4 fragColor;
18477 
18478 void main()
18479 {
18480     fragColor = vec4(redValue, 0., 0., 1.);
18481 })";
18482 
18483     ANGLE_GL_PROGRAM(unusedProgram, kVS, kFS);
18484     ASSERT_GL_NO_ERROR();
18485     // Delete the shader and recompile to fetch from cache.
18486     glDeleteProgram(unusedProgram);
18487     ANGLE_GL_PROGRAM(program, kVS, kFS);
18488     ASSERT_GL_NO_ERROR();
18489     glUseProgram(program);
18490 
18491     constexpr GLfloat kInputData = 1.0f;
18492     GLBuffer input;
18493     glBindBuffer(GL_UNIFORM_BUFFER, input);
18494     glBufferData(GL_UNIFORM_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
18495     const GLuint kInputIndex = glGetUniformBlockIndex(program, "Input");
18496     glUniformBlockBinding(program, kInputIndex, 0);
18497     glBindBufferBase(GL_UNIFORM_BUFFER, 0, input);
18498     glBindBuffer(GL_UNIFORM_BUFFER, 0);
18499     ASSERT_GL_NO_ERROR();
18500 
18501     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18502     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18503 }
18504 
18505 // Test that shader caching maintains SSBOs across vertex shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheVertexWithSSBO)18506 TEST_P(GLSLTest_ES31, ShaderCacheVertexWithSSBO)
18507 {
18508     ANGLE_SKIP_TEST_IF(!IsVulkan());
18509 
18510     // Check that GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS is at least 1.
18511     GLint maxVertexShaderStorageBlocks;
18512     glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &maxVertexShaderStorageBlocks);
18513     ANGLE_SKIP_TEST_IF(maxVertexShaderStorageBlocks == 0);
18514     constexpr char kVS[] = R"(#version 310 es
18515 
18516 precision mediump float;
18517 
18518 layout (location = 0) in vec4 a_position;
18519 
18520 layout (binding = 0, std430) buffer Input {
18521     float redInput;
18522 };
18523 
18524 out float redValue;
18525 
18526 void main() {
18527     gl_Position = a_position;
18528     redValue = redInput;
18529 })";
18530 
18531     constexpr char kFS[] = R"(#version 310 es
18532 
18533 precision mediump float;
18534 
18535 in float redValue;
18536 
18537 out vec4 fragColor;
18538 
18539 void main()
18540 {
18541     fragColor = vec4(redValue, 0., 0., 1.);
18542 })";
18543 
18544     ANGLE_GL_PROGRAM(unusedProgram, kVS, kFS);
18545     ASSERT_GL_NO_ERROR();
18546     // Delete the shader and recompile to fetch from cache.
18547     glDeleteProgram(unusedProgram);
18548     ANGLE_GL_PROGRAM(program, kVS, kFS);
18549     ASSERT_GL_NO_ERROR();
18550     glUseProgram(program);
18551 
18552     constexpr GLfloat kInputData = 1.0f;
18553     GLBuffer input;
18554     glBindBuffer(GL_SHADER_STORAGE_BUFFER, input);
18555     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
18556     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, input);
18557     glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
18558     ASSERT_GL_NO_ERROR();
18559 
18560     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18561     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18562 }
18563 
18564 // Test that shader caching maintains uniforms across vertex shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheFragmentWithUniform)18565 TEST_P(GLSLTest_ES31, ShaderCacheFragmentWithUniform)
18566 {
18567     ANGLE_SKIP_TEST_IF(!IsVulkan());
18568     constexpr char kFS[] = R"(#version 310 es
18569 
18570 precision mediump float;
18571 
18572 uniform float redValue;
18573 
18574 out vec4 fragColor;
18575 
18576 void main()
18577 {
18578     fragColor = vec4(redValue, 0., 0., 1.);
18579 })";
18580 
18581     ANGLE_GL_PROGRAM(unusedProgram, essl31_shaders::vs::Simple(), kFS);
18582     ASSERT_GL_NO_ERROR();
18583     // Delete the shader and recompile to fetch from cache.
18584     glDeleteProgram(unusedProgram);
18585     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
18586     ASSERT_GL_NO_ERROR();
18587     glUseProgram(program);
18588 
18589     GLfloat redValue     = 1.0f;
18590     int redInputLocation = glGetUniformLocation(program, "redValue");
18591     glUniform1f(redInputLocation, redValue);
18592     ASSERT_GL_NO_ERROR();
18593 
18594     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18595     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18596 }
18597 
18598 // Test that shader caching maintains uniform blocks across vertex shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheFragmentWithUniformBlock)18599 TEST_P(GLSLTest_ES31, ShaderCacheFragmentWithUniformBlock)
18600 {
18601     ANGLE_SKIP_TEST_IF(!IsVulkan());
18602     constexpr char kFS[] = R"(#version 310 es
18603 
18604 precision mediump float;
18605 
18606 layout (std140) uniform Input {
18607     float redValue;
18608 };
18609 
18610 out vec4 fragColor;
18611 
18612 void main()
18613 {
18614     fragColor = vec4(redValue, 0., 0., 1.);
18615 })";
18616 
18617     ANGLE_GL_PROGRAM(unusedProgram, essl31_shaders::vs::Simple(), kFS);
18618     ASSERT_GL_NO_ERROR();
18619     // Delete the shader and recompile to fetch from cache.
18620     glDeleteProgram(unusedProgram);
18621     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
18622     ASSERT_GL_NO_ERROR();
18623     glUseProgram(program);
18624 
18625     constexpr GLfloat kInputData = 1.0f;
18626     GLBuffer input;
18627     glBindBuffer(GL_UNIFORM_BUFFER, input);
18628     glBufferData(GL_UNIFORM_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
18629     const GLuint kInputIndex = glGetUniformBlockIndex(program, "Input");
18630     glUniformBlockBinding(program, kInputIndex, 0);
18631     glBindBufferBase(GL_UNIFORM_BUFFER, 0, input);
18632     glBindBuffer(GL_UNIFORM_BUFFER, 0);
18633     ASSERT_GL_NO_ERROR();
18634 
18635     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18636     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18637 }
18638 
18639 // Test that shader caching maintains SSBOs across vertex shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheFragmentWithSSBO)18640 TEST_P(GLSLTest_ES31, ShaderCacheFragmentWithSSBO)
18641 {
18642     ANGLE_SKIP_TEST_IF(!IsVulkan());
18643     constexpr char kFS[] = R"(#version 310 es
18644 
18645 precision mediump float;
18646 
18647 layout (binding = 0, std430) buffer Input {
18648     float redValue;
18649 };
18650 
18651 out vec4 fragColor;
18652 
18653 void main()
18654 {
18655     fragColor = vec4(redValue, 0., 0., 1.);
18656 })";
18657 
18658     ANGLE_GL_PROGRAM(unusedProgram, essl31_shaders::vs::Simple(), kFS);
18659     ASSERT_GL_NO_ERROR();
18660     // Delete the shader and recompile to fetch from cache.
18661     glDeleteProgram(unusedProgram);
18662     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
18663     ASSERT_GL_NO_ERROR();
18664     glUseProgram(program);
18665 
18666     constexpr GLfloat kInputData = 1.0f;
18667     GLBuffer input;
18668     glBindBuffer(GL_SHADER_STORAGE_BUFFER, input);
18669     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
18670     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, input);
18671     glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
18672     ASSERT_GL_NO_ERROR();
18673 
18674     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18675     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18676 }
18677 
18678 // Test that shader caching maintains whether GL_ARB_sample_shading is enabled across shader
18679 // compilations.
TEST_P(GLSLTest_ES31,ShaderCacheFragmentWithARBSampleShading)18680 TEST_P(GLSLTest_ES31, ShaderCacheFragmentWithARBSampleShading)
18681 {
18682     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ARB_sample_shading"));
18683     ANGLE_SKIP_TEST_IF(!IsVulkan());
18684 
18685     constexpr char kFS[] = R"(#version 310 es
18686 #extension GL_ARB_sample_shading : enable
18687 
18688 precision mediump float;
18689 
18690 out vec4 fragColor;
18691 
18692 void main()
18693 {
18694 #ifdef GL_ARB_sample_shading
18695     fragColor = vec4(1., 0., 0., 1.);
18696 #else
18697     fragColor = vec4(0.);
18698 #endif
18699 })";
18700 
18701     ANGLE_GL_PROGRAM(unusedProgram, essl31_shaders::vs::Simple(), kFS);
18702     ASSERT_GL_NO_ERROR();
18703     // Delete the shader and recompile to fetch from cache.
18704     glDeleteProgram(unusedProgram);
18705     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
18706     ASSERT_GL_NO_ERROR();
18707     glUseProgram(program);
18708 
18709     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18710     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18711 }
18712 
18713 // Test that shader caching maintains which advanced blending equations (provided by
18714 // GL_KHR_blend_equation_advanced) are used across shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheFragmentWithKHRAdvancedBlendEquations)18715 TEST_P(GLSLTest_ES31, ShaderCacheFragmentWithKHRAdvancedBlendEquations)
18716 {
18717     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_KHR_blend_equation_advanced"));
18718     ANGLE_SKIP_TEST_IF(!IsVulkan());
18719 
18720     constexpr char kFS[] = R"(#version 310 es
18721 #extension GL_KHR_blend_equation_advanced : require
18722 
18723 layout (blend_support_multiply) out;
18724 
18725 precision mediump float;
18726 
18727 out vec4 fragColor;
18728 
18729 void main()
18730 {
18731     fragColor = vec4(1., 0., 0., 1.);
18732 })";
18733 
18734     ANGLE_GL_PROGRAM(unusedProgram, essl31_shaders::vs::Simple(), kFS);
18735     ASSERT_GL_NO_ERROR();
18736     // Delete the shader and recompile to fetch from cache.
18737     glDeleteProgram(unusedProgram);
18738     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
18739     ASSERT_GL_NO_ERROR();
18740     glUseProgram(program);
18741 
18742     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18743     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18744 }
18745 
18746 // Test that shader caching maintains uniforms in geometry shaders across shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheGeometryWithUniform)18747 TEST_P(GLSLTest_ES31, ShaderCacheGeometryWithUniform)
18748 {
18749     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
18750     ANGLE_SKIP_TEST_IF(!IsVulkan());
18751 
18752     constexpr char kGS[] = R"(#version 310 es
18753 #extension GL_EXT_geometry_shader : require
18754 precision mediump float;
18755 
18756 layout (triangles) in;
18757 layout (triangle_strip, max_vertices = 3) out;
18758 
18759 uniform float redInput;
18760 
18761 out float redValue;
18762 
18763 void main() {
18764     gl_Position = gl_in[0].gl_Position;
18765     redValue = redInput;
18766     EmitVertex();
18767 
18768     gl_Position = gl_in[1].gl_Position;
18769     redValue = redInput;
18770     EmitVertex();
18771 
18772     gl_Position = gl_in[2].gl_Position;
18773     redValue = redInput;
18774     EmitVertex();
18775 
18776     EndPrimitive();
18777 }
18778 )";
18779 
18780     constexpr char kFS[] = R"(#version 310 es
18781 precision mediump float;
18782 
18783 out vec4 fragColor;
18784 
18785 in float redValue;
18786 
18787 void main()
18788 {
18789     fragColor = vec4(redValue, 0., 0., 1.);
18790 })";
18791 
18792     ANGLE_GL_PROGRAM_WITH_GS(unusedProgram, essl31_shaders::vs::Simple(), kGS, kFS);
18793     ASSERT_GL_NO_ERROR();
18794     // Delete the shader and recompile to fetch from cache.
18795     glDeleteProgram(unusedProgram);
18796     ANGLE_GL_PROGRAM_WITH_GS(program, essl31_shaders::vs::Simple(), kGS, kFS);
18797     ASSERT_GL_NO_ERROR();
18798     glUseProgram(program);
18799 
18800     constexpr GLfloat kRedValue = 1.0f;
18801     int redInputLocation        = glGetUniformLocation(program, "redInput");
18802     glUniform1f(redInputLocation, kRedValue);
18803     ASSERT_GL_NO_ERROR();
18804 
18805     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18806     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18807 }
18808 
18809 // Test that shader caching maintains uniform blocks in geometry shaders across shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheGeometryWithUniformBlock)18810 TEST_P(GLSLTest_ES31, ShaderCacheGeometryWithUniformBlock)
18811 {
18812     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
18813     ANGLE_SKIP_TEST_IF(!IsVulkan());
18814 
18815     constexpr char kGS[] = R"(#version 310 es
18816 #extension GL_EXT_geometry_shader : require
18817 precision mediump float;
18818 
18819 layout (triangles) in;
18820 layout (triangle_strip, max_vertices = 3) out;
18821 
18822 layout (std140) uniform Input {
18823     float redInput;
18824 };
18825 
18826 out float redValue;
18827 
18828 void main() {
18829     gl_Position = gl_in[0].gl_Position;
18830     redValue = redInput;
18831     EmitVertex();
18832 
18833     gl_Position = gl_in[1].gl_Position;
18834     redValue = redInput;
18835     EmitVertex();
18836 
18837     gl_Position = gl_in[2].gl_Position;
18838     redValue = redInput;
18839     EmitVertex();
18840 
18841     EndPrimitive();
18842 }
18843 )";
18844 
18845     constexpr char kFS[] = R"(#version 310 es
18846 precision mediump float;
18847 
18848 out vec4 fragColor;
18849 
18850 in float redValue;
18851 
18852 void main()
18853 {
18854     fragColor = vec4(redValue, 0., 0., 1.);
18855 })";
18856 
18857     ANGLE_GL_PROGRAM_WITH_GS(unusedProgram, essl31_shaders::vs::Simple(), kGS, kFS);
18858     ASSERT_GL_NO_ERROR();
18859     // Delete the shader and recompile to fetch from cache.
18860     glDeleteProgram(unusedProgram);
18861     ANGLE_GL_PROGRAM_WITH_GS(program, essl31_shaders::vs::Simple(), kGS, kFS);
18862     ASSERT_GL_NO_ERROR();
18863     glUseProgram(program);
18864 
18865     constexpr GLfloat kInputData = 1.0f;
18866     GLBuffer input;
18867     glBindBuffer(GL_UNIFORM_BUFFER, input);
18868     glBufferData(GL_UNIFORM_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
18869     const GLuint kInputIndex = glGetUniformBlockIndex(program, "Input");
18870     glUniformBlockBinding(program, kInputIndex, 0);
18871     glBindBufferBase(GL_UNIFORM_BUFFER, 0, input);
18872     glBindBuffer(GL_UNIFORM_BUFFER, 0);
18873     ASSERT_GL_NO_ERROR();
18874 
18875     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18876     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18877 }
18878 
18879 // Test that shader caching maintains SSBO in geometry shaders across shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheGeometryWithSSBO)18880 TEST_P(GLSLTest_ES31, ShaderCacheGeometryWithSSBO)
18881 {
18882     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
18883     ANGLE_SKIP_TEST_IF(!IsVulkan());
18884     GLint maxGeometryShaderStorageBlocks = 0;
18885     glGetIntegerv(GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT, &maxGeometryShaderStorageBlocks);
18886     ANGLE_SKIP_TEST_IF(maxGeometryShaderStorageBlocks == 0);
18887 
18888     constexpr char kGS[] = R"(#version 310 es
18889 #extension GL_EXT_geometry_shader : require
18890 precision mediump float;
18891 
18892 layout (triangles) in;
18893 layout (triangle_strip, max_vertices = 3) out;
18894 
18895 layout (binding = 0, std430) buffer Input {
18896     float redInput;
18897 };
18898 
18899 out float redValue;
18900 
18901 void main() {
18902     gl_Position = gl_in[0].gl_Position;
18903     redValue = redInput;
18904     EmitVertex();
18905 
18906     gl_Position = gl_in[1].gl_Position;
18907     redValue = redInput;
18908     EmitVertex();
18909 
18910     gl_Position = gl_in[2].gl_Position;
18911     redValue = redInput;
18912     EmitVertex();
18913 
18914     EndPrimitive();
18915 }
18916 )";
18917 
18918     constexpr char kFS[] = R"(#version 310 es
18919 precision mediump float;
18920 
18921 out vec4 fragColor;
18922 
18923 in float redValue;
18924 
18925 void main()
18926 {
18927     fragColor = vec4(redValue, 0., 0., 1.);
18928 })";
18929 
18930     ANGLE_GL_PROGRAM_WITH_GS(unusedProgram, essl31_shaders::vs::Simple(), kGS, kFS);
18931     ASSERT_GL_NO_ERROR();
18932     // Delete the shader and recompile to fetch from cache.
18933     glDeleteProgram(unusedProgram);
18934     ANGLE_GL_PROGRAM_WITH_GS(program, essl31_shaders::vs::Simple(), kGS, kFS);
18935     ASSERT_GL_NO_ERROR();
18936     glUseProgram(program);
18937 
18938     constexpr GLfloat kInputData = 1.0f;
18939     GLBuffer input;
18940     glBindBuffer(GL_SHADER_STORAGE_BUFFER, input);
18941     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
18942     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, input);
18943     glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
18944     ASSERT_GL_NO_ERROR();
18945 
18946     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
18947     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
18948 }
18949 
18950 // Test that shader caching maintains the number of invocations in geometry shaders across shader
18951 // compilations.
TEST_P(GLSLTest_ES31,ShaderCacheGeometryWithInvocations)18952 TEST_P(GLSLTest_ES31, ShaderCacheGeometryWithInvocations)
18953 {
18954     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
18955     ANGLE_SKIP_TEST_IF(!IsVulkan());
18956 
18957     constexpr char kGS[] = R"(#version 310 es
18958 #extension GL_EXT_geometry_shader : require
18959 precision mediump float;
18960 
18961 layout (triangles, invocations = 2) in;
18962 layout (triangle_strip, max_vertices = 3) out;
18963 
18964 out float redValue;
18965 
18966 void main() {
18967     float redOut = 0.;
18968     if (gl_InvocationID == 1) {
18969         redOut = 1.;
18970     }
18971 
18972     gl_Position = gl_in[0].gl_Position;
18973     redValue = redOut;
18974     EmitVertex();
18975 
18976     gl_Position = gl_in[1].gl_Position;
18977     redValue = redOut;
18978     EmitVertex();
18979 
18980     gl_Position = gl_in[2].gl_Position;
18981     redValue = redOut;
18982     EmitVertex();
18983 
18984     EndPrimitive();
18985 }
18986 )";
18987 
18988     constexpr char kFS[] = R"(#version 310 es
18989 precision mediump float;
18990 
18991 out vec4 fragColor;
18992 
18993 in float redValue;
18994 
18995 void main()
18996 {
18997     fragColor = vec4(redValue, 0., 0., 1.);
18998 })";
18999 
19000     ANGLE_GL_PROGRAM_WITH_GS(unusedProgram, essl31_shaders::vs::Simple(), kGS, kFS);
19001     ASSERT_GL_NO_ERROR();
19002     // Delete the shader and recompile to fetch from cache.
19003     glDeleteProgram(unusedProgram);
19004     ANGLE_GL_PROGRAM_WITH_GS(program, essl31_shaders::vs::Simple(), kGS, kFS);
19005     ASSERT_GL_NO_ERROR();
19006     glUseProgram(program);
19007 
19008     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
19009     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
19010 }
19011 
19012 // Test that shader caching maintains uniforms in tessellation control shaders across shader
19013 // compilations.
TEST_P(GLSLTest_ES31,ShaderCacheTessellationControlWithUniform)19014 TEST_P(GLSLTest_ES31, ShaderCacheTessellationControlWithUniform)
19015 {
19016     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
19017     ANGLE_SKIP_TEST_IF(!IsVulkan());
19018 
19019     constexpr char kTCS[] = R"(#version 310 es
19020 #extension GL_EXT_tessellation_shader : require
19021 precision mediump float;
19022 
19023 layout (vertices = 1) out;
19024 
19025 uniform float redInput;
19026 
19027 patch out float redValueCS;
19028 
19029 void main()
19030 {
19031     gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
19032     gl_TessLevelInner[0] = 1.0;
19033     gl_TessLevelInner[1] = 1.0;
19034     gl_TessLevelOuter[0] = 1.0;
19035     gl_TessLevelOuter[1] = 1.0;
19036     gl_TessLevelOuter[2] = 1.0;
19037     gl_TessLevelOuter[3] = 1.0;
19038 
19039     redValueCS = redInput;
19040 }
19041 
19042 )";
19043 
19044     constexpr char kTES[] = R"(#version 310 es
19045 #extension GL_EXT_tessellation_shader : require
19046 precision mediump float;
19047 
19048 layout (quads, cw, fractional_odd_spacing) in;
19049 
19050 patch in float redValueCS;
19051 
19052 out float redValue;
19053 
19054 void main()
19055 {
19056     gl_Position = vec4(gl_TessCoord.xy * 2. - 1., 0, 1);
19057 
19058     redValue = redValueCS;
19059 }
19060 )";
19061 
19062     constexpr char kFS[] = R"(#version 310 es
19063 precision mediump float;
19064 
19065 out vec4 fragColor;
19066 
19067 in float redValue;
19068 
19069 void main()
19070 {
19071     fragColor = vec4(redValue, 0., 0., 1.);
19072 })";
19073 
19074     ANGLE_GL_PROGRAM_WITH_TESS(unusedProgram, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
19075     ASSERT_GL_NO_ERROR();
19076     // Delete the shader and recompile to fetch from cache.
19077     glDeleteProgram(unusedProgram);
19078     ANGLE_GL_PROGRAM_WITH_TESS(program, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
19079     ASSERT_GL_NO_ERROR();
19080     glUseProgram(program);
19081 
19082     constexpr GLfloat kRedValue = 1.0f;
19083     int redInputLocation        = glGetUniformLocation(program, "redInput");
19084     glUniform1f(redInputLocation, kRedValue);
19085     ASSERT_GL_NO_ERROR();
19086 
19087     drawPatches(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, GL_FALSE);
19088     ASSERT_GL_NO_ERROR();
19089 
19090     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
19091 }
19092 
19093 // Test that shader caching maintains uniform blocks in tessellation control shaders across shader
19094 // compilations.
TEST_P(GLSLTest_ES31,ShaderCacheTessellationControlWithUniformBlock)19095 TEST_P(GLSLTest_ES31, ShaderCacheTessellationControlWithUniformBlock)
19096 {
19097     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
19098     ANGLE_SKIP_TEST_IF(!IsVulkan());
19099 
19100     constexpr char kTCS[] = R"(#version 310 es
19101 #extension GL_EXT_tessellation_shader : require
19102 precision mediump float;
19103 
19104 layout (vertices = 1) out;
19105 
19106 layout (std140) uniform Input {
19107     float redInput;
19108 };
19109 
19110 patch out float redValueCS;
19111 
19112 void main()
19113 {
19114     gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
19115     gl_TessLevelInner[0] = 1.0;
19116     gl_TessLevelInner[1] = 1.0;
19117     gl_TessLevelOuter[0] = 1.0;
19118     gl_TessLevelOuter[1] = 1.0;
19119     gl_TessLevelOuter[2] = 1.0;
19120     gl_TessLevelOuter[3] = 1.0;
19121 
19122     redValueCS = redInput;
19123 }
19124 
19125 )";
19126 
19127     constexpr char kTES[] = R"(#version 310 es
19128 #extension GL_EXT_tessellation_shader : require
19129 precision mediump float;
19130 
19131 layout (quads, cw, fractional_odd_spacing) in;
19132 
19133 patch in float redValueCS;
19134 
19135 out float redValue;
19136 
19137 void main()
19138 {
19139     gl_Position = vec4(gl_TessCoord.xy * 2. - 1., 0, 1);
19140 
19141     redValue = redValueCS;
19142 }
19143 )";
19144 
19145     constexpr char kFS[] = R"(#version 310 es
19146 precision mediump float;
19147 
19148 out vec4 fragColor;
19149 
19150 in float redValue;
19151 
19152 void main()
19153 {
19154     fragColor = vec4(redValue, 0., 0., 1.);
19155 })";
19156 
19157     ANGLE_GL_PROGRAM_WITH_TESS(unusedProgram, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
19158     ASSERT_GL_NO_ERROR();
19159     // Delete the shader and recompile to fetch from cache.
19160     glDeleteProgram(unusedProgram);
19161     ANGLE_GL_PROGRAM_WITH_TESS(program, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
19162     ASSERT_GL_NO_ERROR();
19163     glUseProgram(program);
19164 
19165     constexpr GLfloat kInputData = 1.0f;
19166     GLBuffer input;
19167     glBindBuffer(GL_UNIFORM_BUFFER, input);
19168     glBufferData(GL_UNIFORM_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
19169     const GLuint kInputIndex = glGetUniformBlockIndex(program, "Input");
19170     glUniformBlockBinding(program, kInputIndex, 0);
19171     glBindBufferBase(GL_UNIFORM_BUFFER, 0, input);
19172     glBindBuffer(GL_UNIFORM_BUFFER, 0);
19173     ASSERT_GL_NO_ERROR();
19174 
19175     drawPatches(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, GL_FALSE);
19176     ASSERT_GL_NO_ERROR();
19177 
19178     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
19179 }
19180 
19181 // Test that shader caching maintains SSBOs in tessellation control shaders across shader
19182 // compilations.
TEST_P(GLSLTest_ES31,ShaderCacheTessellationControlWithSSBO)19183 TEST_P(GLSLTest_ES31, ShaderCacheTessellationControlWithSSBO)
19184 {
19185     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
19186     ANGLE_SKIP_TEST_IF(!IsVulkan());
19187     GLint maxTessControlShaderStorageBlocks;
19188     glGetIntegerv(GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS_EXT,
19189                   &maxTessControlShaderStorageBlocks);
19190     ANGLE_SKIP_TEST_IF(maxTessControlShaderStorageBlocks == 0);
19191 
19192     constexpr char kTCS[] = R"(#version 310 es
19193 #extension GL_EXT_tessellation_shader : require
19194 precision mediump float;
19195 
19196 layout (vertices = 1) out;
19197 
19198 layout (binding = 0, std430) buffer Input {
19199     float redInput;
19200 };
19201 
19202 patch out float redValueCS;
19203 
19204 void main()
19205 {
19206     gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
19207     gl_TessLevelInner[0] = 1.0;
19208     gl_TessLevelInner[1] = 1.0;
19209     gl_TessLevelOuter[0] = 1.0;
19210     gl_TessLevelOuter[1] = 1.0;
19211     gl_TessLevelOuter[2] = 1.0;
19212     gl_TessLevelOuter[3] = 1.0;
19213 
19214     redValueCS = redInput;
19215 }
19216 
19217 )";
19218 
19219     constexpr char kTES[] = R"(#version 310 es
19220 #extension GL_EXT_tessellation_shader : require
19221 precision mediump float;
19222 
19223 layout (quads, cw, fractional_odd_spacing) in;
19224 
19225 patch in float redValueCS;
19226 
19227 out float redValue;
19228 
19229 void main()
19230 {
19231     gl_Position = vec4(gl_TessCoord.xy * 2. - 1., 0, 1);
19232 
19233     redValue = redValueCS;
19234 }
19235 )";
19236 
19237     constexpr char kFS[] = R"(#version 310 es
19238 precision mediump float;
19239 
19240 out vec4 fragColor;
19241 
19242 in float redValue;
19243 
19244 void main()
19245 {
19246     fragColor = vec4(redValue, 0., 0., 1.);
19247 })";
19248 
19249     ANGLE_GL_PROGRAM_WITH_TESS(unusedProgram, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
19250     ASSERT_GL_NO_ERROR();
19251     // Delete the shader and recompile to fetch from cache.
19252     glDeleteProgram(unusedProgram);
19253     ANGLE_GL_PROGRAM_WITH_TESS(program, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
19254     ASSERT_GL_NO_ERROR();
19255     glUseProgram(program);
19256 
19257     constexpr GLfloat kInputData = 1.0f;
19258     GLBuffer input;
19259     glBindBuffer(GL_SHADER_STORAGE_BUFFER, input);
19260     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
19261     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, input);
19262     glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
19263     ASSERT_GL_NO_ERROR();
19264 
19265     drawPatches(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, GL_FALSE);
19266     ASSERT_GL_NO_ERROR();
19267 
19268     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
19269 }
19270 
19271 // Test that shader caching maintains uniforms in tessellation evaluation shaders across shader
19272 // compilations.
TEST_P(GLSLTest_ES31,ShaderCacheTessellationEvalWithUniform)19273 TEST_P(GLSLTest_ES31, ShaderCacheTessellationEvalWithUniform)
19274 {
19275     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
19276     ANGLE_SKIP_TEST_IF(!IsVulkan());
19277 
19278     constexpr char kTCS[] = R"(#version 310 es
19279 #extension GL_EXT_tessellation_shader : require
19280 precision mediump float;
19281 
19282 layout (vertices = 1) out;
19283 
19284 void main()
19285 {
19286     gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
19287     gl_TessLevelInner[0] = 1.0;
19288     gl_TessLevelInner[1] = 1.0;
19289     gl_TessLevelOuter[0] = 1.0;
19290     gl_TessLevelOuter[1] = 1.0;
19291     gl_TessLevelOuter[2] = 1.0;
19292     gl_TessLevelOuter[3] = 1.0;
19293 }
19294 
19295 )";
19296 
19297     constexpr char kTES[] = R"(#version 310 es
19298 #extension GL_EXT_tessellation_shader : require
19299 precision mediump float;
19300 
19301 layout (quads, cw, fractional_odd_spacing) in;
19302 
19303 uniform float redInput;
19304 
19305 out float redValue;
19306 
19307 void main()
19308 {
19309     gl_Position = vec4(gl_TessCoord.xy * 2. - 1., 0, 1);
19310 
19311     redValue = redInput;
19312 }
19313 )";
19314 
19315     constexpr char kFS[] = R"(#version 310 es
19316 precision mediump float;
19317 
19318 out vec4 fragColor;
19319 
19320 in float redValue;
19321 
19322 void main()
19323 {
19324     fragColor = vec4(redValue, 0., 0., 1.);
19325 })";
19326 
19327     ANGLE_GL_PROGRAM_WITH_TESS(unusedProgram, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
19328     ASSERT_GL_NO_ERROR();
19329     // Delete the shader and recompile to fetch from cache.
19330     glDeleteProgram(unusedProgram);
19331     ANGLE_GL_PROGRAM_WITH_TESS(program, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
19332     ASSERT_GL_NO_ERROR();
19333     glUseProgram(program);
19334 
19335     constexpr GLfloat kRedValue = 1.0f;
19336     int redInputLocation        = glGetUniformLocation(program, "redInput");
19337     glUniform1f(redInputLocation, kRedValue);
19338     ASSERT_GL_NO_ERROR();
19339 
19340     drawPatches(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, GL_FALSE);
19341     ASSERT_GL_NO_ERROR();
19342 
19343     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
19344 }
19345 
19346 // Test that shader caching maintains uniform blocks in tessellation evaluation shaders across
19347 // shader compilations.
TEST_P(GLSLTest_ES31,ShaderCacheTessellationEvalWithUniformBlock)19348 TEST_P(GLSLTest_ES31, ShaderCacheTessellationEvalWithUniformBlock)
19349 {
19350     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
19351     ANGLE_SKIP_TEST_IF(!IsVulkan());
19352 
19353     constexpr char kTCS[] = R"(#version 310 es
19354 #extension GL_EXT_tessellation_shader : require
19355 precision mediump float;
19356 
19357 layout (vertices = 1) out;
19358 
19359 void main()
19360 {
19361     gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
19362     gl_TessLevelInner[0] = 1.0;
19363     gl_TessLevelInner[1] = 1.0;
19364     gl_TessLevelOuter[0] = 1.0;
19365     gl_TessLevelOuter[1] = 1.0;
19366     gl_TessLevelOuter[2] = 1.0;
19367     gl_TessLevelOuter[3] = 1.0;
19368 }
19369 
19370 )";
19371 
19372     constexpr char kTES[] = R"(#version 310 es
19373 #extension GL_EXT_tessellation_shader : require
19374 precision mediump float;
19375 
19376 layout (quads, cw, fractional_odd_spacing) in;
19377 
19378 layout (std140) uniform Input {
19379     float redInput;
19380 };
19381 
19382 out float redValue;
19383 
19384 void main()
19385 {
19386     gl_Position = vec4(gl_TessCoord.xy * 2. - 1., 0, 1);
19387 
19388     redValue = redInput;
19389 }
19390 )";
19391 
19392     constexpr char kFS[] = R"(#version 310 es
19393 precision mediump float;
19394 
19395 out vec4 fragColor;
19396 
19397 in float redValue;
19398 
19399 void main()
19400 {
19401     fragColor = vec4(redValue, 0., 0., 1.);
19402 })";
19403 
19404     ANGLE_GL_PROGRAM_WITH_TESS(unusedProgram, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
19405     ASSERT_GL_NO_ERROR();
19406     // Delete the shader and recompile to fetch from cache.
19407     glDeleteProgram(unusedProgram);
19408     ANGLE_GL_PROGRAM_WITH_TESS(program, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
19409     ASSERT_GL_NO_ERROR();
19410     glUseProgram(program);
19411 
19412     constexpr GLfloat kInputData = 1.0f;
19413     GLBuffer input;
19414     glBindBuffer(GL_UNIFORM_BUFFER, input);
19415     glBufferData(GL_UNIFORM_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
19416     const GLuint kInputIndex = glGetUniformBlockIndex(program, "Input");
19417     glUniformBlockBinding(program, kInputIndex, 0);
19418     glBindBufferBase(GL_UNIFORM_BUFFER, 0, input);
19419     glBindBuffer(GL_UNIFORM_BUFFER, 0);
19420     ASSERT_GL_NO_ERROR();
19421 
19422     drawPatches(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, GL_FALSE);
19423     ASSERT_GL_NO_ERROR();
19424 
19425     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
19426 }
19427 
19428 // Test that shader caching maintains SSBOs in tessellation evaluation shaders across shader
19429 // compilations.
TEST_P(GLSLTest_ES31,ShaderCacheTessellationEvalWithSSBO)19430 TEST_P(GLSLTest_ES31, ShaderCacheTessellationEvalWithSSBO)
19431 {
19432     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
19433     ANGLE_SKIP_TEST_IF(!IsVulkan());
19434     GLint maxTessEvalShaderStorageBlocks;
19435     glGetIntegerv(GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS_EXT,
19436                   &maxTessEvalShaderStorageBlocks);
19437     ANGLE_SKIP_TEST_IF(maxTessEvalShaderStorageBlocks == 0);
19438 
19439     constexpr char kTCS[] = R"(#version 310 es
19440 #extension GL_EXT_tessellation_shader : require
19441 precision mediump float;
19442 
19443 layout (vertices = 1) out;
19444 
19445 void main()
19446 {
19447     gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
19448     gl_TessLevelInner[0] = 1.0;
19449     gl_TessLevelInner[1] = 1.0;
19450     gl_TessLevelOuter[0] = 1.0;
19451     gl_TessLevelOuter[1] = 1.0;
19452     gl_TessLevelOuter[2] = 1.0;
19453     gl_TessLevelOuter[3] = 1.0;
19454 }
19455 
19456 )";
19457 
19458     constexpr char kTES[] = R"(#version 310 es
19459 #extension GL_EXT_tessellation_shader : require
19460 precision mediump float;
19461 
19462 layout (quads, cw, fractional_odd_spacing) in;
19463 
19464 layout (binding = 0, std430) buffer Input {
19465     float redInput;
19466 };
19467 
19468 out float redValue;
19469 
19470 void main()
19471 {
19472     gl_Position = vec4(gl_TessCoord.xy * 2. - 1., 0, 1);
19473 
19474     redValue = redInput;
19475 }
19476 )";
19477 
19478     constexpr char kFS[] = R"(#version 310 es
19479 precision mediump float;
19480 
19481 out vec4 fragColor;
19482 
19483 in float redValue;
19484 
19485 void main()
19486 {
19487     fragColor = vec4(redValue, 0., 0., 1.);
19488 })";
19489 
19490     ANGLE_GL_PROGRAM_WITH_TESS(unusedProgram, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
19491     ASSERT_GL_NO_ERROR();
19492     // Delete the shader and recompile to fetch from cache.
19493     glDeleteProgram(unusedProgram);
19494     ANGLE_GL_PROGRAM_WITH_TESS(program, essl31_shaders::vs::Simple(), kTCS, kTES, kFS);
19495     ASSERT_GL_NO_ERROR();
19496     glUseProgram(program);
19497 
19498     constexpr GLfloat kInputData = 1.0f;
19499     GLBuffer input;
19500     glBindBuffer(GL_SHADER_STORAGE_BUFFER, input);
19501     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat), &kInputData, GL_STATIC_COPY);
19502     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, input);
19503     glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
19504     ASSERT_GL_NO_ERROR();
19505 
19506     drawPatches(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, GL_FALSE);
19507     ASSERT_GL_NO_ERROR();
19508 
19509     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
19510 }
19511 
19512 // Test that only macros for ESSL 1.0 compatible extensions are defined
TEST_P(GLSLTest,ESSL1ExtensionMacros)19513 TEST_P(GLSLTest, ESSL1ExtensionMacros)
19514 {
19515     std::string fs = essl1_shaders::fs::Red();
19516     fs += ExpectedExtensionMacros({
19517         "GL_ANGLE_multi_draw",
19518         "GL_APPLE_clip_distance",
19519         "GL_ARB_texture_rectangle",
19520         "GL_ARM_shader_framebuffer_fetch",
19521         "GL_EXT_blend_func_extended",
19522         "GL_EXT_draw_buffers",
19523         "GL_EXT_frag_depth",
19524         "GL_EXT_separate_shader_objects",
19525         "GL_EXT_shader_framebuffer_fetch_non_coherent",
19526         "GL_EXT_shader_framebuffer_fetch",
19527         "GL_EXT_shader_non_constant_global_initializers",
19528         "GL_EXT_shader_texture_lod",
19529         "GL_EXT_shadow_samplers",
19530         "GL_KHR_blend_equation_advanced",
19531         "GL_NV_EGL_stream_consumer_external",
19532         "GL_NV_shader_framebuffer_fetch",
19533         "GL_OES_EGL_image_external",
19534         "GL_OES_standard_derivatives",
19535         "GL_OES_texture_3D",
19536         "GL_WEBGL_video_texture",
19537     });
19538     fs += UnexpectedExtensionMacros({
19539         "GL_ANDROID_extension_pack_es31a",
19540         "GL_ANGLE_base_vertex_base_instance_shader_builtin",
19541         "GL_ANGLE_clip_cull_distance",
19542         "GL_ANGLE_shader_pixel_local_storage",
19543         "GL_ANGLE_texture_multisample",
19544         "GL_EXT_clip_cull_distance",
19545         "GL_EXT_geometry_shader",
19546         "GL_EXT_gpu_shader5",
19547         "GL_EXT_primitive_bounding_box",
19548         "GL_EXT_shader_io_blocks",
19549         "GL_EXT_tessellation_shader",
19550         "GL_EXT_texture_buffer",
19551         "GL_EXT_texture_cube_map_array",
19552         "GL_EXT_YUV_target",
19553         "GL_NV_shader_noperspective_interpolation",
19554         "GL_OES_EGL_image_external_essl3",
19555         "GL_OES_geometry_shader",
19556         "GL_OES_primitive_bounding_box",
19557         "GL_OES_sample_variables",
19558         "GL_OES_shader_image_atomic",
19559         "GL_OES_shader_io_blocks",
19560         "GL_OES_shader_multisample_interpolation",
19561         "GL_OES_texture_buffer",
19562         "GL_OES_texture_cube_map_array",
19563         "GL_OES_texture_storage_multisample_2d_array",
19564         "GL_OVR_multiview",
19565         "GL_OVR_multiview2",
19566     });
19567     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), fs.c_str());
19568     ASSERT_GL_NO_ERROR();
19569 }
19570 
19571 // Test that only macros for ESSL 3.0 compatible extensions are defined
TEST_P(GLSLTest_ES3,ESSL3ExtensionMacros)19572 TEST_P(GLSLTest_ES3, ESSL3ExtensionMacros)
19573 {
19574     std::string fs = essl3_shaders::fs::Red();
19575     fs += ExpectedExtensionMacros({
19576         "GL_ANGLE_base_vertex_base_instance_shader_builtin",
19577         "GL_ANGLE_clip_cull_distance",
19578         "GL_ANGLE_multi_draw",
19579         "GL_ANGLE_shader_pixel_local_storage",
19580         "GL_ANGLE_texture_multisample",
19581         "GL_APPLE_clip_distance",
19582         "GL_ARB_texture_rectangle",
19583         "GL_ARM_shader_framebuffer_fetch",
19584         "GL_EXT_blend_func_extended",
19585         "GL_EXT_clip_cull_distance",
19586         "GL_EXT_separate_shader_objects",
19587         "GL_EXT_shader_framebuffer_fetch_non_coherent",
19588         "GL_EXT_shader_framebuffer_fetch",
19589         "GL_EXT_shader_non_constant_global_initializers",
19590         "GL_EXT_YUV_target",
19591         "GL_KHR_blend_equation_advanced",
19592         "GL_NV_EGL_stream_consumer_external",
19593         "GL_NV_shader_noperspective_interpolation",
19594         // Enabled on ESSL 3+ to workaround app bug. http://issuetracker.google.com/285871779
19595         "GL_OES_EGL_image_external",
19596         "GL_OES_EGL_image_external_essl3",
19597         // Enabled on ESSL 3+ to workaround app bug. http://issuetracker.google.com/285871779
19598         "GL_OES_texture_3D",
19599         "GL_OES_sample_variables",
19600         "GL_OES_shader_multisample_interpolation",
19601         // Enabled on ESSL 3+ because ANGLE can support multisample textures with ES 3.0 contexts.
19602         "GL_OES_texture_storage_multisample_2d_array",
19603         "GL_OVR_multiview",
19604         "GL_OVR_multiview2",
19605         "GL_WEBGL_video_texture",
19606     });
19607     fs += UnexpectedExtensionMacros({
19608         "GL_ANDROID_extension_pack_es31a",
19609         "GL_EXT_draw_buffers",
19610         "GL_EXT_frag_depth",
19611         "GL_EXT_geometry_shader",
19612         "GL_EXT_gpu_shader5",
19613         "GL_EXT_primitive_bounding_box",
19614         "GL_EXT_shader_io_blocks",
19615         "GL_EXT_shader_texture_lod",
19616         "GL_EXT_shadow_samplers",
19617         "GL_EXT_tessellation_shader",
19618         "GL_EXT_texture_buffer",
19619         "GL_EXT_texture_cube_map_array",
19620         "GL_NV_shader_framebuffer_fetch",
19621         "GL_OES_geometry_shader",
19622         "GL_OES_primitive_bounding_box",
19623         "GL_OES_shader_image_atomic",
19624         "GL_OES_shader_io_blocks",
19625         "GL_OES_standard_derivatives",
19626         "GL_OES_texture_buffer",
19627         "GL_OES_texture_cube_map_array",
19628     });
19629     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fs.c_str());
19630     ASSERT_GL_NO_ERROR();
19631 }
19632 
19633 // Test that only macros for ESSL 3.1 compatible extensions are defined
TEST_P(GLSLTest_ES31,ESSL31ExtensionMacros)19634 TEST_P(GLSLTest_ES31, ESSL31ExtensionMacros)
19635 {
19636     std::string fs = essl31_shaders::fs::Red();
19637     fs += ExpectedExtensionMacros({
19638         "GL_ANDROID_extension_pack_es31a",
19639         "GL_ANGLE_base_vertex_base_instance_shader_builtin",
19640         "GL_ANGLE_clip_cull_distance",
19641         "GL_ANGLE_multi_draw",
19642         "GL_ANGLE_shader_pixel_local_storage",
19643         "GL_ANGLE_texture_multisample",
19644         "GL_APPLE_clip_distance",
19645         "GL_ARB_texture_rectangle",
19646         "GL_ARM_shader_framebuffer_fetch",
19647         "GL_EXT_blend_func_extended",
19648         "GL_EXT_clip_cull_distance",
19649         "GL_EXT_geometry_shader",
19650         "GL_EXT_gpu_shader5",
19651         "GL_EXT_primitive_bounding_box",
19652         "GL_EXT_separate_shader_objects",
19653         "GL_EXT_shader_framebuffer_fetch_non_coherent",
19654         "GL_EXT_shader_framebuffer_fetch",
19655         "GL_EXT_shader_io_blocks",
19656         "GL_EXT_shader_non_constant_global_initializers",
19657         "GL_EXT_tessellation_shader",
19658         "GL_EXT_texture_buffer",
19659         "GL_EXT_texture_cube_map_array",
19660         "GL_EXT_YUV_target",
19661         "GL_KHR_blend_equation_advanced",
19662         "GL_NV_EGL_stream_consumer_external",
19663         "GL_NV_shader_noperspective_interpolation",
19664         // Enabled on ESSL 3+ to workaround app bug. http://issuetracker.google.com/285871779
19665         "GL_OES_EGL_image_external",
19666         "GL_OES_EGL_image_external_essl3",
19667         // Enabled on ESSL 3+ to workaround app bug. http://issuetracker.google.com/285871779
19668         "GL_OES_texture_3D",
19669         "GL_OES_geometry_shader",
19670         "GL_OES_primitive_bounding_box",
19671         "GL_OES_sample_variables",
19672         "GL_OES_shader_image_atomic",
19673         "GL_OES_shader_io_blocks",
19674         "GL_OES_shader_multisample_interpolation",
19675         "GL_OES_texture_buffer",
19676         "GL_OES_texture_cube_map_array",
19677         "GL_OES_texture_storage_multisample_2d_array",
19678         "GL_OVR_multiview",
19679         "GL_OVR_multiview2",
19680         "GL_WEBGL_video_texture",
19681     });
19682     fs += UnexpectedExtensionMacros({
19683         "GL_EXT_draw_buffers",
19684         "GL_EXT_frag_depth",
19685         "GL_EXT_shader_texture_lod",
19686         "GL_EXT_shadow_samplers",
19687         "GL_NV_shader_framebuffer_fetch",
19688         "GL_OES_standard_derivatives",
19689     });
19690     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), fs.c_str());
19691     ASSERT_GL_NO_ERROR();
19692 }
19693 
19694 // Make sure names starting with webgl_ work.
TEST_P(GLSLTest_ES3,NameWithWebgl)19695 TEST_P(GLSLTest_ES3, NameWithWebgl)
19696 {
19697     constexpr char kFS[] = R"(#version 300 es
19698 out highp vec4 webgl_color;
19699 void main()
19700 {
19701   webgl_color = vec4(0, 1, 0, 1);
19702 })";
19703 
19704     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
19705     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
19706     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
19707 }
19708 
19709 // Make sure webgl_FragColor works.
TEST_P(GLSLTest_ES3,NameWithWebglFragColor)19710 TEST_P(GLSLTest_ES3, NameWithWebglFragColor)
19711 {
19712     constexpr char kFS[] = R"(#version 300 es
19713 out highp vec4 webgl_FragColor;
19714 void main()
19715 {
19716   webgl_FragColor = vec4(0, 1, 0, 1);
19717 })";
19718 
19719     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
19720     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
19721     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
19722 }
19723 
19724 // Test that the ScalarizeVecAndMatConstructorArgs workaround works correctly with constructors that
19725 // have no precision.  Regression test for a bug where the generated helper has no precision
19726 // specified on the parameters and return value.
TEST_P(GLSLTest,ScalarizeVectorWorkaroundVsPrecisionlessConstructor)19727 TEST_P(GLSLTest, ScalarizeVectorWorkaroundVsPrecisionlessConstructor)
19728 {
19729     constexpr char kFS[] = R"(precision highp float;
19730 void main() {
19731     bool b1 = true;
19732     float f1 = dot(vec4(b1 ? 1.0 : 0.0, 0.0, 0.0, 0.0), vec4(1.0));
19733     gl_FragColor = vec4(f1,0.0,0.0, 1.0);
19734 })";
19735 
19736     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
19737     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
19738     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
19739 }
19740 
19741 // Test that Metal compiler doesn't inline non-const globals
TEST_P(WebGLGLSLTest,InvalidGlobalsNotInlined)19742 TEST_P(WebGLGLSLTest, InvalidGlobalsNotInlined)
19743 {
19744     constexpr char kFS[] = R"(#version 100
19745   precision highp float;
19746   float v1 = 0.5;
19747   float v2 = v1;
19748 
19749   float f1() {
19750     return v2;
19751   }
19752 
19753   void main() {
19754     gl_FragColor = vec4(v1 + f1(),0.0,0.0, 1.0);
19755   })";
19756     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
19757     ASSERT_GL_NO_ERROR();
19758 }
19759 
19760 // Test that a struct can have lots of fields.  Regression test for an inefficient O(n^2) check for
19761 // fields having unique names.
TEST_P(GLSLTest_ES3,LotsOfFieldsInStruct)19762 TEST_P(GLSLTest_ES3, LotsOfFieldsInStruct)
19763 {
19764     std::ostringstream fs;
19765     fs << R"(#version 300 es
19766 precision highp float;
19767 struct LotsOfFields
19768 {
19769 )";
19770     // Note: 16383 is the SPIR-V limit for struct member count.
19771     for (uint32_t i = 0; i < 16383; ++i)
19772     {
19773         fs << "    float field" << i << ";\n";
19774     }
19775     fs << R"(};
19776 uniform B { LotsOfFields s; };
19777 out vec4 color;
19778 void main() {
19779     color = vec4(s.field0, 0.0, 0.0, 1.0);
19780 })";
19781 
19782     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fs.str().c_str());
19783 }
19784 
19785 // Test that structs with too many fields are rejected.  In SPIR-V, the instruction that defines the
19786 // struct lists the fields which means the length of the instruction is a function of the field
19787 // count.  Since SPIR-V instruction sizes are limited to 16 bits, structs with more fields cannot be
19788 // represented.
TEST_P(GLSLTest_ES3,TooManyFieldsInStruct)19789 TEST_P(GLSLTest_ES3, TooManyFieldsInStruct)
19790 {
19791     std::ostringstream fs;
19792     fs << R"(#version 300 es
19793 precision highp float;
19794 struct TooManyFields
19795 {
19796 )";
19797     for (uint32_t i = 0; i < (1 << 16); ++i)
19798     {
19799         fs << "    float field" << i << ";\n";
19800     }
19801     fs << R"(};
19802 uniform B { TooManyFields s; };
19803 out vec4 color;
19804 void main() {
19805     color = vec4(s.field0, 0.0, 0.0, 1.0);
19806 })";
19807 
19808     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, fs.str().c_str());
19809     EXPECT_EQ(0u, shader);
19810 }
19811 
19812 // Same as TooManyFieldsInStruct, but with samplers in the struct.
TEST_P(GLSLTest_ES3,TooManySamplerFieldsInStruct)19813 TEST_P(GLSLTest_ES3, TooManySamplerFieldsInStruct)
19814 {
19815     std::ostringstream fs;
19816     fs << R"(#version 300 es
19817 precision highp float;
19818 struct TooManyFields
19819 {
19820 )";
19821     for (uint32_t i = 0; i < (1 << 16); ++i)
19822     {
19823         fs << "    sampler2D field" << i << ";\n";
19824     }
19825     fs << R"(};
19826 uniform TooManyFields s;
19827 out vec4 color;
19828 void main() {
19829     color = texture(s.field0, vec2(0));
19830 })";
19831 
19832     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, fs.str().c_str());
19833     EXPECT_EQ(0u, shader);
19834 }
19835 
19836 // More complex variation of ManySamplerFieldsInStruct.  This one compiles fine.
TEST_P(GLSLTest_ES3,ManySamplerFieldsInStructComplex)19837 TEST_P(GLSLTest_ES3, ManySamplerFieldsInStructComplex)
19838 {
19839     // D3D and OpenGL may be more restrictive about this many samplers.
19840     ANGLE_SKIP_TEST_IF(IsD3D() || IsOpenGL());
19841 
19842     std::ostringstream fs;
19843     fs << R"(#version 300 es
19844 precision highp float;
19845 
19846 struct X {
19847     mediump sampler2D a[0xf00];
19848     mediump sampler2D b[0xf00];
19849     mediump sampler2D c[0xf000];
19850     mediump sampler2D d[0xf00];
19851 };
19852 
19853 struct Y {
19854   X s1;
19855   mediump sampler2D a[0xf00];
19856   mediump sampler2D b[0xf000];
19857   mediump sampler2D c[0x14000];
19858 };
19859 
19860 struct S {
19861     Y s1;
19862 };
19863 
19864 struct structBuffer { S s; };
19865 
19866 uniform structBuffer b;
19867 
19868 out vec4 color;
19869 void main()
19870 {
19871     color = texture(b.s.s1.s1.c[0], vec2(0));
19872 })";
19873 
19874     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, fs.str().c_str());
19875     EXPECT_NE(0u, shader);
19876 }
19877 
19878 // Make sure a large array of samplers works.
TEST_P(GLSLTest,ManySamplers)19879 TEST_P(GLSLTest, ManySamplers)
19880 {
19881     // D3D and OpenGL may be more restrictive about this many samplers.
19882     ANGLE_SKIP_TEST_IF(IsD3D() || IsOpenGL());
19883 
19884     std::ostringstream fs;
19885     fs << R"(precision highp float;
19886 
19887 uniform mediump sampler2D c[0x12000];
19888 
19889 void main()
19890 {
19891     gl_FragColor = texture2D(c[0], vec2(0));
19892 })";
19893 
19894     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, fs.str().c_str());
19895     EXPECT_NE(0u, shader);
19896 }
19897 
19898 // Make sure a large array of samplers works when declared in a struct.
TEST_P(GLSLTest,ManySamplersInStruct)19899 TEST_P(GLSLTest, ManySamplersInStruct)
19900 {
19901     // D3D and OpenGL may be more restrictive about this many samplers.
19902     ANGLE_SKIP_TEST_IF(IsD3D() || IsOpenGL());
19903 
19904     std::ostringstream fs;
19905     fs << R"(precision highp float;
19906 
19907 struct X {
19908     mediump sampler2D c[0x12000];
19909 };
19910 
19911 uniform X x;
19912 
19913 void main()
19914 {
19915     gl_FragColor = texture2D(x.c[0], vec2(0));
19916 })";
19917 
19918     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, fs.str().c_str());
19919     EXPECT_NE(0u, shader);
19920 }
19921 
19922 // Test that passing large arrays to functions are compiled correctly.  Regression test for the
19923 // SPIR-V generator that made a copy of the array to pass to the function, by decomposing and
19924 // reconstructing it (in the absence of OpCopyLogical), but the reconstruction instruction has a
19925 // length higher than can fit in SPIR-V.
TEST_P(GLSLTest_ES3,LargeInterfaceBlockArrayPassedToFunction)19926 TEST_P(GLSLTest_ES3, LargeInterfaceBlockArrayPassedToFunction)
19927 {
19928     constexpr char kFS[] = R"(#version 300 es
19929 precision highp float;
19930 uniform Large { float a[65536]; };
19931 float f(float b[65536])
19932 {
19933     b[0] = 1.0;
19934     return b[0] + b[1];
19935 }
19936 out vec4 color;
19937 void main() {
19938     color = vec4(f(a), 0.0, 0.0, 1.0);
19939 })";
19940 
19941     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
19942     EXPECT_EQ(0u, shader);
19943 }
19944 
19945 // Make sure the shader in LargeInterfaceBlockArrayPassedToFunction works if the large local is
19946 // avoided.
TEST_P(GLSLTest_ES3,LargeInterfaceBlockArray)19947 TEST_P(GLSLTest_ES3, LargeInterfaceBlockArray)
19948 {
19949     int maxUniformBlockSize = 0;
19950     glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &maxUniformBlockSize);
19951     ANGLE_SKIP_TEST_IF(maxUniformBlockSize < 16384 * 4);
19952 
19953     constexpr char kFS[] = R"(#version 300 es
19954 precision highp float;
19955 uniform Large { float a[16384]; };
19956 out vec4 color;
19957 void main() {
19958     color = vec4(a[0], 0.0, 0.0, 1.0);
19959 })";
19960 
19961     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
19962 }
19963 
19964 // Similar to LargeInterfaceBlockArrayPassedToFunction, but the array is nested in a struct.
TEST_P(GLSLTest_ES3,LargeInterfaceBlockNestedArrayPassedToFunction)19965 TEST_P(GLSLTest_ES3, LargeInterfaceBlockNestedArrayPassedToFunction)
19966 {
19967     constexpr char kFS[] = R"(#version 300 es
19968 precision highp float;
19969 struct S { float a[65536]; };
19970 uniform Large { S s; };
19971 float f(float b[65536])
19972 {
19973     b[0] = 1.0;
19974     return b[0] + b[1];
19975 }
19976 out vec4 color;
19977 void main() {
19978     color = vec4(f(s.a), 0.0, 0.0, 1.0);
19979 })";
19980 
19981     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
19982     EXPECT_EQ(0u, shader);
19983 }
19984 
19985 // Make sure the shader in LargeInterfaceBlockNestedArrayPassedToFunction works if the large local
19986 // is avoided.
TEST_P(GLSLTest_ES3,LargeInterfaceBlockNestedArray)19987 TEST_P(GLSLTest_ES3, LargeInterfaceBlockNestedArray)
19988 {
19989     int maxUniformBlockSize = 0;
19990     glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &maxUniformBlockSize);
19991     ANGLE_SKIP_TEST_IF(maxUniformBlockSize < 16384 * 4);
19992 
19993     constexpr char kFS[] = R"(#version 300 es
19994 precision highp float;
19995 struct S { float a[16384]; };
19996 uniform Large { S s; };
19997 out vec4 color;
19998 void main() {
19999     color = vec4(s.a[0], 0.0, 0.0, 1.0);
20000 })";
20001 
20002     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
20003 }
20004 
20005 // Similar to LargeInterfaceBlockArrayPassedToFunction, but the large array is copied to a local
20006 // variable instead.
TEST_P(GLSLTest_ES3,LargeInterfaceBlockArrayCopiedToLocal)20007 TEST_P(GLSLTest_ES3, LargeInterfaceBlockArrayCopiedToLocal)
20008 {
20009     constexpr char kFS[] = R"(#version 300 es
20010 precision highp float;
20011 uniform Large { float a[65536]; };
20012 out vec4 color;
20013 void main() {
20014     float b[65536] = a;
20015     color = vec4(b[0], 0.0, 0.0, 1.0);
20016 })";
20017 
20018     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
20019     EXPECT_EQ(0u, shader);
20020 }
20021 
20022 // Similar to LargeInterfaceBlockArrayCopiedToLocal, but the array is nested in a struct
TEST_P(GLSLTest_ES3,LargeInterfaceBlockNestedArrayCopiedToLocal)20023 TEST_P(GLSLTest_ES3, LargeInterfaceBlockNestedArrayCopiedToLocal)
20024 {
20025     constexpr char kFS[] = R"(#version 300 es
20026 precision highp float;
20027 struct S { float a[65536]; };
20028 uniform Large { S s; };
20029 out vec4 color;
20030 void main() {
20031     S s2 = s;
20032     color = vec4(s2.a[0], 0.0, 0.0, 1.0);
20033 })";
20034 
20035     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
20036     EXPECT_EQ(0u, shader);
20037 }
20038 
20039 // Test that too large varyings are rejected.
TEST_P(GLSLTest_ES3,LargeArrayVarying)20040 TEST_P(GLSLTest_ES3, LargeArrayVarying)
20041 {
20042     constexpr char kFS[] = R"(#version 300 es
20043 precision highp float;
20044 in float a[65536];
20045 out vec4 color;
20046 void main() {
20047     color = vec4(a[0], 0.0, 0.0, 1.0);
20048 })";
20049 
20050     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
20051     EXPECT_EQ(0u, shader);
20052 }
20053 
20054 // Regression test for const globals losing const qualifiers during MSL
20055 // translation and exceeding available temporary registers on Apple GPUs.
TEST_P(GLSLTest_ES3,LargeConstGlobalArraysOfStructs)20056 TEST_P(GLSLTest_ES3, LargeConstGlobalArraysOfStructs)
20057 {
20058     const int n = 128;
20059     std::stringstream fragmentShader;
20060     fragmentShader << "#version 300 es\n"
20061                    << "precision mediump float;\n"
20062                    << "uniform mediump int zero;\n"
20063                    << "out vec4 color;\n"
20064                    << "struct S { vec3 A; vec3 B; float C; };\n";
20065     for (int i = 0; i < 3; ++i)
20066     {
20067         fragmentShader << "const S s" << i << "[" << n << "] = S[" << n << "](\n";
20068         for (int j = 0; j < n; ++j)
20069         {
20070             fragmentShader << "  S(vec3(0., 1., 0.), vec3(" << j << "), 0.)"
20071                            << (j != n - 1 ? ",\n" : "\n");
20072         }
20073         fragmentShader << ");\n";
20074     }
20075     // To ensure that the array is not rescoped, it must be accessed from two functions.
20076     // To ensure that the array is not optimized out, it must be accessed with a dynamic index.
20077     fragmentShader << "vec4 foo() {\n"
20078                    << "  return vec4(s0[zero].A * s1[zero].A * s2[zero].A, 1.0);\n"
20079                    << "}\n"
20080                    << "void main() {\n"
20081                    << "  color = foo() * vec4(s0[zero].A * s1[zero].A * s2[zero].A, 1.0);\n"
20082                    << "}\n";
20083     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fragmentShader.str().c_str());
20084 
20085     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
20086     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
20087     ASSERT_GL_NO_ERROR();
20088 }
20089 
20090 // Test that framebuffer fetch emulation does not add a user-visible uniform.
TEST_P(GLSLTest,FramebufferFetchDoesNotAddUniforms)20091 TEST_P(GLSLTest, FramebufferFetchDoesNotAddUniforms)
20092 {
20093     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch"));
20094     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_draw_buffers"));
20095 
20096     static constexpr char kFS[] = R"(#version 100
20097 #extension GL_EXT_shader_framebuffer_fetch : require
20098 #extension GL_EXT_draw_buffers : require
20099 uniform highp vec4 u_color;
20100 
20101 void main (void)
20102 {
20103     gl_FragData[0] = gl_LastFragData[0] + u_color;
20104     gl_FragData[1] = gl_LastFragData[1] + u_color;
20105     gl_FragData[2] = gl_LastFragData[2] + u_color;
20106     gl_FragData[3] = gl_LastFragData[3] + u_color;
20107 })";
20108 
20109     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
20110     glUseProgram(program);
20111 
20112     GLint activeUniforms = 0, uniformsMaxLength = 0;
20113     glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &activeUniforms);
20114     glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &uniformsMaxLength);
20115 
20116     // There should be only one active uniform
20117     EXPECT_EQ(activeUniforms, 1);
20118 
20119     // And that is u_color
20120     GLsizei nameLen = uniformsMaxLength;
20121     std::vector<char> name(uniformsMaxLength);
20122 
20123     GLint size;
20124     GLenum type;
20125 
20126     glGetActiveUniform(program, 0, uniformsMaxLength, &nameLen, &size, &type, name.data());
20127     EXPECT_EQ(std::string(name.data()), "u_color");
20128     EXPECT_EQ(size, 1);
20129     EXPECT_EQ(type, static_cast<GLenum>(GL_FLOAT_VEC4));
20130 }
20131 
20132 // Test that framebuffer fetch emulation does not add a user-visible uniform.
TEST_P(GLSLTest_ES31,FramebufferFetchDoesNotAddUniforms)20133 TEST_P(GLSLTest_ES31, FramebufferFetchDoesNotAddUniforms)
20134 {
20135     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch"));
20136 
20137     static constexpr char kFS[] = R"(#version 310 es
20138 #extension GL_EXT_shader_framebuffer_fetch : require
20139 layout(location = 0) inout highp vec4 o_color;
20140 
20141 layout(std140, binding = 0) buffer outBlock {
20142     highp vec4 data[256];
20143 };
20144 
20145 uniform highp vec4 u_color;
20146 void main (void)
20147 {
20148     uint index = uint(gl_FragCoord.y) * 16u + uint(gl_FragCoord.x);
20149     data[index] = o_color;
20150     o_color += u_color;
20151 })";
20152 
20153     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
20154     glUseProgram(program);
20155 
20156     GLint activeUniforms = 0, uniformsMaxLength = 0;
20157     glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &activeUniforms);
20158     glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &uniformsMaxLength);
20159 
20160     // There should be only one active uniform
20161     EXPECT_EQ(activeUniforms, 1);
20162 
20163     // And that is u_color
20164     GLsizei nameLen = uniformsMaxLength;
20165     std::vector<char> name(uniformsMaxLength);
20166 
20167     GLint size;
20168     GLenum type;
20169 
20170     glGetActiveUniform(program, 0, uniformsMaxLength, &nameLen, &size, &type, name.data());
20171     EXPECT_EQ(std::string(name.data()), "u_color");
20172     EXPECT_EQ(size, 1);
20173     EXPECT_EQ(type, static_cast<GLenum>(GL_FLOAT_VEC4));
20174 }
20175 
20176 // Test that advanced blend emulation does not add a user-visible uniform.
TEST_P(GLSLTest_ES31,AdvancedBlendEquationsDoesNotAddUniforms)20177 TEST_P(GLSLTest_ES31, AdvancedBlendEquationsDoesNotAddUniforms)
20178 {
20179     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_KHR_blend_equation_advanced"));
20180 
20181     static constexpr char kFS[] = R"(#version 310 es
20182 #extension GL_KHR_blend_equation_advanced : require
20183 
20184 layout (blend_support_multiply) out;
20185 
20186 out highp vec4 o_color;
20187 
20188 layout(std140, binding = 0) buffer outBlock {
20189     highp vec4 data[256];
20190 };
20191 
20192 uniform highp vec4 u_color;
20193 void main (void)
20194 {
20195     o_color = u_color;
20196 })";
20197 
20198     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
20199     glUseProgram(program);
20200 
20201     GLint activeUniforms = 0, uniformsMaxLength = 0;
20202     glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &activeUniforms);
20203     glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &uniformsMaxLength);
20204 
20205     // There should be only one active uniform
20206     EXPECT_EQ(activeUniforms, 1);
20207 
20208     // And that is u_color
20209     GLsizei nameLen = uniformsMaxLength;
20210     std::vector<char> name(uniformsMaxLength);
20211 
20212     GLint size;
20213     GLenum type;
20214 
20215     glGetActiveUniform(program, 0, uniformsMaxLength, &nameLen, &size, &type, name.data());
20216     EXPECT_EQ(std::string(name.data()), "u_color");
20217     EXPECT_EQ(size, 1);
20218     EXPECT_EQ(type, static_cast<GLenum>(GL_FLOAT_VEC4));
20219 }
20220 
20221 // Tests struct in function return type.
TEST_P(GLSLTest,StructInFunctionDefinition)20222 TEST_P(GLSLTest, StructInFunctionDefinition)
20223 {
20224     const char kFragmentShader[] = R"(precision mediump float;
20225 struct Foo
20226 {
20227     float v;
20228 };
20229 
20230 Foo foo()
20231 {
20232     Foo f;
20233     f.v = 0.5;
20234     return f;
20235 }
20236 
20237 void main()
20238 {
20239     gl_FragColor = vec4(1, 0, 0, 1);
20240     Foo f = foo();
20241     if (f.v == 0.5)
20242     {
20243         gl_FragColor = vec4(0, 1, 0, 1);
20244     }
20245 })";
20246 
20247     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
20248     glUseProgram(program);
20249 
20250     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
20251     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
20252 }
20253 
20254 // Tests struct definition in function return type.
TEST_P(GLSLTest,StructDefinitionInFunctionDefinition)20255 TEST_P(GLSLTest, StructDefinitionInFunctionDefinition)
20256 {
20257     const char kFragmentShader[] = R"(precision mediump float;
20258 struct Foo { float v; } foo()
20259 {
20260     Foo f;
20261     f.v = 0.5;
20262     return f;
20263 }
20264 
20265 void main()
20266 {
20267     gl_FragColor = vec4(1, 0, 0, 1);
20268     Foo f = foo();
20269     if (f.v == 0.5)
20270     {
20271         gl_FragColor = vec4(0, 1, 0, 1);
20272     }
20273 })";
20274 
20275     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
20276     glUseProgram(program);
20277 
20278     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
20279     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
20280 }
20281 
20282 // Test struct definition in forward declaration of function return type.
TEST_P(GLSLTest,StructDefinitionInFunctionPrototype)20283 TEST_P(GLSLTest, StructDefinitionInFunctionPrototype)
20284 {
20285     const char kFragmentShader[] = R"(precision mediump float;
20286 struct Foo { float v; } foo();
20287 
20288 void main()
20289 {
20290     gl_FragColor = vec4(1, 0, 0, 1);
20291     Foo f = foo();
20292     if (f.v == 0.5)
20293     {
20294         gl_FragColor = vec4(0, 1, 0, 1);
20295     }
20296 }
20297 
20298 Foo foo()
20299 {
20300     Foo f;
20301     f.v = 0.5;
20302     return f;
20303 })";
20304 
20305     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
20306     glUseProgram(program);
20307 
20308     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
20309     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
20310 }
20311 
20312 // Test that struct declarations are introduced into the correct scope.
TEST_P(GLSLTest,StructDefinitionInFunctionPrototypeScope)20313 TEST_P(GLSLTest, StructDefinitionInFunctionPrototypeScope)
20314 {
20315     const char kFragmentShader[] = R"(precision mediump float;
20316 
20317 struct Foo { float v; } foo()
20318 {
20319     Foo f;
20320     f.v = 0.5;
20321     return f;
20322 }
20323 
20324 struct Bar { Foo f; } bar()
20325 {
20326     Bar b;
20327     b.f = foo();
20328     return b;
20329 }
20330 
20331 void main()
20332 {
20333     gl_FragColor = vec4(1, 0, 0, 1);
20334     Bar b = bar();
20335     if (b.f.v == 0.5)
20336     {
20337         gl_FragColor = vec4(0, 1, 0, 1);
20338     }
20339 })";
20340 
20341     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
20342     glUseProgram(program);
20343 
20344     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
20345     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
20346 }
20347 
20348 // Test that struct declarations are introduced into the correct scope.
TEST_P(GLSLTest,NestedReturnedStructs)20349 TEST_P(GLSLTest, NestedReturnedStructs)
20350 {
20351     const char kFragmentShader[] = R"(precision mediump float;
20352 struct Foo { float v; } foo(float bar);
20353 
20354 void main()
20355 {
20356     gl_FragColor = vec4(1, 0, 0, 1);
20357     float v = foo(foo(0.5).v).v;
20358     if (v == 0.5)
20359     {
20360         gl_FragColor = vec4(0, 1, 0, 1);
20361     }
20362 }
20363 
20364 Foo foo(float bar)
20365 {
20366     Foo f;
20367     f.v = bar;
20368     return f;
20369 })";
20370 
20371     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
20372     glUseProgram(program);
20373 
20374     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
20375     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
20376 }
20377 
20378 // Test that vec equality works.
TEST_P(GLSLTest,VecEquality)20379 TEST_P(GLSLTest, VecEquality)
20380 {
20381     const char kFragmentShader[] = R"(precision mediump float;
20382 uniform vec4 u;
20383 void main()
20384 {
20385     gl_FragColor = vec4(0, 0, 0, 1);
20386     vec4 a = vec4(1.0, 2.0, 3.0, 4.0);
20387     if (a == u)
20388         gl_FragColor.g = 1.0;
20389 
20390     vec4 b = vec4(1.0) + u;
20391     if (b == u)
20392         gl_FragColor.r = 1.0;
20393 }
20394 )";
20395 
20396     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
20397     glUseProgram(program);
20398     GLint u = glGetUniformLocation(program, "u");
20399     glUniform4f(u, 1, 2, 3, 4);
20400 
20401     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
20402     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
20403 }
20404 
20405 // Test that mat equality works.
TEST_P(GLSLTest,MatEquality)20406 TEST_P(GLSLTest, MatEquality)
20407 {
20408     const char kFragmentShader[] = R"(precision mediump float;
20409 uniform vec4 u;
20410 void main()
20411 {
20412     gl_FragColor = vec4(0, 0, 0, 1);
20413     mat4 a = mat4(1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4);
20414     if (a == mat4(u, u, u, u))
20415         gl_FragColor.g = 1.0;
20416     mat4 b = mat4(1.0);
20417     if (b == mat4(u, u, u, u))
20418         gl_FragColor.r = 1.0;
20419 }
20420 )";
20421 
20422     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
20423     glUseProgram(program);
20424     GLint u = glGetUniformLocation(program, "u");
20425     glUniform4f(u, 1, 2, 3, 4);
20426 
20427     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
20428     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
20429 }
20430 
20431 // Test that struct equality works.
TEST_P(GLSLTest,StructEquality)20432 TEST_P(GLSLTest, StructEquality)
20433 {
20434     const char kFragmentShader[] = R"(precision mediump float;
20435 uniform vec4 u;
20436 struct A {
20437     vec4 i;
20438 };
20439 void main()
20440 {
20441     gl_FragColor = vec4(0, 0, 0, 1);
20442     A a, b;
20443     a.i = vec4(1,2,3,4);
20444     b.i = u;
20445     if (a == b)
20446         gl_FragColor.g = 1.0;
20447     b.i = vec4(1.0);
20448     if (a == b)
20449         gl_FragColor.r = 1.0;
20450 }
20451 )";
20452     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
20453     glUseProgram(program);
20454     GLint u = glGetUniformLocation(program, "u");
20455     glUniform4f(u, 1, 2, 3, 4);
20456 
20457     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
20458     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
20459 }
20460 
20461 // Test that nested struct equality works.
TEST_P(GLSLTest,NestedStructEquality)20462 TEST_P(GLSLTest, NestedStructEquality)
20463 {
20464     const char kFragmentShader[] = R"(precision mediump float;
20465 uniform vec4 u;
20466 struct A {
20467     vec4 i;
20468 };
20469 struct B {
20470     A a;
20471 };
20472 void main()
20473 {
20474     gl_FragColor = vec4(0, 0, 0, 1);
20475     B a, b;
20476     a.a.i = vec4(1,2,3,4);
20477     b.a.i = u;
20478     if (a == b)
20479         gl_FragColor.g = 1.0;
20480     b.a.i = vec4(1.0);
20481     if (a == b)
20482         gl_FragColor.r = 1.0;
20483 }
20484 )";
20485     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragmentShader);
20486     glUseProgram(program);
20487     GLint u = glGetUniformLocation(program, "u");
20488     glUniform4f(u, 1, 2, 3, 4);
20489 
20490     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
20491     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
20492 }
20493 
20494 // Test that double underscores user defined name is allowed
TEST_P(GLSLTest_ES3,DoubleUnderscoresName)20495 TEST_P(GLSLTest_ES3, DoubleUnderscoresName)
20496 {
20497     constexpr char kFS[] = R"(#version 300 es
20498 precision mediump float;
20499 out vec4 oColor;
20500 uniform struct __Data {float red;} data;
20501 void main() {oColor=vec4(data.red,0,1,1);})";
20502 
20503     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
20504     glUseProgram(program);
20505     // populate uniform
20506     GLint uniformLocation = glGetUniformLocation(program, "data.red");
20507     EXPECT_NE(uniformLocation, -1);
20508     glUniform1f(uniformLocation, 0);
20509 
20510     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
20511     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
20512     ASSERT_GL_NO_ERROR();
20513 }
20514 
20515 // Test that user defined name starts with "ANGLE" or "ANGLE_"
TEST_P(GLSLTest_ES3,VariableNameStartsWithANGLE)20516 TEST_P(GLSLTest_ES3, VariableNameStartsWithANGLE)
20517 {
20518     constexpr char kFS[] = R"(#version 300 es
20519 precision mediump float;
20520 out vec4 oColor;
20521 uniform struct ANGLEData{float red;} data;
20522 uniform struct ANGLE_Data{float green;} _data;
20523 void main() {oColor=vec4(data.red,_data.green,1,1);})";
20524 
20525     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
20526     glUseProgram(program);
20527     // populate uniform
20528     GLint uniformRedLocation   = glGetUniformLocation(program, "data.red");
20529     GLint uniformGreenLocation = glGetUniformLocation(program, "_data.green");
20530     EXPECT_NE(uniformRedLocation, -1);
20531     EXPECT_NE(uniformGreenLocation, -1);
20532     glUniform1f(uniformRedLocation, 0);
20533     glUniform1f(uniformGreenLocation, 0);
20534 
20535     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
20536     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
20537     ASSERT_GL_NO_ERROR();
20538 }
20539 
20540 // Test that underscores in array names work with out arrays.
TEST_P(GLSLTest_ES3,UnderscoresWorkWithOutArrays)20541 TEST_P(GLSLTest_ES3, UnderscoresWorkWithOutArrays)
20542 {
20543     GLuint fbo;
20544     glGenFramebuffers(1, &fbo);
20545     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
20546 
20547     GLuint textures[4];
20548     glGenTextures(4, textures);
20549 
20550     for (size_t texIndex = 0; texIndex < ArraySize(textures); texIndex++)
20551     {
20552         glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
20553         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
20554                      GL_UNSIGNED_BYTE, nullptr);
20555     }
20556 
20557     GLint maxDrawBuffers;
20558     glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
20559     ASSERT_GE(maxDrawBuffers, 4);
20560 
20561     GLuint readFramebuffer;
20562     glGenFramebuffers(1, &readFramebuffer);
20563     glBindFramebuffer(GL_READ_FRAMEBUFFER, readFramebuffer);
20564 
20565     constexpr char kFS[] = R"(#version 300 es
20566 precision highp float;
20567 out vec4 _e[4];
20568 void main()
20569 {
20570     _e[0] = vec4(1.0, 0.0, 0.0, 1.0);
20571     _e[1] = vec4(0.0, 1.0, 0.0, 1.0);
20572     _e[2] = vec4(0.0, 0.0, 1.0, 1.0);
20573     _e[3] = vec4(1.0, 1.0, 1.0, 1.0);
20574 }
20575 )";
20576     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
20577     GLenum allBufs[4] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2,
20578                          GL_COLOR_ATTACHMENT3};
20579     constexpr GLuint kMaxBuffers = 4;
20580     // Enable all draw buffers.
20581     for (GLuint texIndex = 0; texIndex < kMaxBuffers; texIndex++)
20582     {
20583         glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
20584         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
20585                                textures[texIndex], 0);
20586         glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
20587                                textures[texIndex], 0);
20588     }
20589     glDrawBuffers(kMaxBuffers, allBufs);
20590 
20591     // Draw with simple program.
20592     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
20593     ASSERT_GL_NO_ERROR();
20594     verifyAttachment2DColor(0, textures[0], GL_TEXTURE_2D, 0, GLColor::red);
20595     verifyAttachment2DColor(1, textures[1], GL_TEXTURE_2D, 0, GLColor::green);
20596     verifyAttachment2DColor(2, textures[2], GL_TEXTURE_2D, 0, GLColor::blue);
20597     verifyAttachment2DColor(3, textures[3], GL_TEXTURE_2D, 0, GLColor::white);
20598 }
20599 
20600 // Fuzzer test involving struct samplers and comma operator
TEST_P(GLSLTest,StructSamplerVsComma)20601 TEST_P(GLSLTest, StructSamplerVsComma)
20602 {
20603     constexpr char kVS[] = R"(uniform struct S1
20604 {
20605     samplerCube ar;
20606     vec2 c;
20607 } a;
20608 
20609 struct S2
20610 {
20611     vec3 c;
20612 } b[2];
20613 
20614 void main (void)
20615 {
20616     ++b[0].c,a;
20617 })";
20618 
20619     GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
20620     EXPECT_NE(0u, shader);
20621     glDeleteShader(shader);
20622 }
20623 
20624 // Make sure there is no name look up clash when initializing output variables
TEST_P(GLSLTest_ES3_InitShaderVariables,NameLookup)20625 TEST_P(GLSLTest_ES3_InitShaderVariables, NameLookup)
20626 {
20627     constexpr char kFS[] = R"(#version 300 es
20628 out highp vec4 color;
20629 void main()
20630 {
20631     highp vec4 color;
20632     color.x = 1.0;
20633 }
20634 )";
20635     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
20636     drawQuad(program, essl3_shaders::PositionAttrib(), 0);
20637     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
20638     ASSERT_GL_NO_ERROR();
20639 }
20640 
20641 // Test that lowp and mediump varyings can be correctly matched between VS and FS.
TEST_P(GLSLTest,LowpMediumpVarying)20642 TEST_P(GLSLTest, LowpMediumpVarying)
20643 {
20644     const char kVS[] = R"(varying lowp float lowpVarying;
20645 attribute vec4 position;
20646 void main ()
20647 {
20648   lowpVarying = 1.;
20649   gl_Position = position;
20650 })";
20651 
20652     const char kFS[] = R"(varying mediump float lowpVarying;
20653 void main ()
20654 {
20655   gl_FragColor = vec4(lowpVarying, 0, 0, 1);
20656 })";
20657 
20658     ANGLE_GL_PROGRAM(program, kVS, kFS);
20659     drawQuad(program, "position", 0);
20660     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
20661 }
20662 
20663 // Test that a mismatched varying that is unused in fragshader compiles.
TEST_P(GLSLTest,MismatchedInactiveVarying)20664 TEST_P(GLSLTest, MismatchedInactiveVarying)
20665 {
20666     const char kVS[] = R"(precision mediump float;
20667 
20668 attribute vec2 a_position_0;
20669 attribute vec4 a_color_0;
20670 
20671 varying vec4 vertexColor;
20672 
20673 void main()
20674 {
20675     vertexColor = a_color_0;
20676     gl_Position = vec4(a_position_0, 0.0, 1.0);
20677 })";
20678 
20679     const char kFS[] = R"(precision highp float;
20680 
20681 uniform vec2 resolution;
20682 uniform vec2 fragOffset;
20683 uniform vec2 fragScale;
20684 
20685 varying vec4 vertexColor;
20686 varying vec2 texCoord;
20687 
20688 void main()
20689 {
20690     vec2 uv = (fragScale * gl_FragCoord.xy + fragOffset) / resolution;
20691     gl_FragColor = vec4(uv, 1.0, 1.0);
20692 })";
20693 
20694     ANGLE_GL_PROGRAM(program, kVS, kFS);
20695 }
20696 
20697 // Regression test for a bug where the sampler-in-struct rewrite transformation did not take a
20698 // specific pattern of side_effect,index_the_struct_to_write into account.
TEST_P(GLSLTest_ES3,StructWithSamplerRHSOfCommaWithSideEffect)20699 TEST_P(GLSLTest_ES3, StructWithSamplerRHSOfCommaWithSideEffect)
20700 {
20701     constexpr char kVS[] = R"(uniform struct S {
20702     sampler2D s;
20703     mat2 m;
20704 } u[2];
20705 void main()
20706 {
20707     ++gl_Position, u[0];
20708 })";
20709 
20710     GLuint shader = CompileShader(GL_VERTEX_SHADER, kVS);
20711     EXPECT_NE(0u, shader);
20712     glDeleteShader(shader);
20713 }
20714 }  // anonymous namespace
20715 
20716 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(
20717     GLSLTest,
20718     ES3_OPENGL().enable(Feature::ForceInitShaderVariables),
20719     ES3_OPENGL().enable(Feature::ScalarizeVecAndMatConstructorArgs),
20720     ES3_OPENGLES().enable(Feature::ScalarizeVecAndMatConstructorArgs),
20721     ES3_VULKAN().enable(Feature::AvoidOpSelectWithMismatchingRelaxedPrecision),
20722     ES3_VULKAN().enable(Feature::ForceInitShaderVariables),
20723     ES3_VULKAN().disable(Feature::SupportsSPIRV14),
20724     ES2_VULKAN().enable(Feature::VaryingsRequireMatchingPrecisionInSpirv));
20725 
20726 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(GLSLTestNoValidation);
20727 
20728 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLTest_ES3);
20729 ANGLE_INSTANTIATE_TEST_ES3_AND(
20730     GLSLTest_ES3,
20731     ES3_OPENGL().enable(Feature::ForceInitShaderVariables),
20732     ES3_OPENGL().enable(Feature::ScalarizeVecAndMatConstructorArgs),
20733     ES3_OPENGLES().enable(Feature::ScalarizeVecAndMatConstructorArgs),
20734     ES3_VULKAN().enable(Feature::AvoidOpSelectWithMismatchingRelaxedPrecision),
20735     ES3_VULKAN().enable(Feature::ForceInitShaderVariables),
20736     ES3_VULKAN().disable(Feature::SupportsSPIRV14));
20737 
20738 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLTestLoops);
20739 ANGLE_INSTANTIATE_TEST_ES3(GLSLTestLoops);
20740 
20741 ANGLE_INSTANTIATE_TEST_ES2(WebGLGLSLTest);
20742 
20743 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WebGL2GLSLTest);
20744 ANGLE_INSTANTIATE_TEST_ES3(WebGL2GLSLTest);
20745 
20746 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLTest_ES31);
20747 ANGLE_INSTANTIATE_TEST_ES31_AND(GLSLTest_ES31,
20748                                 ES31_VULKAN().enable(Feature::ForceInitShaderVariables),
20749                                 ES31_VULKAN().disable(Feature::SupportsSPIRV14));
20750 
20751 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLTest_ES3_InitShaderVariables);
20752 ANGLE_INSTANTIATE_TEST(
20753     GLSLTest_ES3_InitShaderVariables,
20754     ES3_VULKAN().enable(Feature::ForceInitShaderVariables),
20755     ES3_VULKAN().disable(Feature::SupportsSPIRV14).enable(Feature::ForceInitShaderVariables));
20756 
20757 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLSLTest_ES31_InitShaderVariables);
20758 ANGLE_INSTANTIATE_TEST(
20759     GLSLTest_ES31_InitShaderVariables,
20760     ES31_VULKAN().enable(Feature::ForceInitShaderVariables),
20761     ES31_VULKAN().disable(Feature::SupportsSPIRV14).enable(Feature::ForceInitShaderVariables));
20762